Refactor the temporary solution of the stubs.
Also, fix test 032 and 088.
Change-Id: I84049356b29ca6d9a5c852c926190de76b285780
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 434aa7b..74616d1 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -142,12 +142,9 @@
declare void @art_check_cast_from_code(%JavaObject*, %JavaObject*)
declare void @art_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
-declare void @art_ensure_link_from_code(%JavaObject*)
-
declare %JavaObject* @art_ensure_resolved_from_code(%JavaObject*,
%JavaObject*,
i32,
- i32)
+ i1)
-declare %JavaObject* @art_ensure_initialized_from_code(%JavaObject*,
- %JavaObject*)
+declare %JavaObject* @art_fix_stub_from_code(%JavaObject*)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 52048eb..6676e02 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -268,12 +268,19 @@
FuncTy_28_args.push_back(PointerTy_1);
FuncTy_28_args.push_back(PointerTy_1);
FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 32));
-FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 1));
FunctionType* FuncTy_28 = FunctionType::get(
/*Result=*/PointerTy_1,
/*Params=*/FuncTy_28_args,
/*isVarArg=*/false);
+std::vector<Type*>FuncTy_29_args;
+FuncTy_29_args.push_back(PointerTy_1);
+FunctionType* FuncTy_29 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_29_args,
+ /*isVarArg=*/false);
+
// Function Declarations
@@ -794,17 +801,6 @@
AttrListPtr func_art_check_put_array_element_from_code_PAL;
func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_array_element_from_code_PAL);
-Function* func_art_ensure_link_from_code = mod->getFunction("art_ensure_link_from_code");
-if (!func_art_ensure_link_from_code) {
-func_art_ensure_link_from_code = Function::Create(
- /*Type=*/FuncTy_4,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"art_ensure_link_from_code", mod); // (external, no body)
-func_art_ensure_link_from_code->setCallingConv(CallingConv::C);
-}
-AttrListPtr func_art_ensure_link_from_code_PAL;
-func_art_ensure_link_from_code->setAttributes(func_art_ensure_link_from_code_PAL);
-
Function* func_art_ensure_resolved_from_code = mod->getFunction("art_ensure_resolved_from_code");
if (!func_art_ensure_resolved_from_code) {
func_art_ensure_resolved_from_code = Function::Create(
@@ -816,16 +812,16 @@
AttrListPtr func_art_ensure_resolved_from_code_PAL;
func_art_ensure_resolved_from_code->setAttributes(func_art_ensure_resolved_from_code_PAL);
-Function* func_art_ensure_initialized_from_code = mod->getFunction("art_ensure_initialized_from_code");
-if (!func_art_ensure_initialized_from_code) {
-func_art_ensure_initialized_from_code = Function::Create(
- /*Type=*/FuncTy_25,
+Function* func_art_fix_stub_from_code = mod->getFunction("art_fix_stub_from_code");
+if (!func_art_fix_stub_from_code) {
+func_art_fix_stub_from_code = Function::Create(
+ /*Type=*/FuncTy_29,
/*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"art_ensure_initialized_from_code", mod); // (external, no body)
-func_art_ensure_initialized_from_code->setCallingConv(CallingConv::C);
+ /*Name=*/"art_fix_stub_from_code", mod); // (external, no body)
+func_art_fix_stub_from_code->setCallingConv(CallingConv::C);
}
-AttrListPtr func_art_ensure_initialized_from_code_PAL;
-func_art_ensure_initialized_from_code->setAttributes(func_art_ensure_initialized_from_code_PAL);
+AttrListPtr func_art_fix_stub_from_code_PAL;
+func_art_fix_stub_from_code->setAttributes(func_art_fix_stub_from_code_PAL);
// Global Variable Declarations
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index e0a5704..492ad25 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -39,6 +39,7 @@
namespace art {
namespace compiler_llvm {
+using namespace runtime_support;
JniCompiler::JniCompiler(CompilationUnit* cunit,
Compiler const& compiler,
@@ -106,8 +107,7 @@
}
// Get thread object
- llvm::Value* thread_object_addr =
- irb_.CreateCall(irb_.GetRuntime(runtime_support::GetCurrentThread));
+ llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
// Shadow stack
llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
@@ -132,7 +132,7 @@
// Push the shadow frame
llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
- irb_.CreateCall(irb_.GetRuntime(runtime_support::PushShadowFrame), shadow_frame_upcast);
+ irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
// Get JNIEnv
llvm::Value* jni_env_object_addr = LoadFromObjectOffset(thread_object_addr,
@@ -145,20 +145,10 @@
irb_.getInt32(kNative));
// Get callee code_addr
- llvm::Value* code_addr_ =
+ llvm::Value* code_addr =
LoadFromObjectOffset(method_object_addr,
Method::NativeMethodOffset().Int32Value(),
GetFunctionType(method_idx_, is_static, true)->getPointerTo());
- llvm::Value* code_addr;
- llvm::FunctionType* method_type = GetFunctionType(method_idx_, is_static, true);
-
- // TODO: Inline check
- llvm::Value* runtime_func = irb_.GetRuntime(runtime_support::EnsureInitialized);
- llvm::Value* result = irb_.CreateCall2(runtime_func,
- method_object_addr,
- irb_.CreatePointerCast(code_addr_,
- irb_.getJObjectTy()));
- code_addr = irb_.CreatePointerCast(result, method_type->getPointerTo());
// Load actual parameters
std::vector<llvm::Value*> args;
@@ -204,11 +194,10 @@
// Acquire lock for synchronized methods.
if (is_synchronized) {
// Acquire lock
- irb_.CreateCall(irb_.GetRuntime(runtime_support::LockObject), this_object_or_class_object);
+ irb_.CreateCall(irb_.GetRuntime(LockObject), this_object_or_class_object);
// Check exception pending
- llvm::Value* exception_pending =
- irb_.CreateCall(irb_.GetRuntime(runtime_support::IsExceptionPending));
+ llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
// Create two basic block for branch
llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "B.cont", func_);
@@ -222,7 +211,7 @@
irb_.SetInsertPoint(block_exception_);
// TODO: Set thread state?
// Pop the shadow frame
- irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
+ irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
// Unwind
if (return_shorty != 'V') {
irb_.CreateRet(irb_.getJZero(return_shorty));
@@ -256,7 +245,7 @@
// Release lock for synchronized methods.
if (is_synchronized) {
- irb_.CreateCall(irb_.GetRuntime(runtime_support::UnlockObject), this_object_or_class_object);
+ irb_.CreateCall(irb_.GetRuntime(UnlockObject), this_object_or_class_object);
}
// Set thread state to kRunnable
@@ -266,7 +255,7 @@
if (return_shorty == 'L') {
// If the return value is reference, it may point to SIRT, we should decode it.
- retval = irb_.CreateCall2(irb_.GetRuntime(runtime_support::DecodeJObjectInThread),
+ retval = irb_.CreateCall2(irb_.GetRuntime(DecodeJObjectInThread),
thread_object_addr,
retval);
}
@@ -286,7 +275,7 @@
saved_local_ref_cookie);
// Pop the shadow frame
- irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
+ irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
// Return!
if (return_shorty != 'V') {
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 615e600..5485ba6 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2782,38 +2782,27 @@
<< PrettyMethod(callee_method_idx, *dex_file_);
}
-llvm::Value* MethodCompiler::EmitEnsureInitialized(llvm::Value* callee_method_object_addr,
- uint32_t method_idx,
- bool is_static,
- llvm::Value* code_addr) {
- llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
-
- // TODO: Inline check
- llvm::Value* runtime_func = irb_.GetRuntime(EnsureInitialized);
- llvm::Value* result = irb_.CreateCall2(runtime_func,
- callee_method_object_addr,
- irb_.CreatePointerCast(code_addr,
- irb_.getJObjectTy()));
- return irb_.CreatePointerCast(result, method_type->getPointerTo());
-}
-
llvm::Value* MethodCompiler::EmitEnsureResolved(llvm::Value* callee,
llvm::Value* caller,
uint32_t dex_method_idx,
- Instruction::Code instr_code) {
- // TODO: Inline check
- llvm::Value* runtime_func = irb_.GetRuntime(EnsureResolved);
- return irb_.CreateCall4(runtime_func,
- callee,
- caller,
- irb_.getInt32(dex_method_idx),
- irb_.getInt32(instr_code));
+ bool is_virtual) {
+ // TODO: Remove this after we solve the trampoline related problems.
+ return irb_.CreateCall4(irb_.GetRuntime(EnsureResolved),
+ callee,
+ caller,
+ irb_.getInt32(dex_method_idx),
+ irb_.getInt1(is_virtual));
}
-void MethodCompiler::EmitEnsureLink(llvm::Value* method_object_addr) {
- // TODO: Inline check
- llvm::Value* runtime_func = irb_.GetRuntime(EnsureLink);
- irb_.CreateCall(runtime_func, method_object_addr);
+llvm::Value* MethodCompiler::EmitFixStub(llvm::Value* callee_method_object_addr,
+ uint32_t method_idx,
+ bool is_static) {
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ llvm::Value* code_addr = irb_.CreateCall(irb_.GetRuntime(FixStub), callee_method_object_addr);
+
+ llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
+
+ return irb_.CreatePointerCast(code_addr, method_type->getPointerTo());
}
void MethodCompiler::EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
@@ -2842,28 +2831,23 @@
EmitUpdateLineNumFromDexPC(dex_pc);
- llvm::Value* callee_method_object_addr_ =
+ llvm::Value* callee_method_object_addr =
irb_.CreateCall3(runtime_func,
callee_method_idx_value, this_addr, method_object_addr);
EmitGuard_ExceptionLandingPad(dex_pc);
- llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
- method_object_addr,
- callee_method_idx,
- (is_virtual ?
- Instruction::INVOKE_VIRTUAL :
- Instruction::INVOKE_SUPER));
-
- EmitEnsureLink(callee_method_object_addr);
-
- llvm::Value* code_addr_ =
+#if 0
+ llvm::Value* code_addr =
EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+#else
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+ callee_method_idx,
+ false);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
- llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
- callee_method_idx,
- false,
- code_addr_);
// Load the actual parameter
std::vector<llvm::Value*> args;
args.push_back(callee_method_object_addr);
@@ -2908,25 +2892,26 @@
// Load callee method code address (branch destination)
llvm::Value* vtable_addr = EmitLoadVTableAddr(class_object_addr);
- llvm::Value* method_object_addr_ =
+ llvm::Value* method_object_addr =
EmitLoadMethodObjectAddrFromVTable(vtable_addr,
callee_method->GetMethodIndex());
- llvm::Value* method_object_addr = EmitEnsureResolved(method_object_addr_,
- EmitLoadMethodObjectAddr(),
- callee_method_idx,
- Instruction::INVOKE_VIRTUAL);
+#if 0
+ llvm::Value* code_addr =
+ EmitLoadCodeAddr(method_object_addr, callee_method_idx, false);
+#else
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ method_object_addr = EmitEnsureResolved(method_object_addr,
+ EmitLoadMethodObjectAddr(),
+ callee_method_idx,
+ true);
+ EmitGuard_ExceptionLandingPad(dex_pc);
- EmitEnsureLink(method_object_addr);
-
- llvm::Value* code_addr_ =
- EmitLoadCodeAddr(method_object_addr, callee_method_idx, false);
-
- llvm::Value* code_addr = EmitEnsureInitialized(method_object_addr,
- callee_method_idx,
- false,
- code_addr_);
-
+ llvm::Value* code_addr = EmitFixStub(method_object_addr,
+ callee_method_idx,
+ false);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
// Load actual parameters
std::vector<llvm::Value*> args;
args.push_back(method_object_addr);
@@ -3009,25 +2994,26 @@
// Load method object from virtual table
llvm::Value* vtable_addr = EmitLoadVTableAddr(super_class_addr);
- llvm::Value* callee_method_object_addr_ =
+ llvm::Value* callee_method_object_addr =
EmitLoadMethodObjectAddrFromVTable(vtable_addr,
callee_method->GetMethodIndex());
- llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
- method_object_addr,
- callee_method_idx,
- Instruction::INVOKE_SUPER);
-
- EmitEnsureLink(callee_method_object_addr);
-
- llvm::Value* code_addr_ =
- EmitLoadCodeAddr(callee_method_object_addr,
- callee_method_idx, false);
-
- llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
+#if 0
+ llvm::Value* code_addr =
+ EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+#else
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr,
+ method_object_addr,
callee_method_idx,
- false,
- code_addr_);
+ true);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+
+ llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+ callee_method_idx,
+ false);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
// Load actual parameters
std::vector<llvm::Value*> args;
@@ -3087,24 +3073,26 @@
llvm::Value* callee_method_object_field_addr =
EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
- llvm::Value* callee_method_object_addr_ =
+ llvm::Value* callee_method_object_addr =
irb_.CreateLoad(callee_method_object_field_addr);
- llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
- EmitLoadMethodObjectAddr(),
- callee_method_idx,
- Instruction::INVOKE_DIRECT);
+#if 0
+ llvm::Value* code_addr =
+ EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, is_static);
+#else
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr,
+ EmitLoadMethodObjectAddr(),
+ callee_method_idx,
+ false);
+ EmitGuard_ExceptionLandingPad(dex_pc);
- EmitEnsureLink(callee_method_object_addr);
-
- llvm::Value* code_addr_ =
- EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, is_static);
-
- llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
- callee_method_idx,
- is_static,
- code_addr_);
- EmitGuard_ExceptionLandingPad(dex_pc);
+ llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+ callee_method_idx,
+ is_static);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+ // FixStub may resolve method, so we need to reload method.
+#endif
// Load the actual parameter
std::vector<llvm::Value*> args;
@@ -3156,26 +3144,22 @@
EmitUpdateLineNumFromDexPC(dex_pc);
- llvm::Value* callee_method_object_addr_ =
+ llvm::Value* callee_method_object_addr =
irb_.CreateCall3(runtime_func,
callee_method_idx_value, this_addr, method_object_addr);
EmitGuard_ExceptionLandingPad(dex_pc);
- llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
- method_object_addr,
- callee_method_idx,
- Instruction::INVOKE_INTERFACE);
-
- EmitEnsureLink(callee_method_object_addr);
-
- llvm::Value* code_addr_ =
+#if 0
+ llvm::Value* code_addr =
EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
-
- llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
- callee_method_idx,
- false,
- code_addr_);
+#else
+ // TODO: Remove this after we solve the link and trampoline related problems.
+ llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+ callee_method_idx,
+ false);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
// Load the actual parameter
std::vector<llvm::Value*> args;
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index e5be3ba..48d4467 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -194,15 +194,13 @@
void EmitInsn_SPut(GEN_INSN_ARGS, JType field_jty);
// INVOKE instructions
- llvm::Value* EmitEnsureInitialized(llvm::Value* callee_method_object_addr,
- uint32_t method_idx,
- bool is_static,
- llvm::Value* code_addr);
+ llvm::Value* EmitFixStub(llvm::Value* callee_method_object_addr,
+ uint32_t method_idx,
+ bool is_static);
llvm::Value* EmitEnsureResolved(llvm::Value* callee,
llvm::Value* caller,
uint32_t dex_method_idx,
- Instruction::Code instr_code);
- void EmitEnsureLink(llvm::Value*);
+ bool is_virtual);
void EmitInsn_InvokeVirtual(GEN_INSN_ARGS, bool is_range);
void EmitInsn_InvokeSuper(GEN_INSN_ARGS, bool is_range);
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 2f1fb13..56755fa 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -57,7 +57,6 @@
V(InitializeStaticStorage, art_initialize_static_storage_from_code) \
V(IsExceptionPending, art_is_exception_pending_from_code) \
V(FindCatchBlock, art_find_catch_block_from_code) \
- V(EnsureInitialized, art_ensure_initialized_from_code) \
- V(EnsureLink, art_ensure_link_from_code) \
V(EnsureResolved, art_ensure_resolved_from_code) \
+ V(FixStub, art_fix_stub_from_code) \
V(DecodeJObjectInThread, art_decode_jobject_in_thread)
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index e7e2d86..79d06df 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -521,92 +521,87 @@
}
}
-const void* art_ensure_initialized_from_code(Method* called,
- void* code) {
- if (LIKELY(code != Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
- return code;
- }
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- Class* called_class = called->GetDeclaringClass();
- linker->EnsureInitialized(called_class, true, true);
- if (LIKELY(called_class->IsInitialized())) {
- return called->GetCode();
- } else if (called_class->IsInitializing()) {
- return linker->GetOatCodeFor(called);
- } else {
- DCHECK(called_class->IsErroneous());
- return code;
- }
-}
-
+// TODO: This runtime support function is the temporary solution for the stubs. Because now the
+// stubs and runtime support functions in the LLVM part and the non-LLVM part is different.
+// After deal these problems, we should remove this function, and will save a function call before
+// every method invocation.
Method* art_ensure_resolved_from_code(Method* called,
Method* caller,
uint32_t dex_method_idx,
- Instruction::Code instr_code) {
+ bool is_virtual) {
if (LIKELY(!called->IsResolutionMethod())) {
return called;
}
- // Compute details about the called method (avoid GCs)
+
+ // If the called method is ResolutionMethod. -> ResolutionTrampoline(kUnknownMethod)
+ // Resolve method.
ClassLinker* linker = Runtime::Current()->GetClassLinker();
- bool is_static = (instr_code == Instruction::INVOKE_STATIC) ||
- (instr_code == Instruction::INVOKE_STATIC_RANGE);
-
- bool is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
- (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
- (instr_code == Instruction::INVOKE_SUPER) ||
- (instr_code == Instruction::INVOKE_SUPER_RANGE);
-
- DCHECK(is_static || is_virtual ||
- (instr_code == Instruction::INVOKE_DIRECT) ||
- (instr_code == Instruction::INVOKE_DIRECT_RANGE));
-
called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
+ if (UNLIKELY(Thread::Current()->IsExceptionPending())) {
+ return NULL;
+ }
+ if (LIKELY(called->IsDirect() == !is_virtual)) {
+ // Ensure that the called method's class is initialized.
+ Class* called_class = called->GetDeclaringClass();
+ linker->EnsureInitialized(called_class, true, true);
+ return called;
+ } else {
+ // Direct method has been made virtual
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+ "Expected direct method but found virtual: %s",
+ PrettyMethod(called, true).c_str());
+ return NULL;
+ }
+}
- const void* code = NULL;
- Thread* thread = art_get_current_thread_from_code();
- if (LIKELY(!thread->IsExceptionPending())) {
- if (LIKELY(called->IsDirect() == !is_virtual)) {
- // Ensure that the called method's class is initialized.
- Class* called_class = called->GetDeclaringClass();
- linker->EnsureInitialized(called_class, true, true);
- if (LIKELY(called_class->IsInitialized())) {
- code = called->GetCode();
- } else if (called_class->IsInitializing()) {
- if (is_static) {
- // Class is still initializing, go to oat and grab code (trampoline must be left in place
- // until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
- LOG(FATAL) << "Is static";
- } else {
- // No trampoline for non-static methods.
- code = called->GetCode();
- }
- } else {
- DCHECK(called_class->IsErroneous());
- LOG(FATAL) << "Is erroneous";
- }
+
+// TODO: This runtime support function is the temporary solution for the stubs. Because now the
+// stubs and runtime support functions in the LLVM part and the non-LLVM part is different.
+// After deal these problems, we should remove this function, and will save a function call before
+// every method invocation.
+// It calls to this function before invoking any function, and this function will check:
+// 1. The code address is ResolutionStub. -> ResolutionTrampoline(kStaticMethod)
+// Initialize class.
+// 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
+// 3. The code address is 0. -> Link the code by ELFLoader
+// The item 3 will solved by in-place linking at image loading.
+const void* art_fix_stub_from_code(Method* called) {
+ if (UNLIKELY(called->IsResolutionMethod())) {
+ LOG(FATAL) << "is ResolutionMethod!!";
+ }
+ Runtime* runtime = Runtime::Current();
+ const void* code = called->GetCode();
+
+ // 1. The code address is ResolutionStub. -> ResolutionTrampoline(kStaticMethod)
+ if (UNLIKELY(code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
+ ClassLinker* linker = runtime->GetClassLinker();
+ Class* called_class = called->GetDeclaringClass();
+ linker->EnsureInitialized(called_class, true, true);
+ if (LIKELY(called_class->IsInitialized())) {
+ return called->GetCode();
+ } else if (called_class->IsInitializing()) {
+ return linker->GetOatCodeFor(called);
} else {
- // Direct method has been made virtual
- thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
- "Expected direct method but found virtual: %s",
- PrettyMethod(called, true).c_str());
+ DCHECK(Thread::Current()->IsExceptionPending());
+ DCHECK(called_class->IsErroneous());
+ return NULL;
}
}
- if (code != NULL) {
- // Expect class to at least be initializing.
- DCHECK(called->GetDeclaringClass()->IsInitializing());
- // Don't want infinite recursion.
- DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
+ // 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
+ if (UNLIKELY(code == runtime->GetAbstractMethodErrorStubArray()->GetData())) {
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
+ "abstract method \"%s\"", PrettyMethod(called).c_str());
+ return NULL;
}
- return called;
-}
-
-void art_ensure_link_from_code(Method* method) {
- if (method->GetInvokeStub() == NULL || method->GetCode() == NULL) {
- Runtime::Current()->GetClassLinker()->LinkOatCodeFor(method);
+ // 3. The code address is 0. -> Link the code by ELFLoader
+ if (UNLIKELY(called->GetInvokeStub() == NULL || code == NULL)) {
+ runtime->GetClassLinker()->LinkOatCodeFor(called);
+ return called->GetCode();
}
+
+ return code;
}
void* art_find_runtime_support_func(void* context, char const* name) {
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index 1dbd71d..ab5c804 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -62,7 +62,7 @@
void* art_find_runtime_support_func(void* context, char const* name);
-void art_ensure_link_from_code(Method* method);
+const void* art_fix_stub_from_code(Method* called);
} // namespace art
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/upcall_compiler.cc
index 6d14a19..691d7e5 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/upcall_compiler.cc
@@ -144,6 +144,8 @@
}
// Invoke managed method now!
+ // TODO: If we solve the trampoline related problems, we can just get the code address and call.
+#if 0
llvm::Value* code_field_offset_value =
irb_.getPtrEquivInt(Method::GetCodeOffset().Int32Value());
@@ -151,15 +153,20 @@
irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
accurate_func_type->getPointerTo()->getPointerTo());
- llvm::Value* code_addr_ = irb_.CreateLoad(code_field_addr);
- llvm::Value* code_addr;
- // TODO: Inline check
- llvm::Value* runtime_func = irb_.GetRuntime(runtime_support::EnsureInitialized);
- llvm::Value* result = irb_.CreateCall2(runtime_func,
- method_object_addr,
- irb_.CreatePointerCast(code_addr_,
- irb_.getJObjectTy()));
- code_addr = irb_.CreatePointerCast(result, accurate_func_type->getPointerTo());
+ llvm::Value* code_addr = irb_.CreateLoad(code_field_addr);
+#else
+ llvm::Value* result = irb_.CreateCall(irb_.GetRuntime(FixStub), method_object_addr);
+ llvm::Value* code_addr = irb_.CreatePointerCast(result, accurate_func_type->getPointerTo());
+
+ // Exception unwind.
+ llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
+ llvm::BasicBlock* block_unwind = llvm::BasicBlock::Create(*context_, "exception_unwind", func);
+ llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "cont", func);
+ irb_.CreateCondBr(exception_pending, block_unwind, block_cont);
+ irb_.SetInsertPoint(block_unwind);
+ irb_.CreateRetVoid();
+ irb_.SetInsertPoint(block_cont);
+#endif
llvm::Value* retval = irb_.CreateCall(code_addr, args);