blob: 44d0c2d215bbc9fc886390abedfaa1dda51a9ace [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni_compiler.h"
18
19#include "base/logging.h"
20#include "class_linker.h"
21#include "compiled_method.h"
22#include "dex_file-inl.h"
23#include "driver/compiler_driver.h"
24#include "driver/dex_compilation_unit.h"
25#include "llvm/compiler_llvm.h"
26#include "llvm/ir_builder.h"
27#include "llvm/llvm_compilation_unit.h"
28#include "llvm/runtime_support_llvm_func.h"
29#include "llvm/utils_llvm.h"
30#include "mirror/abstract_method.h"
31#include "runtime.h"
32#include "stack.h"
33#include "thread.h"
34
35#include <llvm/ADT/SmallVector.h>
36#include <llvm/IR/BasicBlock.h>
37#include <llvm/IR/DerivedTypes.h>
38#include <llvm/IR/Function.h>
39#include <llvm/IR/Type.h>
40
41namespace art {
42namespace llvm {
43
44using namespace runtime_support;
45
46JniCompiler::JniCompiler(LlvmCompilationUnit* cunit,
47 const CompilerDriver& driver,
48 const DexCompilationUnit* dex_compilation_unit)
49: cunit_(cunit), driver_(&driver), module_(cunit_->GetModule()),
50 context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
51 dex_compilation_unit_(dex_compilation_unit),
52 func_(NULL), elf_func_idx_(0) {
53
54 // Check: Ensure that JNI compiler will only get "native" method
55 CHECK(dex_compilation_unit->IsNative());
56}
57
58
59CompiledMethod* JniCompiler::Compile() {
60 const bool is_static = dex_compilation_unit_->IsStatic();
61 const bool is_synchronized = dex_compilation_unit_->IsSynchronized();
62 const DexFile* dex_file = dex_compilation_unit_->GetDexFile();
63 DexFile::MethodId const& method_id =
64 dex_file->GetMethodId(dex_compilation_unit_->GetDexMethodIndex());
65 char const return_shorty = dex_file->GetMethodShorty(method_id)[0];
66 ::llvm::Value* this_object_or_class_object;
67
68 uint32_t method_idx = dex_compilation_unit_->GetDexMethodIndex();
69 std::string func_name(StringPrintf("jni_%s",
70 MangleForJni(PrettyMethod(method_idx, *dex_file)).c_str()));
71 CreateFunction(func_name);
72
73 // Set argument name
74 ::llvm::Function::arg_iterator arg_begin(func_->arg_begin());
75 ::llvm::Function::arg_iterator arg_end(func_->arg_end());
76 ::llvm::Function::arg_iterator arg_iter(arg_begin);
77
78 DCHECK_NE(arg_iter, arg_end);
79 arg_iter->setName("method");
80 ::llvm::Value* method_object_addr = arg_iter++;
81
82 if (!is_static) {
83 // Non-static, the second argument is "this object"
84 this_object_or_class_object = arg_iter++;
85 } else {
86 // Load class object
87 this_object_or_class_object =
88 irb_.LoadFromObjectOffset(method_object_addr,
89 mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
90 irb_.getJObjectTy(),
91 kTBAAConstJObject);
92 }
93 // Actual argument (ignore method and this object)
94 arg_begin = arg_iter;
95
96 // Count the number of Object* arguments
97 uint32_t sirt_size = 1;
98 // "this" object pointer for non-static
99 // "class" object pointer for static
100 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
101#if !defined(NDEBUG)
102 arg_iter->setName(StringPrintf("a%u", i));
103#endif
104 if (arg_iter->getType() == irb_.getJObjectTy()) {
105 ++sirt_size;
106 }
107 }
108
109 // Shadow stack
110 ::llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
111 ::llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
112
113 // Store the dex pc
114 irb_.StoreToObjectOffset(shadow_frame_,
115 ShadowFrame::DexPCOffset(),
116 irb_.getInt32(DexFile::kDexNoIndex),
117 kTBAAShadowFrame);
118
119 // Push the shadow frame
120 ::llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
121 ::llvm::Value* old_shadow_frame =
122 irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr, sirt_size);
123
124 // Get JNIEnv
125 ::llvm::Value* jni_env_object_addr =
126 irb_.Runtime().EmitLoadFromThreadOffset(Thread::JniEnvOffset().Int32Value(),
127 irb_.getJObjectTy(),
128 kTBAARuntimeInfo);
129
130 // Get callee code_addr
131 ::llvm::Value* code_addr =
132 irb_.LoadFromObjectOffset(method_object_addr,
133 mirror::AbstractMethod::NativeMethodOffset().Int32Value(),
134 GetFunctionType(dex_compilation_unit_->GetDexMethodIndex(),
135 is_static, true)->getPointerTo(),
136 kTBAARuntimeInfo);
137
138 // Load actual parameters
139 std::vector< ::llvm::Value*> args;
140
141 // The 1st parameter: JNIEnv*
142 args.push_back(jni_env_object_addr);
143
144 // Variables for GetElementPtr
145 ::llvm::Value* gep_index[] = {
146 irb_.getInt32(0), // No displacement for shadow frame pointer
147 irb_.getInt32(1), // SIRT
148 NULL,
149 };
150
151 size_t sirt_member_index = 0;
152
153 // Store the "this object or class object" to SIRT
154 gep_index[2] = irb_.getInt32(sirt_member_index++);
155 ::llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
156 irb_.getJObjectTy()->getPointerTo());
157 irb_.CreateStore(this_object_or_class_object, sirt_field_addr, kTBAAShadowFrame);
158 // Push the "this object or class object" to out args
159 this_object_or_class_object = irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy());
160 args.push_back(this_object_or_class_object);
161 // Store arguments to SIRT, and push back to args
162 for (arg_iter = arg_begin; arg_iter != arg_end; ++arg_iter) {
163 if (arg_iter->getType() == irb_.getJObjectTy()) {
164 // Store the reference type arguments to SIRT
165 gep_index[2] = irb_.getInt32(sirt_member_index++);
166 ::llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
167 irb_.getJObjectTy()->getPointerTo());
168 irb_.CreateStore(arg_iter, sirt_field_addr, kTBAAShadowFrame);
169 // Note null is placed in the SIRT but the jobject passed to the native code must be null
170 // (not a pointer into the SIRT as with regular references).
171 ::llvm::Value* equal_null = irb_.CreateICmpEQ(arg_iter, irb_.getJNull());
172 ::llvm::Value* arg =
173 irb_.CreateSelect(equal_null,
174 irb_.getJNull(),
175 irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
176 args.push_back(arg);
177 } else {
178 args.push_back(arg_iter);
179 }
180 }
181
182 ::llvm::Value* saved_local_ref_cookie;
183 { // JniMethodStart
184 RuntimeId func_id = is_synchronized ? JniMethodStartSynchronized
185 : JniMethodStart;
186 ::llvm::SmallVector< ::llvm::Value*, 2> args;
187 if (is_synchronized) {
188 args.push_back(this_object_or_class_object);
189 }
190 args.push_back(irb_.Runtime().EmitGetCurrentThread());
191 saved_local_ref_cookie =
192 irb_.CreateCall(irb_.GetRuntime(func_id), args);
193 }
194
195 // Call!!!
196 ::llvm::Value* retval = irb_.CreateCall(code_addr, args);
197
198 { // JniMethodEnd
199 bool is_return_ref = return_shorty == 'L';
200 RuntimeId func_id =
201 is_return_ref ? (is_synchronized ? JniMethodEndWithReferenceSynchronized
202 : JniMethodEndWithReference)
203 : (is_synchronized ? JniMethodEndSynchronized
204 : JniMethodEnd);
205 ::llvm::SmallVector< ::llvm::Value*, 4> args;
206 if (is_return_ref) {
207 args.push_back(retval);
208 }
209 args.push_back(saved_local_ref_cookie);
210 if (is_synchronized) {
211 args.push_back(this_object_or_class_object);
212 }
213 args.push_back(irb_.Runtime().EmitGetCurrentThread());
214
215 ::llvm::Value* decoded_jobject =
216 irb_.CreateCall(irb_.GetRuntime(func_id), args);
217
218 // Return decoded jobject if return reference.
219 if (is_return_ref) {
220 retval = decoded_jobject;
221 }
222 }
223
224 // Pop the shadow frame
225 irb_.Runtime().EmitPopShadowFrame(old_shadow_frame);
226
227 // Return!
228 if (return_shorty != 'V') {
229 irb_.CreateRet(retval);
230 } else {
231 irb_.CreateRetVoid();
232 }
233
234 // Verify the generated bitcode
235 VERIFY_LLVM_FUNCTION(*func_);
236
237 cunit_->Materialize();
238
239 return new CompiledMethod(cunit_->GetInstructionSet(),
240 cunit_->GetElfObject(),
241 func_name);
242}
243
244
245void JniCompiler::CreateFunction(const std::string& func_name) {
246 CHECK_NE(0U, func_name.size());
247
248 const bool is_static = dex_compilation_unit_->IsStatic();
249
250 // Get function type
251 ::llvm::FunctionType* func_type =
252 GetFunctionType(dex_compilation_unit_->GetDexMethodIndex(), is_static, false);
253
254 // Create function
255 func_ = ::llvm::Function::Create(func_type, ::llvm::Function::InternalLinkage,
256 func_name, module_);
257
258 // Create basic block
259 ::llvm::BasicBlock* basic_block = ::llvm::BasicBlock::Create(*context_, "B0", func_);
260
261 // Set insert point
262 irb_.SetInsertPoint(basic_block);
263}
264
265
266::llvm::FunctionType* JniCompiler::GetFunctionType(uint32_t method_idx,
267 bool is_static, bool is_native_function) {
268 // Get method signature
269 uint32_t shorty_size;
270 const char* shorty = dex_compilation_unit_->GetShorty(&shorty_size);
271 CHECK_GE(shorty_size, 1u);
272
273 // Get return type
274 ::llvm::Type* ret_type = irb_.getJType(shorty[0]);
275
276 // Get argument type
277 std::vector< ::llvm::Type*> args_type;
278
279 args_type.push_back(irb_.getJObjectTy()); // method object pointer
280
281 if (!is_static || is_native_function) {
282 // "this" object pointer for non-static
283 // "class" object pointer for static naitve
284 args_type.push_back(irb_.getJType('L'));
285 }
286
287 for (uint32_t i = 1; i < shorty_size; ++i) {
288 args_type.push_back(irb_.getJType(shorty[i]));
289 }
290
291 return ::llvm::FunctionType::get(ret_type, args_type, false);
292}
293
294} // namespace llvm
295} // namespace art