Add object-space related runtime support.
Change-Id: Ieac2be41efcb57923de6f1dedad94fab0803812d
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 274d575..39fbec7 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -84,7 +84,9 @@
declare void @art_find_instance_field_from_code(i32, %JavaObject*)
declare void @art_find_static_field_from_code(i32, %JavaObject*)
-declare %JavaObject* @art_find_interface_method_from_code(i32, %JavaObject*)
+declare %JavaObject* @art_find_interface_method_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_find_virtual_method_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_find_super_method_from_code(i32, %JavaObject*, %JavaObject*)
declare %JavaObject* @art_initialize_static_storage_from_code(i32, %JavaObject*)
declare %JavaObject* @art_initialize_type_from_code(i32, %JavaObject*)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 22a12fa..dedc392 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -526,7 +526,7 @@
Function* func_art_find_interface_method_from_code = mod->getFunction("art_find_interface_method_from_code");
if (!func_art_find_interface_method_from_code) {
func_art_find_interface_method_from_code = Function::Create(
- /*Type=*/FuncTy_11,
+ /*Type=*/FuncTy_24,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"art_find_interface_method_from_code", mod); // (external, no body)
func_art_find_interface_method_from_code->setCallingConv(CallingConv::C);
@@ -534,6 +534,28 @@
AttrListPtr func_art_find_interface_method_from_code_PAL;
func_art_find_interface_method_from_code->setAttributes(func_art_find_interface_method_from_code_PAL);
+Function* func_art_find_virtual_method_from_code = mod->getFunction("art_find_virtual_method_from_code");
+if (!func_art_find_virtual_method_from_code) {
+func_art_find_virtual_method_from_code = Function::Create(
+ /*Type=*/FuncTy_24,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_find_virtual_method_from_code", mod); // (external, no body)
+func_art_find_virtual_method_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_find_virtual_method_from_code_PAL;
+func_art_find_virtual_method_from_code->setAttributes(func_art_find_virtual_method_from_code_PAL);
+
+Function* func_art_find_super_method_from_code = mod->getFunction("art_find_super_method_from_code");
+if (!func_art_find_super_method_from_code) {
+func_art_find_super_method_from_code = Function::Create(
+ /*Type=*/FuncTy_24,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_find_super_method_from_code", mod); // (external, no body)
+func_art_find_super_method_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_find_super_method_from_code_PAL;
+func_art_find_super_method_from_code->setAttributes(func_art_find_super_method_from_code_PAL);
+
Function* func_art_initialize_static_storage_from_code = mod->getFunction("art_initialize_static_storage_from_code");
if (!func_art_initialize_static_storage_from_code) {
func_art_initialize_static_storage_from_code = Function::Create(
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index c1c9e19..18e157e 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2716,6 +2716,58 @@
}
+void MethodCompiler::EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
+ DecodedInstruction &dec_insn,
+ bool is_range,
+ uint32_t callee_method_idx,
+ bool is_virtual) {
+ // Callee method can't be resolved at compile time. Emit the runtime
+ // method resolution code.
+
+ // Test: Is "this" pointer equal to null?
+ llvm::Value* this_addr = EmitLoadCalleeThis(dec_insn, is_range);
+ EmitGuard_NullPointerException(dex_pc, this_addr);
+
+ // Resolve the callee method object address at runtime
+ llvm::Value* runtime_func;
+ if (is_virtual) {
+ runtime_func = irb_.GetRuntime(FindVirtualMethod);
+ } else {
+ runtime_func = irb_.GetRuntime(FindSuperMethod);
+ }
+
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
+
+ EmitUpdateLineNumFromDexPC(dex_pc);
+
+ 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* code_addr =
+ EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+ // Load the actual parameter
+ std::vector<llvm::Value*> args;
+ args.push_back(callee_method_object_addr);
+ args.push_back(this_addr);
+ EmitLoadActualParameters(args, callee_method_idx, dec_insn, is_range, false);
+
+ // Invoke callee
+ EmitUpdateLineNumFromDexPC(dex_pc);
+ llvm::Value* retval = irb_.CreateCall(code_addr, args);
+ EmitGuard_ExceptionLandingPad(dex_pc);
+
+ UniquePtr<OatCompilationUnit>
+ callee(oat_compilation_unit_->GetCallee(callee_method_idx, /* access flags */ 0));
+ char ret_shorty = callee->GetShorty()[0];
+ if (ret_shorty != 'V') {
+ EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
+ }
+}
void MethodCompiler::EmitInsn_InvokeVirtual(uint32_t dex_pc,
Instruction const* insn,
@@ -2729,12 +2781,8 @@
Method* callee_method = ResolveMethod(callee_method_idx);
if (callee_method == NULL) {
- // Callee method can't be resolved at compile time. Emit the runtime
- // method resolution code.
-
- UNIMPLEMENTED(FATAL) << "Method index " << callee_method_idx
- << " can't be resolved";
-
+ EmitInsn_InvokeVirtualSuperSlow(dex_pc, dec_insn, is_range,
+ callee_method_idx, /*is_virtual*/ true);
} else {
// Test: Is *this* parameter equal to null?
llvm::Value* this_addr = EmitLoadCalleeThis(dec_insn, is_range);
@@ -2788,12 +2836,8 @@
Method* callee_overiding_method = ResolveMethod(callee_method_idx);
if (callee_overiding_method == NULL) {
- // Callee method can't be resolved at compile time. Emit the runtime
- // method resolution code.
-
- UNIMPLEMENTED(FATAL) << "Method index " << callee_method_idx
- << " can't be resolved";
-
+ EmitInsn_InvokeVirtualSuperSlow(dex_pc, dec_insn, is_range,
+ callee_method_idx, /*is_virtual*/ false);
} else {
// CHECK: Is the instruction well-encoded or is the class hierarchy correct?
Class* declaring_class = method_->GetDeclaringClass();
@@ -2960,7 +3004,8 @@
EmitUpdateLineNumFromDexPC(dex_pc);
llvm::Value* callee_method_object_addr =
- irb_.CreateCall2(runtime_func, callee_method_idx_value, method_object_addr);
+ irb_.CreateCall3(runtime_func,
+ callee_method_idx_value, this_addr, method_object_addr);
EmitGuard_ExceptionLandingPad(dex_pc);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index c9e03a4..782b934 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -192,6 +192,11 @@
// INVOKE instructions
void EmitInsn_InvokeVirtual(GEN_INSN_ARGS, bool is_range);
void EmitInsn_InvokeSuper(GEN_INSN_ARGS, bool is_range);
+ void EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
+ DecodedInstruction &dec_insn,
+ bool is_range,
+ uint32_t callee_method_idx,
+ bool is_virtual);
void EmitInsn_InvokeStaticDirect(GEN_INSN_ARGS,
InvokeType invoke_type,
bool is_range);
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index a98dd15..0170148 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -36,8 +36,9 @@
V(AllocArrayWithAccessCheck, art_alloc_array_from_code_with_access_check) \
V(CheckAndAllocArray, art_check_and_alloc_array_from_code) \
V(CheckAndAllocArrayWithAccessCheck, art_check_and_alloc_array_from_code_with_access_check) \
- V(FindInstanceField, art_find_instance_field_from_code) \
- V(FindStaticField, art_find_static_field_from_code) \
+ V(FindInterfaceMethod, art_find_interface_method_from_code) \
+ V(FindVirtualMethod, art_find_virtual_method_from_code) \
+ V(FindSuperMethod, art_find_super_method_from_code) \
V(ResolveString, art_resolve_string_from_code) \
V(Set32Static, art_set32_static_from_code) \
V(Set64Static, art_set64_static_from_code) \
@@ -53,5 +54,4 @@
V(GetObjectInstance, art_get_obj_instance_from_code) \
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(FindInterfaceMethod, art_find_interface_method_from_code)
+ V(FindCatchBlock, art_find_catch_block_from_code)
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 300376b..16f9704 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -174,160 +174,124 @@
// Object Space
//----------------------------------------------------------------------------
-Object* art_alloc_object_from_code(uint32_t type_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_alloc_object_from_code(uint32_t type_idx, Method* referrer) {
+ return AllocObjectFromCode(type_idx, referrer, Thread::Current(), false);
}
-Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx,
- Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, Method* referrer) {
+ return AllocObjectFromCode(type_idx, referrer, Thread::Current(), true);
}
-Object* art_alloc_array_from_code(uint32_t type_idx,
- Object* referrer,
- uint32_t length) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_alloc_array_from_code(uint32_t type_idx, Method* referrer, uint32_t length) {
+ return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
}
Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
- Object* referrer,
+ Method* referrer,
uint32_t length) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+ return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
}
Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
- Object* referrer,
+ Method* referrer,
uint32_t length) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+ return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
}
Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
- Object* referrer,
+ Method* referrer,
uint32_t length) {
- UNIMPLEMENTED(WARNING);
- return NULL;
-}
-
-void art_find_instance_field_from_code(uint32_t field_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
-}
-
-void art_find_static_field_from_code(uint32_t field_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
+ return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
}
Object* art_find_interface_method_from_code(uint32_t method_idx,
- Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+ Object* this_object,
+ Method* referrer) {
+ return _artInvokeCommon(method_idx, this_object, referrer,
+ Thread::Current(), NULL, true, kInterface);
}
-Object* art_initialize_static_storage_from_code(uint32_t type_idx,
- Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_find_virtual_method_from_code(uint32_t method_idx,
+ Object* this_object,
+ Method* referrer) {
+ return _artInvokeCommon(method_idx, this_object, referrer,
+ Thread::Current(), NULL, true, kVirtual);
}
-Object* art_initialize_type_from_code(uint32_t type_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_find_super_method_from_code(uint32_t method_idx,
+ Object* this_object,
+ Method* referrer) {
+ return _artInvokeCommon(method_idx, this_object, referrer,
+ Thread::Current(), NULL, true, kSuper);
}
-Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx,
- Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_initialize_static_storage_from_code(uint32_t type_idx, Method* referrer) {
+ return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), true, true);
}
-Object* art_resolve_string_from_code(Object* referrer, uint32_t string_idx) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+Object* art_initialize_type_from_code(uint32_t type_idx, Method* referrer) {
+ return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, false);
}
-int32_t art_set32_static_from_code(uint32_t field_idx,
- Object* referrer,
- int32_t new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, Method* referrer) {
+ // Called when caller isn't guaranteed to have access to a type and the dex cache may be
+ // unpopulated
+ return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, true);
}
-int32_t art_set64_static_from_code(uint32_t field_idx,
- Object* referrer,
- int64_t new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+Object* art_resolve_string_from_code(Method* referrer, uint32_t string_idx) {
+ return ResolveStringFromCode(referrer, string_idx);
}
-int32_t art_set_obj_static_from_code(uint32_t field_idx,
- Object* referrer,
- Object* new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+int32_t art_set32_static_from_code(uint32_t field_idx, Method* referrer, int32_t new_value) {
+ return artSet32StaticFromCode(field_idx, new_value, referrer, Thread::Current(), NULL);
}
-int32_t art_get32_static_from_code(uint32_t field_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return 0;
+int32_t art_set64_static_from_code(uint32_t field_idx, Method* referrer, int64_t new_value) {
+ return artSet64StaticFromCode(field_idx, referrer, new_value, Thread::Current(), NULL);
}
-int64_t art_get64_static_from_code(uint32_t field_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return 0;
+int32_t art_set_obj_static_from_code(uint32_t field_idx, Method* referrer, Object* new_value) {
+ return artSetObjStaticFromCode(field_idx, new_value, referrer, Thread::Current(), NULL);
}
-Object* art_get_obj_static_from_code(uint32_t field_idx, Object* referrer) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+int32_t art_get32_static_from_code(uint32_t field_idx, Method* referrer) {
+ return artGet32StaticFromCode(field_idx, referrer, Thread::Current(), NULL);
}
-int32_t art_set32_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object,
- uint32_t new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+int64_t art_get64_static_from_code(uint32_t field_idx, Method* referrer) {
+ return artGet64StaticFromCode(field_idx, referrer, Thread::Current(), NULL);
}
-int32_t art_set64_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object,
- int64_t new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
+ return artGetObjStaticFromCode(field_idx, referrer, Thread::Current(), NULL);
}
-int32_t art_set_obj_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object,
- Object* new_value) {
- UNIMPLEMENTED(WARNING);
- return -1;
+int32_t art_set32_instance_from_code(uint32_t field_idx, Method* referrer,
+ Object* obj, uint32_t new_value) {
+ return artSet32InstanceFromCode(field_idx, obj, new_value, referrer, Thread::Current(), NULL);
}
-int32_t art_get32_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object) {
- UNIMPLEMENTED(WARNING);
- return 0;
+int32_t art_set64_instance_from_code(uint32_t field_idx, Method* referrer,
+ Object* obj, int64_t new_value) {
+ return artSet64InstanceFromCode(field_idx, obj, new_value, referrer, Thread::Current(), NULL);
}
-int64_t art_get64_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object) {
- UNIMPLEMENTED(WARNING);
- return 0;
+int32_t art_set_obj_instance_from_code(uint32_t field_idx, Method* referrer,
+ Object* obj, Object* new_value) {
+ return artSetObjInstanceFromCode(field_idx, obj, new_value, referrer, Thread::Current(), NULL);
}
-Object* art_get_obj_instance_from_code(uint32_t field_idx,
- Object* referrer,
- Object* object) {
- UNIMPLEMENTED(WARNING);
- return NULL;
+int32_t art_get32_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
+ return artGet32InstanceFromCode(field_idx, obj, referrer, Thread::Current(), NULL);
+}
+
+int64_t art_get64_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
+ return artGet64InstanceFromCode(field_idx, obj, referrer, Thread::Current(), NULL);
+}
+
+Object* art_get_obj_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
+ return artGetObjInstanceFromCode(field_idx, obj, referrer, Thread::Current(), NULL);
}