blob: ad730dcc81de1d5ca148c317bfc6e47156f222f1 [file] [log] [blame]
Logan Chien88894ee2012-02-13 16:42:22 +08001/*
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 "class_linker.h"
Logan Chien8b977d32012-02-21 19:14:55 +080020#include "compilation_unit.h"
Logan Chien88894ee2012-02-13 16:42:22 +080021#include "compiled_method.h"
22#include "compiler.h"
23#include "compiler_llvm.h"
24#include "ir_builder.h"
25#include "logging.h"
26#include "oat_compilation_unit.h"
27#include "object.h"
28#include "runtime.h"
TDYa12728f1a142012-03-15 21:51:52 -070029#include "runtime_support_func.h"
Logan Chien88894ee2012-02-13 16:42:22 +080030#include "utils_llvm.h"
31
TDYa12728f1a142012-03-15 21:51:52 -070032#include <llvm/Analysis/Verifier.h>
33#include <llvm/BasicBlock.h>
Logan Chien88894ee2012-02-13 16:42:22 +080034#include <llvm/DerivedTypes.h>
35#include <llvm/Function.h>
36#include <llvm/Type.h>
37
38namespace art {
39namespace compiler_llvm {
40
41
Logan Chien8b977d32012-02-21 19:14:55 +080042JniCompiler::JniCompiler(CompilationUnit* cunit,
Logan Chien88894ee2012-02-13 16:42:22 +080043 Compiler const& compiler,
44 OatCompilationUnit* oat_compilation_unit)
Logan Chien8b977d32012-02-21 19:14:55 +080045: cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
46 context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
Logan Chien88894ee2012-02-13 16:42:22 +080047 oat_compilation_unit_(oat_compilation_unit),
48 access_flags_(oat_compilation_unit->access_flags_),
49 method_idx_(oat_compilation_unit->method_idx_),
50 class_linker_(oat_compilation_unit->class_linker_),
51 class_loader_(oat_compilation_unit->class_loader_),
52 dex_cache_(oat_compilation_unit->dex_cache_),
53 dex_file_(oat_compilation_unit->dex_file_),
54 method_(dex_cache_->GetResolvedMethod(method_idx_)) {
55
56 // Check: Ensure that the method is resolved
57 CHECK_NE(method_, static_cast<art::Method*>(NULL));
58
59 // Check: Ensure that JNI compiler will only get "native" method
60 CHECK((access_flags_ & kAccNative) != 0);
61}
62
63
64CompiledMethod* JniCompiler::Compile() {
TDYa12728f1a142012-03-15 21:51:52 -070065 bool is_static = method_->IsStatic();
66
Logan Chien88894ee2012-02-13 16:42:22 +080067 CreateFunction();
68
TDYa12728f1a142012-03-15 21:51:52 -070069 // Set argument name
70 llvm::Function::arg_iterator arg_begin(func_->arg_begin());
71 llvm::Function::arg_iterator arg_end(func_->arg_end());
72 llvm::Function::arg_iterator arg_iter(arg_begin);
73
74 DCHECK_NE(arg_iter, arg_end);
75 arg_iter->setName("method");
76 llvm::Value* method_object_addr = arg_iter++;
77
78 // Actual argument (ignore method)
79 arg_begin = arg_iter;
80
81 // Count the number of Object* arguments
82 uint32_t sirt_size = (is_static ? 1 : 0); // Class object for static function
83 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
84 arg_iter->setName(StringPrintf("a%u", i));
85 if (arg_iter->getType() == irb_.getJObjectTy()) {
86 ++sirt_size;
87 }
88 }
89
90 // Start to build IR
91 irb_.SetInsertPoint(basic_block_);
92
93 llvm::Value* thread_object_addr =
94 irb_.CreateCall(irb_.GetRuntime(runtime_support::GetCurrentThread));
95
96 // Shadow stack
97 llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
98 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
99
100 // Zero-initialization of the shadow frame
101 llvm::ConstantAggregateZero* zero_initializer =
102 llvm::ConstantAggregateZero::get(shadow_frame_type);
103
104 irb_.CreateStore(zero_initializer, shadow_frame_);
105
106 // Variables for GetElementPtr
107 llvm::Constant* zero = irb_.getInt32(0);
108 llvm::Value* gep_index[] = {
109 zero, // No displacement for shadow frame pointer
110 zero, // Get the %ArtFrame data structure
111 NULL,
112 };
113
114 // Store the method pointer
115 gep_index[2] = irb_.getInt32(2);
116 llvm::Value* method_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
117 irb_.CreateStore(method_object_addr, method_field_addr);
118
119 // Store the number of the pointer slots
120 gep_index[2] = irb_.getInt32(0);
121 llvm::Value* size_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
122 llvm::ConstantInt* sirt_size_value = irb_.getInt32(sirt_size);
123 irb_.CreateStore(sirt_size_value, size_field_addr);
124
125 // Push the shadow frame
126 llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
127 irb_.CreateCall(irb_.GetRuntime(runtime_support::PushShadowFrame), shadow_frame_upcast);
128
129 // Set top of managed stack to the method field in the SIRT
130 StoreToObjectOffset(thread_object_addr, Thread::TopOfManagedStackOffset().Int32Value(),
131 method_field_addr->getType(), method_field_addr);
132
133 // Get JNIEnv
134 llvm::Value* jni_env_object_addr = LoadFromObjectOffset(thread_object_addr,
135 Thread::JniEnvOffset().Int32Value(),
136 irb_.getJObjectTy());
137
138 // Set thread state to kNative
139 StoreToObjectOffset(thread_object_addr, Thread::StateOffset().Int32Value(),
140 irb_.getInt32Ty(), irb_.getInt32(Thread::kNative));
141
142 // Get callee code_addr
143 llvm::Value* code_addr =
144 LoadFromObjectOffset(method_object_addr,
145 Method::NativeMethodOffset().Int32Value(),
146 GetFunctionType(method_idx_, is_static, true)->getPointerTo());
147
148
149 // Load actual parameters
150 std::vector<llvm::Value*> args;
151
152 args.push_back(jni_env_object_addr);
153 //args.push_back(method_object_addr); // method object for callee
154
155 // Store arguments to SIRT, and push back to args
156 gep_index[1] = irb_.getInt32(1); // SIRT
157 size_t sirt_member_index = 0;
158
159 // Push class argument if this method is static
160 if (is_static) {
161 llvm::Value* class_object_addr =
162 LoadFromObjectOffset(method_object_addr,
163 Method::DeclaringClassOffset().Int32Value(),
164 irb_.getJObjectTy());
165 gep_index[2] = irb_.getInt32(sirt_member_index++);
166 llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
167 irb_.CreateStore(class_object_addr, sirt_field_addr);
168 args.push_back(irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
169 }
170 for (arg_iter = arg_begin; arg_iter != arg_end; ++arg_iter) {
171 if (arg_iter->getType() == irb_.getJObjectTy()) {
172 gep_index[2] = irb_.getInt32(sirt_member_index++);
173 llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
174 irb_.CreateStore(arg_iter, sirt_field_addr);
175 // Note null is placed in the SIRT but the jobject passed to the native code must be null
176 // (not a pointer into the SIRT as with regular references).
177 llvm::Value* equal_null = irb_.CreateICmpEQ(arg_iter, irb_.getJNull());
178 llvm::Value* arg =
179 irb_.CreateSelect(equal_null,
180 irb_.getJNull(),
181 irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
182 args.push_back(arg);
183 } else {
184 args.push_back(arg_iter);
185 }
186 }
187
188
189 // saved_local_ref_cookie = env->local_ref_cookie
190 llvm::Value* saved_local_ref_cookie =
191 LoadFromObjectOffset(jni_env_object_addr,
192 JNIEnvExt::LocalRefCookieOffset().Int32Value(),
193 irb_.getInt32Ty());
194
195 // env->local_ref_cookie = env->locals.segment_state
196 llvm::Value* segment_state =
197 LoadFromObjectOffset(jni_env_object_addr,
198 JNIEnvExt::SegmentStateOffset().Int32Value(),
199 irb_.getInt32Ty());
200 StoreToObjectOffset(jni_env_object_addr,
201 JNIEnvExt::LocalRefCookieOffset().Int32Value(),
202 irb_.getInt32Ty(),
203 segment_state);
204
205
206 // Call!!!
207 llvm::Value* retval = irb_.CreateCall(code_addr, args);
208
209
210 // Set thread state to kRunnable
211 StoreToObjectOffset(thread_object_addr, Thread::StateOffset().Int32Value(),
212 irb_.getInt32Ty(), irb_.getInt32(Thread::kRunnable));
213
214 // Get return shorty
215 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx_);
216 uint32_t shorty_size;
217 char ret_shorty = dex_file_->GetMethodShorty(method_id, &shorty_size)[0];
218 CHECK_GE(shorty_size, 1u);
219
220 if (ret_shorty == 'L') {
221 // If the return value is reference, it may point to SIRT, we should decode it.
222 retval = irb_.CreateCall2(irb_.GetRuntime(runtime_support::DecodeJObjectInThread),
223 thread_object_addr, retval);
224 }
225
226 // env->locals.segment_state = env->local_ref_cookie
227 llvm::Value* local_ref_cookie =
228 LoadFromObjectOffset(jni_env_object_addr,
229 JNIEnvExt::LocalRefCookieOffset().Int32Value(),
230 irb_.getInt32Ty());
231 StoreToObjectOffset(jni_env_object_addr,
232 JNIEnvExt::SegmentStateOffset().Int32Value(),
233 irb_.getInt32Ty(),
234 local_ref_cookie);
235
236 // env->local_ref_cookie = saved_local_ref_cookie
237 StoreToObjectOffset(jni_env_object_addr, JNIEnvExt::LocalRefCookieOffset().Int32Value(),
238 irb_.getInt32Ty(), saved_local_ref_cookie);
239
240 // Pop the shadow frame
241 irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
242
243 // Return!
244 if (ret_shorty != 'V') {
245 irb_.CreateRet(retval);
246 } else {
247 irb_.CreateRetVoid();
248 }
249
250 // For debug
251 //func_->dump();
252
253 // Verify the generated bitcode
254 llvm::verifyFunction(*func_, llvm::PrintMessageAction);
255
Logan Chien6920bce2012-03-17 21:44:01 +0800256 return new CompiledMethod(cunit_->GetInstructionSet(),
257 cunit_->GetElfIndex());
Logan Chien88894ee2012-02-13 16:42:22 +0800258}
259
260
261void JniCompiler::CreateFunction() {
262 // LLVM function name
263 std::string func_name(LLVMLongName(method_));
264
265 // Get function type
266 llvm::FunctionType* func_type =
TDYa12728f1a142012-03-15 21:51:52 -0700267 GetFunctionType(method_idx_, method_->IsStatic(), false);
Logan Chien88894ee2012-02-13 16:42:22 +0800268
269 // Create function
270 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
271 func_name, module_);
TDYa12728f1a142012-03-15 21:51:52 -0700272
273 // Create basic block
274 basic_block_ = llvm::BasicBlock::Create(*context_, "B0", func_);
Logan Chien88894ee2012-02-13 16:42:22 +0800275}
276
277
278llvm::FunctionType* JniCompiler::GetFunctionType(uint32_t method_idx,
TDYa12728f1a142012-03-15 21:51:52 -0700279 bool is_static, bool is_target_function) {
Logan Chien88894ee2012-02-13 16:42:22 +0800280 // Get method signature
281 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
282
283 uint32_t shorty_size;
284 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
285 CHECK_GE(shorty_size, 1u);
286
287 // Get return type
288 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
289
290 // Get argument type
291 std::vector<llvm::Type*> args_type;
292
293 args_type.push_back(irb_.getJObjectTy()); // method object pointer
294
TDYa12728f1a142012-03-15 21:51:52 -0700295 if (!is_static || is_target_function) {
296 // "this" object pointer for non-static
297 // "class" object pointer for static
298 args_type.push_back(irb_.getJType('L', kAccurate));
Logan Chien88894ee2012-02-13 16:42:22 +0800299 }
300
301 for (uint32_t i = 1; i < shorty_size; ++i) {
302 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
303 }
304
305 return llvm::FunctionType::get(ret_type, args_type, false);
306}
307
TDYa12728f1a142012-03-15 21:51:52 -0700308llvm::Value* JniCompiler::LoadFromObjectOffset(llvm::Value* object_addr, int32_t offset,
309 llvm::Type* type) {
310 // Convert offset to llvm::value
311 llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
312 // Calculate the value's address
313 llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
314 // Load
315 return irb_.CreateLoad(value_addr);
316}
317
318void JniCompiler::StoreToObjectOffset(llvm::Value* object_addr, int32_t offset,
319 llvm::Type* type, llvm::Value* value) {
320 // Convert offset to llvm::value
321 llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
322 // Calculate the value's address
323 llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
324 // Store
325 irb_.CreateStore(value, value_addr);
326}
Logan Chien88894ee2012-02-13 16:42:22 +0800327
328} // namespace compiler_llvm
329} // namespace art