summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/Android.mk3
-rw-r--r--compiler/dex/quick/arm/call_arm.cc6
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h6
-rw-r--r--compiler/dex/quick/arm/int_arm.cc6
-rw-r--r--compiler/dex/quick/arm/target_arm.cc4
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc2
-rw-r--r--compiler/dex/quick/gen_common.cc96
-rw-r--r--compiler/dex/quick/gen_invoke.cc67
-rw-r--r--compiler/dex/quick/mips/call_mips.cc6
-rw-r--r--compiler/dex/quick/mips/codegen_mips.h6
-rw-r--r--compiler/dex/quick/mips/fp_mips.cc2
-rw-r--r--compiler/dex/quick/mips/int_mips.cc4
-rw-r--r--compiler/dex/quick/mips/target_mips.cc4
-rw-r--r--compiler/dex/quick/mips/utility_mips.cc2
-rw-r--r--compiler/dex/quick/mir_to_lir.h44
-rw-r--r--compiler/dex/quick/x86/call_x86.cc8
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h8
-rw-r--r--compiler/dex/quick/x86/int_x86.cc12
-rw-r--r--compiler/dex/quick/x86/target_x86.cc2
-rw-r--r--compiler/dex/quick/x86/utility_x86.cc4
-rw-r--r--compiler/driver/compiler_driver.cc78
-rw-r--r--compiler/driver/compiler_driver.h23
-rw-r--r--compiler/image_writer.cc107
-rw-r--r--compiler/image_writer.h11
-rw-r--r--compiler/jni/quick/jni_compiler.cc6
-rw-r--r--compiler/oat_writer.cc128
-rw-r--r--compiler/oat_writer.h16
-rw-r--r--compiler/stubs/portable/stubs.cc138
-rw-r--r--compiler/stubs/quick/stubs.cc263
-rw-r--r--compiler/stubs/stubs.h59
-rw-r--r--compiler/utils/arm/assembler_arm.cc10
-rw-r--r--compiler/utils/mips/assembler_mips.cc33
-rw-r--r--runtime/Android.mk7
-rw-r--r--runtime/arch/arm/asm_support_arm.S7
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc193
-rw-r--r--runtime/arch/arm/jni_entrypoints_arm.S7
-rw-r--r--runtime/arch/arm/portable_entrypoints_arm.S3
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S183
-rw-r--r--runtime/arch/mips/asm_support_mips.S8
-rw-r--r--runtime/arch/mips/entrypoints_init_mips.cc192
-rw-r--r--runtime/arch/mips/jni_entrypoints_mips.S4
-rw-r--r--runtime/arch/mips/portable_entrypoints_mips.S12
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S186
-rw-r--r--runtime/arch/x86/asm_support_x86.S12
-rw-r--r--runtime/arch/x86/entrypoints_init_x86.cc246
-rw-r--r--runtime/arch/x86/portable_entrypoints_x86.S19
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S209
-rw-r--r--runtime/class_linker.cc99
-rw-r--r--runtime/class_linker.h20
-rw-r--r--runtime/common_test.h11
-rw-r--r--runtime/entrypoints/entrypoint_utils.h71
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc43
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.h47
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.cc87
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.h37
-rw-r--r--runtime/entrypoints/portable/portable_entrypoints.h8
-rw-r--r--runtime/entrypoints/quick/quick_argument_visitor.h138
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints.h74
-rw-r--r--runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_interpreter_entrypoints.cc128
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc74
-rw-r--r--runtime/entrypoints/quick/quick_proxy_entrypoints.cc126
-rw-r--r--runtime/entrypoints/quick/quick_stub_entrypoints.cc295
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc558
-rw-r--r--runtime/instrumentation.cc26
-rw-r--r--runtime/interpreter/interpreter.cc16
-rw-r--r--runtime/interpreter/interpreter.h6
-rw-r--r--runtime/jni_internal.h4
-rw-r--r--runtime/mirror/abstract_method-inl.h4
-rw-r--r--runtime/mirror/abstract_method.cc7
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc7
-rw-r--r--runtime/oat.cc112
-rw-r--r--runtime/oat.h33
-rw-r--r--runtime/oat_test.cc2
-rw-r--r--runtime/object_utils.h4
-rw-r--r--runtime/stack.cc2
-rw-r--r--runtime/thread.cc82
-rw-r--r--runtime/thread.h30
78 files changed, 2129 insertions, 2476 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 82103f8..417fe6d 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -74,8 +74,7 @@ LIBART_COMPILER_SRC_FILES := \
llvm/runtime_support_builder_arm.cc \
llvm/runtime_support_builder_thumb2.cc \
llvm/runtime_support_builder_x86.cc \
- stubs/portable/stubs.cc \
- stubs/quick/stubs.cc \
+ trampolines/trampoline_compiler.cc \
utils/arm/assembler_arm.cc \
utils/arm/managed_register_arm.cc \
utils/assembler.cc \
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 745e43d..2d8e24f 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -432,7 +432,7 @@ void ArmMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) {
// Making a call - use explicit registers
FlushAllRegs(); /* Everything to home location */
LoadValueDirectFixed(rl_src, r0);
- LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode),
+ LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData).Int32Value(),
rARM_LR);
// Materialize a pointer to the fill data image
NewLIR3(kThumb2Adr, r1, 0, reinterpret_cast<uintptr_t>(tab_rec));
@@ -488,7 +488,7 @@ void ArmMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
OpRegImm(kOpCmp, r1, 0);
OpIT(kCondNe, "T");
// Go expensive route - artLockObjectFromCode(self, obj);
- LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObjectFromCode), rARM_LR);
+ LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pLockObject).Int32Value(), rARM_LR);
ClobberCalleeSave();
LIR* call_inst = OpReg(kOpBlx, rARM_LR);
MarkSafepointPC(call_inst);
@@ -519,7 +519,7 @@ void ArmMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
OpIT(kCondEq, "EE");
StoreWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r3);
// Go expensive route - UnlockObjectFromCode(obj);
- LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR);
+ LoadWordDisp(rARM_SELF, QUICK_ENTRYPOINT_OFFSET(pUnlockObject).Int32Value(), rARM_LR);
ClobberCalleeSave();
LIR* call_inst = OpReg(kOpBlx, rARM_LR);
MarkSafepointPC(call_inst);
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 1599941..f1ccfa0 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -28,7 +28,7 @@ class ArmMir2Lir : public Mir2Lir {
// Required for target - codegen helpers.
bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src,
RegLocation rl_dest, int lit);
- int LoadHelper(int offset);
+ int LoadHelper(ThreadOffset offset);
LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
int s_reg);
@@ -153,12 +153,12 @@ class ArmMir2Lir : public Mir2Lir {
LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
LIR* OpTestSuspend(LIR* target);
- LIR* OpThreadMem(OpKind op, int thread_offset);
+ LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
LIR* OpVldm(int rBase, int count);
LIR* OpVstm(int rBase, int count);
void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
- void OpTlsCmp(int offset, int val);
+ void OpTlsCmp(ThreadOffset offset, int val);
RegLocation ArgLoc(RegLocation loc);
LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 9db1016..c258019 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -498,7 +498,7 @@ void ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
LOG(FATAL) << "Unexpected use of OpLea for Arm";
}
-void ArmMir2Lir::OpTlsCmp(int offset, int val) {
+void ArmMir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
}
@@ -665,7 +665,7 @@ void ArmMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1,
*/
RegLocation rl_result;
if (BadOverlap(rl_src1, rl_dest) || (BadOverlap(rl_src2, rl_dest))) {
- int func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
+ ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
FlushAllRegs();
CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
rl_result = GetReturnWide(false);
@@ -956,7 +956,7 @@ void ArmMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array,
// Get the array's class.
LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class);
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value,
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElement), r_value,
r_array_class, true);
// Redo LoadValues in case they didn't survive the call.
LoadValueDirectFixed(rl_array, r_array); // Reload array
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index 6f37798..47d3d97 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -714,8 +714,8 @@ void ArmMir2Lir::FreeCallTemps() {
FreeTemp(r3);
}
-int ArmMir2Lir::LoadHelper(int offset) {
- LoadWordDisp(rARM_SELF, offset, rARM_LR);
+int ArmMir2Lir::LoadHelper(ThreadOffset offset) {
+ LoadWordDisp(rARM_SELF, offset.Int32Value(), rARM_LR);
return rARM_LR;
}
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index afc8a66..c63de69 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -1029,7 +1029,7 @@ LIR* ArmMir2Lir::OpFpRegCopy(int r_dest, int r_src) {
return res;
}
-LIR* ArmMir2Lir::OpThreadMem(OpKind op, int thread_offset) {
+LIR* ArmMir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
return NULL;
}
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index ebe10bb..298d389 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -208,12 +208,12 @@ void Mir2Lir::GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest,
void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest,
RegLocation rl_src) {
FlushAllRegs(); /* Everything to home location */
- int func_offset;
+ ThreadOffset func_offset(-1);
if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
type_idx)) {
- func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocArrayFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocArray);
} else {
- func_offset= QUICK_ENTRYPOINT_OFFSET(pAllocArrayFromCodeWithAccessCheck);
+ func_offset= QUICK_ENTRYPOINT_OFFSET(pAllocArrayWithAccessCheck);
}
CallRuntimeHelperImmMethodRegLocation(func_offset, type_idx, rl_src, true);
RegLocation rl_result = GetReturn(false);
@@ -230,12 +230,12 @@ void Mir2Lir::GenFilledNewArray(CallInfo* info) {
int elems = info->num_arg_words;
int type_idx = info->index;
FlushAllRegs(); /* Everything to home location */
- int func_offset;
+ ThreadOffset func_offset(-1);
if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
type_idx)) {
- func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArray);
} else {
- func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCodeWithAccessCheck);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArrayWithAccessCheck);
}
CallRuntimeHelperImmMethodImm(func_offset, type_idx, elems, true);
FreeTemp(TargetReg(kArg2));
@@ -408,9 +408,10 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do
FreeTemp(rBase);
} else {
FlushAllRegs(); // Everything to home locations
- int setter_offset = is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Static) :
- (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjStatic)
- : QUICK_ENTRYPOINT_OFFSET(pSet32Static));
+ ThreadOffset setter_offset =
+ is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Static)
+ : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjStatic)
+ : QUICK_ENTRYPOINT_OFFSET(pSet32Static));
CallRuntimeHelperImmRegLocation(setter_offset, field_idx, rl_src, true);
}
}
@@ -483,9 +484,10 @@ void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
}
} else {
FlushAllRegs(); // Everything to home locations
- int getterOffset = is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Static) :
- (is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjStatic)
- : QUICK_ENTRYPOINT_OFFSET(pGet32Static));
+ ThreadOffset getterOffset =
+ is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Static)
+ :(is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjStatic)
+ : QUICK_ENTRYPOINT_OFFSET(pGet32Static));
CallRuntimeHelperImm(getterOffset, field_idx, true);
if (is_long_or_double) {
RegLocation rl_result = GetReturnWide(rl_dest.fp);
@@ -499,7 +501,7 @@ void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
void Mir2Lir::HandleSuspendLaunchPads() {
int num_elems = suspend_launchpads_.Size();
- int helper_offset = QUICK_ENTRYPOINT_OFFSET(pTestSuspendFromCode);
+ ThreadOffset helper_offset = QUICK_ENTRYPOINT_OFFSET(pTestSuspend);
for (int i = 0; i < num_elems; i++) {
ResetRegPool();
ResetDefTracking();
@@ -539,13 +541,13 @@ void Mir2Lir::HandleThrowLaunchPads() {
LIR* lab = throw_launchpads_.Get(i);
current_dalvik_offset_ = lab->operands[1];
AppendLIR(lab);
- int func_offset = 0;
+ ThreadOffset func_offset(-1);
int v1 = lab->operands[2];
int v2 = lab->operands[3];
bool target_x86 = (cu_->instruction_set == kX86);
switch (lab->operands[0]) {
case kThrowNullPointer:
- func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowNullPointerFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowNullPointer);
break;
case kThrowConstantArrayBounds: // v1 is length reg (for Arm/Mips), v2 constant index
// v1 holds the constant array index. Mips/Arm uses v2 for length, x86 reloads.
@@ -557,7 +559,7 @@ void Mir2Lir::HandleThrowLaunchPads() {
// Make sure the following LoadConstant doesn't mess with kArg1.
LockTemp(TargetReg(kArg1));
LoadConstant(TargetReg(kArg0), v2);
- func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBounds);
break;
case kThrowArrayBounds:
// Move v1 (array index) to kArg0 and v2 (array length) to kArg1
@@ -590,18 +592,18 @@ void Mir2Lir::HandleThrowLaunchPads() {
OpRegCopy(TargetReg(kArg0), v1);
}
}
- func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBounds);
break;
case kThrowDivZero:
- func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowDivZeroFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowDivZero);
break;
case kThrowNoSuchMethod:
OpRegCopy(TargetReg(kArg0), v1);
func_offset =
- QUICK_ENTRYPOINT_OFFSET(pThrowNoSuchMethodFromCode);
+ QUICK_ENTRYPOINT_OFFSET(pThrowNoSuchMethod);
break;
case kThrowStackOverflow:
- func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflowFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow);
// Restore stack alignment
if (target_x86) {
OpRegImm(kOpAdd, TargetReg(kSp), frame_size_);
@@ -664,9 +666,10 @@ void Mir2Lir::GenIGet(uint32_t field_idx, int opt_flags, OpSize size,
StoreValue(rl_dest, rl_result);
}
} else {
- int getterOffset = is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Instance) :
- (is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjInstance)
- : QUICK_ENTRYPOINT_OFFSET(pGet32Instance));
+ ThreadOffset getterOffset =
+ is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Instance)
+ : (is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjInstance)
+ : QUICK_ENTRYPOINT_OFFSET(pGet32Instance));
CallRuntimeHelperImmRegLocation(getterOffset, field_idx, rl_obj, true);
if (is_long_or_double) {
RegLocation rl_result = GetReturnWide(rl_dest.fp);
@@ -719,9 +722,10 @@ void Mir2Lir::GenIPut(uint32_t field_idx, int opt_flags, OpSize size,
}
}
} else {
- int setter_offset = is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Instance) :
- (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjInstance)
- : QUICK_ENTRYPOINT_OFFSET(pSet32Instance));
+ ThreadOffset setter_offset =
+ is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Instance)
+ : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjInstance)
+ : QUICK_ENTRYPOINT_OFFSET(pSet32Instance));
CallRuntimeHelperImmRegLocationRegLocation(setter_offset, field_idx, rl_obj, rl_src, true);
}
}
@@ -735,7 +739,7 @@ void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
type_idx)) {
// Call out to helper which resolves type and verifies access.
// Resolved type returned in kRet0.
- CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+ CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
type_idx, rl_method.low_reg, true);
RegLocation rl_result = GetReturn(false);
StoreValue(rl_dest, rl_result);
@@ -764,7 +768,7 @@ void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
// TUNING: move slow path to end & remove unconditional branch
LIR* target1 = NewLIR0(kPseudoTargetLabel);
// Call out to helper, which will return resolved type in kArg0
- CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx,
+ CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx,
rl_method.low_reg, true);
RegLocation rl_result = GetReturn(false);
StoreValue(rl_dest, rl_result);
@@ -797,7 +801,7 @@ void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
LoadWordDisp(TargetReg(kArg2),
mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0));
// Might call out to helper, which will return resolved string in kRet0
- int r_tgt = CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveStringFromCode));
+ int r_tgt = CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveString));
LoadWordDisp(TargetReg(kArg0), offset_of_string, TargetReg(kRet0));
LoadConstant(TargetReg(kArg1), string_idx);
if (cu_->instruction_set == kThumb2) {
@@ -821,7 +825,7 @@ void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
branch->target = target;
} else {
DCHECK_EQ(cu_->instruction_set, kX86);
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pResolveStringFromCode), TargetReg(kArg2),
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pResolveString), TargetReg(kArg2),
TargetReg(kArg1), true);
}
GenBarrier();
@@ -845,12 +849,12 @@ void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) {
FlushAllRegs(); /* Everything to home location */
// alloc will always check for resolution, do we also need to verify
// access because the verifier was unable to?
- int func_offset;
+ ThreadOffset func_offset(-1);
if (cu_->compiler_driver->CanAccessInstantiableTypeWithoutChecks(
cu_->method_idx, *cu_->dex_file, type_idx)) {
- func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectFromCode);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObject);
} else {
- func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectFromCodeWithAccessCheck);
+ func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectWithAccessCheck);
}
CallRuntimeHelperImmMethod(func_offset, type_idx, true);
RegLocation rl_result = GetReturn(false);
@@ -929,7 +933,7 @@ void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_know
if (needs_access_check) {
// Check we have access to type_idx and if not throw IllegalAccessError,
// returns Class* in kArg0
- CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
type_idx, true);
OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path
LoadValueDirectFixed(rl_src, TargetReg(kArg0)); // kArg0 <= ref
@@ -951,7 +955,7 @@ void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_know
LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL);
// Not resolved
// Call out to helper, which will return resolved type in kRet0
- CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, true);
+ CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx, true);
OpRegCopy(TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path
LoadValueDirectFixed(rl_src, TargetReg(kArg0)); /* reload Ref */
// Rejoin code paths
@@ -986,7 +990,7 @@ void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_know
}
} else {
if (cu_->instruction_set == kThumb2) {
- int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
+ int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
if (!type_known_abstract) {
/* Uses conditional nullification */
OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2)); // Same?
@@ -1003,13 +1007,13 @@ void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_know
branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
}
if (cu_->instruction_set != kX86) {
- int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
+ int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
OpRegCopy(TargetReg(kArg0), TargetReg(kArg2)); // .ne case - arg0 <= class
OpReg(kOpBlx, r_tgt); // .ne case: helper(class, ref->class)
FreeTemp(r_tgt);
} else {
OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
- OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
+ OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
}
}
}
@@ -1069,7 +1073,7 @@ void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_
// Check we have access to type_idx and if not throw IllegalAccessError,
// returns Class* in kRet0
// InitializeTypeAndVerifyAccess(idx, method)
- CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
+ CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
type_idx, TargetReg(kArg1), true);
OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path
} else if (use_declaring_class) {
@@ -1089,7 +1093,7 @@ void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_
// Not resolved
// Call out to helper, which will return resolved type in kArg0
// InitializeTypeFromCode(idx, method)
- CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx,
+ CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx,
TargetReg(kArg1), true);
OpRegCopy(class_reg, TargetReg(kRet0)); // Align usage with fast path
// Rejoin code paths
@@ -1109,7 +1113,7 @@ void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_
if (!type_known_abstract) {
branch2 = OpCmpBranch(kCondEq, TargetReg(kArg1), class_reg, NULL);
}
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCheckCastFromCode), TargetReg(kArg1),
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCheckCast), TargetReg(kArg1),
TargetReg(kArg2), true);
/* branch target here */
LIR* target = NewLIR0(kPseudoTargetLabel);
@@ -1168,7 +1172,7 @@ void Mir2Lir::GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_des
void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src1, RegLocation rl_shift) {
- int func_offset = -1; // Make gcc happy
+ ThreadOffset func_offset(-1);
switch (opcode) {
case Instruction::SHL_LONG:
@@ -1303,7 +1307,7 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
}
rl_result = GenDivRem(rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv);
} else {
- int func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
+ ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
FlushAllRegs(); /* Send everything to home location */
LoadValueDirectFixed(rl_src2, TargetReg(kArg1));
int r_tgt = CallHelperSetup(func_offset);
@@ -1558,7 +1562,7 @@ void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, Re
FlushAllRegs(); /* Everything to home location */
LoadValueDirectFixed(rl_src, TargetReg(kArg0));
Clobber(TargetReg(kArg0));
- int func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
+ ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
CallRuntimeHelperRegImm(func_offset, TargetReg(kArg0), lit, false);
if (is_div)
rl_result = GetReturn(false);
@@ -1589,7 +1593,7 @@ void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
OpKind second_op = kOpBkpt;
bool call_out = false;
bool check_zero = false;
- int func_offset;
+ ThreadOffset func_offset(-1);
int ret_reg = TargetReg(kRet0);
switch (opcode) {
@@ -1709,7 +1713,7 @@ void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
}
}
-void Mir2Lir::GenConversionCall(int func_offset,
+void Mir2Lir::GenConversionCall(ThreadOffset func_offset,
RegLocation rl_dest, RegLocation rl_src) {
/*
* Don't optimize the register usage since it calls out to support
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 1b34e99..20d683a 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -37,12 +37,12 @@ namespace art {
* has a memory call operation, part 1 is a NOP for x86. For other targets,
* load arguments between the two parts.
*/
-int Mir2Lir::CallHelperSetup(int helper_offset) {
+int Mir2Lir::CallHelperSetup(ThreadOffset helper_offset) {
return (cu_->instruction_set == kX86) ? 0 : LoadHelper(helper_offset);
}
/* NOTE: if r_tgt is a temp, it will be freed following use */
-LIR* Mir2Lir::CallHelper(int r_tgt, int helper_offset, bool safepoint_pc) {
+LIR* Mir2Lir::CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc) {
LIR* call_inst;
if (cu_->instruction_set == kX86) {
call_inst = OpThreadMem(kOpBlx, helper_offset);
@@ -56,21 +56,22 @@ LIR* Mir2Lir::CallHelper(int r_tgt, int helper_offset, bool safepoint_pc) {
return call_inst;
}
-void Mir2Lir::CallRuntimeHelperImm(int helper_offset, int arg0, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperImm(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadConstant(TargetReg(kArg0), arg0);
ClobberCalleeSave();
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperReg(int helper_offset, int arg0, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperReg(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
OpRegCopy(TargetReg(kArg0), arg0);
ClobberCalleeSave();
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegLocation(int helper_offset, RegLocation arg0, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperRegLocation(ThreadOffset helper_offset, RegLocation arg0,
+ bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
if (arg0.wide == 0) {
LoadValueDirectFixed(arg0, TargetReg(kArg0));
@@ -81,7 +82,7 @@ void Mir2Lir::CallRuntimeHelperRegLocation(int helper_offset, RegLocation arg0,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmImm(int helper_offset, int arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperImmImm(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadConstant(TargetReg(kArg0), arg0);
@@ -90,7 +91,7 @@ void Mir2Lir::CallRuntimeHelperImmImm(int helper_offset, int arg0, int arg1,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmRegLocation(int helper_offset, int arg0,
+void Mir2Lir::CallRuntimeHelperImmRegLocation(ThreadOffset helper_offset, int arg0,
RegLocation arg1, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
if (arg1.wide == 0) {
@@ -103,7 +104,7 @@ void Mir2Lir::CallRuntimeHelperImmRegLocation(int helper_offset, int arg0,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegLocationImm(int helper_offset, RegLocation arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperRegLocationImm(ThreadOffset helper_offset, RegLocation arg0, int arg1,
bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadValueDirectFixed(arg0, TargetReg(kArg0));
@@ -112,7 +113,7 @@ void Mir2Lir::CallRuntimeHelperRegLocationImm(int helper_offset, RegLocation arg
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmReg(int helper_offset, int arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
OpRegCopy(TargetReg(kArg1), arg1);
@@ -121,8 +122,8 @@ void Mir2Lir::CallRuntimeHelperImmReg(int helper_offset, int arg0, int arg1,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegImm(int helper_offset, int arg0, int arg1,
- bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperRegImm(ThreadOffset helper_offset, int arg0, int arg1,
+ bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
OpRegCopy(TargetReg(kArg0), arg0);
LoadConstant(TargetReg(kArg1), arg1);
@@ -130,7 +131,7 @@ void Mir2Lir::CallRuntimeHelperRegImm(int helper_offset, int arg0, int arg1,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmMethod(int helper_offset, int arg0, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperImmMethod(ThreadOffset helper_offset, int arg0, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadCurrMethodDirect(TargetReg(kArg1));
LoadConstant(TargetReg(kArg0), arg0);
@@ -138,7 +139,7 @@ void Mir2Lir::CallRuntimeHelperImmMethod(int helper_offset, int arg0, bool safep
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(int helper_offset, RegLocation arg0,
+void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(ThreadOffset helper_offset, RegLocation arg0,
RegLocation arg1, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
if (arg0.wide == 0) {
@@ -168,7 +169,8 @@ void Mir2Lir::CallRuntimeHelperRegLocationRegLocation(int helper_offset, RegLoca
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegReg(int helper_offset, int arg0, int arg1, bool safepoint_pc) {
+void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset helper_offset, int arg0, int arg1,
+ bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
DCHECK_NE(TargetReg(kArg0), arg1); // check copy into arg0 won't clobber arg1
OpRegCopy(TargetReg(kArg0), arg0);
@@ -177,7 +179,7 @@ void Mir2Lir::CallRuntimeHelperRegReg(int helper_offset, int arg0, int arg1, boo
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperRegRegImm(int helper_offset, int arg0, int arg1,
+void Mir2Lir::CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, int arg0, int arg1,
int arg2, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
DCHECK_NE(TargetReg(kArg0), arg1); // check copy into arg0 won't clobber arg1
@@ -188,7 +190,7 @@ void Mir2Lir::CallRuntimeHelperRegRegImm(int helper_offset, int arg0, int arg1,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmMethodRegLocation(int helper_offset,
+void Mir2Lir::CallRuntimeHelperImmMethodRegLocation(ThreadOffset helper_offset,
int arg0, RegLocation arg2, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadValueDirectFixed(arg2, TargetReg(kArg2));
@@ -198,7 +200,7 @@ void Mir2Lir::CallRuntimeHelperImmMethodRegLocation(int helper_offset,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmMethodImm(int helper_offset, int arg0,
+void Mir2Lir::CallRuntimeHelperImmMethodImm(ThreadOffset helper_offset, int arg0,
int arg2, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
LoadCurrMethodDirect(TargetReg(kArg1));
@@ -208,7 +210,7 @@ void Mir2Lir::CallRuntimeHelperImmMethodImm(int helper_offset, int arg0,
CallHelper(r_tgt, helper_offset, safepoint_pc);
}
-void Mir2Lir::CallRuntimeHelperImmRegLocationRegLocation(int helper_offset,
+void Mir2Lir::CallRuntimeHelperImmRegLocationRegLocation(ThreadOffset helper_offset,
int arg0, RegLocation arg1,
RegLocation arg2, bool safepoint_pc) {
int r_tgt = CallHelperSetup(helper_offset);
@@ -470,14 +472,14 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
// Disable sharpening
direct_method = 0;
}
- int trampoline = (cu->instruction_set == kX86) ? 0
- : QUICK_ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline);
if (direct_method != 0) {
switch (state) {
case 0: // Load the trampoline target [sets kInvokeTgt].
if (cu->instruction_set != kX86) {
- cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
+ cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline.Int32Value(),
+ cg->TargetReg(kInvokeTgt));
}
// Get the interface Method* [sets kArg0]
if (direct_method != static_cast<unsigned int>(-1)) {
@@ -506,7 +508,8 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
cg->LoadCurrMethodDirect(cg->TargetReg(kArg0));
// Load the trampoline target [sets kInvokeTgt].
if (cu->instruction_set != kX86) {
- cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
+ cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline.Int32Value(),
+ cg->TargetReg(kInvokeTgt));
}
break;
case 1: // Get method->dex_cache_resolved_methods_ [set/use kArg0]
@@ -528,7 +531,7 @@ static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
return state + 1;
}
-static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, int trampoline,
+static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, ThreadOffset trampoline,
int state, const MethodReference& target_method,
uint32_t method_idx) {
Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
@@ -539,7 +542,7 @@ static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, int trampoline,
if (state == 0) {
if (cu->instruction_set != kX86) {
// Load trampoline target
- cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
+ cg->LoadWordDisp(cg->TargetReg(kSelf), trampoline.Int32Value(), cg->TargetReg(kInvokeTgt));
}
// Load kArg0 with method index
CHECK_EQ(cu->dex_file, target_method.dex_file);
@@ -555,7 +558,7 @@ static int NextStaticCallInsnSP(CompilationUnit* cu, CallInfo* info,
uint32_t method_idx,
uintptr_t unused, uintptr_t unused2,
InvokeType unused3) {
- int trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
return NextInvokeInsnSP(cu, info, trampoline, state, target_method, 0);
}
@@ -563,7 +566,7 @@ static int NextDirectCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
const MethodReference& target_method,
uint32_t method_idx, uintptr_t unused,
uintptr_t unused2, InvokeType unused3) {
- int trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
return NextInvokeInsnSP(cu, info, trampoline, state, target_method, 0);
}
@@ -571,7 +574,7 @@ static int NextSuperCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
const MethodReference& target_method,
uint32_t method_idx, uintptr_t unused,
uintptr_t unused2, InvokeType unused3) {
- int trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
return NextInvokeInsnSP(cu, info, trampoline, state, target_method, 0);
}
@@ -579,7 +582,7 @@ static int NextVCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
const MethodReference& target_method,
uint32_t method_idx, uintptr_t unused,
uintptr_t unused2, InvokeType unused3) {
- int trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
return NextInvokeInsnSP(cu, info, trampoline, state, target_method, 0);
}
@@ -589,7 +592,7 @@ static int NextInterfaceCallInsnWithAccessCheck(CompilationUnit* cu,
uint32_t unused,
uintptr_t unused2, uintptr_t unused3,
InvokeType unused4) {
- int trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
+ ThreadOffset trampoline = QUICK_ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
return NextInvokeInsnSP(cu, info, trampoline, state, target_method, 0);
}
@@ -1108,9 +1111,9 @@ bool Mir2Lir::GenInlinedStringCompareTo(CallInfo* info) {
bool Mir2Lir::GenInlinedCurrentThread(CallInfo* info) {
RegLocation rl_dest = InlineTarget(info);
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
- int offset = Thread::PeerOffset().Int32Value();
+ ThreadOffset offset = Thread::PeerOffset();
if (cu_->instruction_set == kThumb2 || cu_->instruction_set == kMips) {
- LoadWordDisp(TargetReg(kSelf), offset, rl_result.low_reg);
+ LoadWordDisp(TargetReg(kSelf), offset.Int32Value(), rl_result.low_reg);
} else {
CHECK(cu_->instruction_set == kX86);
reinterpret_cast<X86Mir2Lir*>(this)->OpRegThreadMem(kOpMov, rl_result.low_reg, offset);
@@ -1406,7 +1409,7 @@ void Mir2Lir::GenInvoke(CallInfo* info) {
call_inst = OpMem(kOpBlx, TargetReg(kArg0),
mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value());
} else {
- int trampoline = 0;
+ ThreadOffset trampoline(-1);
switch (info->type) {
case kInterface:
trampoline = fast_path ? QUICK_ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index 846c055..eaae0e1 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -247,7 +247,7 @@ void MipsMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) {
GenBarrier();
NewLIR0(kMipsCurrPC); // Really a jal to .+8
// Now, fill the branch delay slot with the helper load
- int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode));
+ int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData));
GenBarrier(); // Scheduling barrier
// Construct BaseLabel and set up table base register
@@ -272,7 +272,7 @@ void MipsMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
LockCallTemps(); // Prepare for explicit register usage
GenNullCheck(rl_src.s_reg_low, rMIPS_ARG0, opt_flags);
// Go expensive route - artLockObjectFromCode(self, obj);
- int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pLockObjectFromCode));
+ int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pLockObject));
ClobberCalleeSave();
LIR* call_inst = OpReg(kOpBlx, r_tgt);
MarkSafepointPC(call_inst);
@@ -287,7 +287,7 @@ void MipsMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
LockCallTemps(); // Prepare for explicit register usage
GenNullCheck(rl_src.s_reg_low, rMIPS_ARG0, opt_flags);
// Go expensive route - UnlockObjectFromCode(obj);
- int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pUnlockObjectFromCode));
+ int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pUnlockObject));
ClobberCalleeSave();
LIR* call_inst = OpReg(kOpBlx, r_tgt);
MarkSafepointPC(call_inst);
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 802ff62..6100396 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -29,7 +29,7 @@ class MipsMir2Lir : public Mir2Lir {
// Required for target - codegen utilities.
bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src,
RegLocation rl_dest, int lit);
- int LoadHelper(int offset);
+ int LoadHelper(ThreadOffset offset);
LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
int s_reg);
@@ -154,12 +154,12 @@ class MipsMir2Lir : public Mir2Lir {
LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
LIR* OpTestSuspend(LIR* target);
- LIR* OpThreadMem(OpKind op, int thread_offset);
+ LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
LIR* OpVldm(int rBase, int count);
LIR* OpVstm(int rBase, int count);
void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
- void OpTlsCmp(int offset, int val);
+ void OpTlsCmp(ThreadOffset offset, int val);
LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
int s_reg);
diff --git a/compiler/dex/quick/mips/fp_mips.cc b/compiler/dex/quick/mips/fp_mips.cc
index 3203017..9e2fea9 100644
--- a/compiler/dex/quick/mips/fp_mips.cc
+++ b/compiler/dex/quick/mips/fp_mips.cc
@@ -176,7 +176,7 @@ void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src1, RegLocation rl_src2) {
bool wide = true;
- int offset = -1; // Make gcc happy.
+ ThreadOffset offset(-1);
switch (opcode) {
case Instruction::CMPL_FLOAT:
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index bd044c6..4a48c87 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -254,7 +254,7 @@ void MipsMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
LOG(FATAL) << "Unexpected use of OpLea for Arm";
}
-void MipsMir2Lir::OpTlsCmp(int offset, int val) {
+void MipsMir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
}
@@ -579,7 +579,7 @@ void MipsMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array,
// Get the array's class.
LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class);
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value,
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElement), r_value,
r_array_class, true);
// Redo LoadValues in case they didn't survive the call.
LoadValueDirectFixed(rl_array, r_array); // Reload array
diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc
index 0a17fb1..7a9e91a 100644
--- a/compiler/dex/quick/mips/target_mips.cc
+++ b/compiler/dex/quick/mips/target_mips.cc
@@ -505,8 +505,8 @@ void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
* ensure that all branch instructions can be restarted if
* there is a trap in the shadow. Allocate a temp register.
*/
-int MipsMir2Lir::LoadHelper(int offset) {
- LoadWordDisp(rMIPS_SELF, offset, r_T9);
+int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
+ LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
return r_T9;
}
diff --git a/compiler/dex/quick/mips/utility_mips.cc b/compiler/dex/quick/mips/utility_mips.cc
index 68b26f1..5d9ae33 100644
--- a/compiler/dex/quick/mips/utility_mips.cc
+++ b/compiler/dex/quick/mips/utility_mips.cc
@@ -632,7 +632,7 @@ LIR* MipsMir2Lir::StoreBaseDispWide(int rBase, int displacement,
return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
}
-LIR* MipsMir2Lir::OpThreadMem(OpKind op, int thread_offset) {
+LIR* MipsMir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
LOG(FATAL) << "Unexpected use of OpThreadMem for MIPS";
return NULL;
}
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index a34e929..2794bf5 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -424,42 +424,42 @@ class Mir2Lir : public Backend {
RegLocation rl_src, int lit);
void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src1, RegLocation rl_src2);
- void GenConversionCall(int func_offset, RegLocation rl_dest,
+ void GenConversionCall(ThreadOffset func_offset, RegLocation rl_dest,
RegLocation rl_src);
void GenSuspendTest(int opt_flags);
void GenSuspendTestAndBranch(int opt_flags, LIR* target);
// Shared by all targets - implemented in gen_invoke.cc.
- int CallHelperSetup(int helper_offset);
- LIR* CallHelper(int r_tgt, int helper_offset, bool safepoint_pc);
- void CallRuntimeHelperImm(int helper_offset, int arg0, bool safepoint_pc);
- void CallRuntimeHelperReg(int helper_offset, int arg0, bool safepoint_pc);
- void CallRuntimeHelperRegLocation(int helper_offset, RegLocation arg0,
- bool safepoint_pc);
- void CallRuntimeHelperImmImm(int helper_offset, int arg0, int arg1,
+ int CallHelperSetup(ThreadOffset helper_offset);
+ LIR* CallHelper(int r_tgt, ThreadOffset helper_offset, bool safepoint_pc);
+ void CallRuntimeHelperImm(ThreadOffset helper_offset, int arg0, bool safepoint_pc);
+ void CallRuntimeHelperReg(ThreadOffset helper_offset, int arg0, bool safepoint_pc);
+ void CallRuntimeHelperRegLocation(ThreadOffset helper_offset, RegLocation arg0,
+ bool safepoint_pc);
+ void CallRuntimeHelperImmImm(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc);
- void CallRuntimeHelperImmRegLocation(int helper_offset, int arg0,
+ void CallRuntimeHelperImmRegLocation(ThreadOffset helper_offset, int arg0,
RegLocation arg1, bool safepoint_pc);
- void CallRuntimeHelperRegLocationImm(int helper_offset, RegLocation arg0,
+ void CallRuntimeHelperRegLocationImm(ThreadOffset helper_offset, RegLocation arg0,
int arg1, bool safepoint_pc);
- void CallRuntimeHelperImmReg(int helper_offset, int arg0, int arg1,
+ void CallRuntimeHelperImmReg(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc);
- void CallRuntimeHelperRegImm(int helper_offset, int arg0, int arg1,
+ void CallRuntimeHelperRegImm(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc);
- void CallRuntimeHelperImmMethod(int helper_offset, int arg0,
+ void CallRuntimeHelperImmMethod(ThreadOffset helper_offset, int arg0,
bool safepoint_pc);
- void CallRuntimeHelperRegLocationRegLocation(int helper_offset,
+ void CallRuntimeHelperRegLocationRegLocation(ThreadOffset helper_offset,
RegLocation arg0, RegLocation arg1,
bool safepoint_pc);
- void CallRuntimeHelperRegReg(int helper_offset, int arg0, int arg1,
+ void CallRuntimeHelperRegReg(ThreadOffset helper_offset, int arg0, int arg1,
bool safepoint_pc);
- void CallRuntimeHelperRegRegImm(int helper_offset, int arg0, int arg1,
+ void CallRuntimeHelperRegRegImm(ThreadOffset helper_offset, int arg0, int arg1,
int arg2, bool safepoint_pc);
- void CallRuntimeHelperImmMethodRegLocation(int helper_offset, int arg0,
+ void CallRuntimeHelperImmMethodRegLocation(ThreadOffset helper_offset, int arg0,
RegLocation arg2, bool safepoint_pc);
- void CallRuntimeHelperImmMethodImm(int helper_offset, int arg0, int arg2,
+ void CallRuntimeHelperImmMethodImm(ThreadOffset helper_offset, int arg0, int arg2,
bool safepoint_pc);
- void CallRuntimeHelperImmRegLocationRegLocation(int helper_offset,
+ void CallRuntimeHelperImmRegLocationRegLocation(ThreadOffset helper_offset,
int arg0, RegLocation arg1, RegLocation arg2,
bool safepoint_pc);
void GenInvoke(CallInfo* info);
@@ -526,7 +526,7 @@ class Mir2Lir : public Backend {
// Required for target - codegen helpers.
virtual bool SmallLiteralDivide(Instruction::Code dalvik_opcode,
RegLocation rl_src, RegLocation rl_dest, int lit) = 0;
- virtual int LoadHelper(int offset) = 0;
+ virtual int LoadHelper(ThreadOffset offset) = 0;
virtual LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg) = 0;
virtual LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
int s_reg) = 0;
@@ -674,14 +674,14 @@ class Mir2Lir : public Backend {
virtual LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1,
int r_src2) = 0;
virtual LIR* OpTestSuspend(LIR* target) = 0;
- virtual LIR* OpThreadMem(OpKind op, int thread_offset) = 0;
+ virtual LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset) = 0;
virtual LIR* OpVldm(int rBase, int count) = 0;
virtual LIR* OpVstm(int rBase, int count) = 0;
virtual void OpLea(int rBase, int reg1, int reg2, int scale,
int offset) = 0;
virtual void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
int src_hi) = 0;
- virtual void OpTlsCmp(int offset, int val) = 0;
+ virtual void OpTlsCmp(ThreadOffset offset, int val) = 0;
virtual bool InexpensiveConstantInt(int32_t value) = 0;
virtual bool InexpensiveConstantFloat(int32_t value) = 0;
virtual bool InexpensiveConstantLong(int64_t value) = 0;
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 1c395de..6e3e55f 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -148,7 +148,7 @@ void X86Mir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) {
NewLIR1(kX86StartOfMethod, rX86_ARG2);
NewLIR2(kX86PcRelAdr, rX86_ARG1, reinterpret_cast<uintptr_t>(tab_rec));
NewLIR2(kX86Add32RR, rX86_ARG1, rX86_ARG2);
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rX86_ARG0,
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData), rX86_ARG0,
rX86_ARG1, true);
}
@@ -165,7 +165,7 @@ void X86Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
NewLIR3(kX86LockCmpxchgMR, rCX, mirror::Object::MonitorOffset().Int32Value(), rDX);
LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondEq);
// If lock is held, go the expensive route - artLockObjectFromCode(self, obj);
- CallRuntimeHelperReg(QUICK_ENTRYPOINT_OFFSET(pLockObjectFromCode), rCX, true);
+ CallRuntimeHelperReg(QUICK_ENTRYPOINT_OFFSET(pLockObject), rCX, true);
branch->target = NewLIR0(kPseudoTargetLabel);
}
@@ -185,7 +185,7 @@ void X86Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
LIR* branch2 = NewLIR1(kX86Jmp8, 0);
branch->target = NewLIR0(kPseudoTargetLabel);
// Otherwise, go the expensive route - UnlockObjectFromCode(obj);
- CallRuntimeHelperReg(QUICK_ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rAX, true);
+ CallRuntimeHelperReg(QUICK_ENTRYPOINT_OFFSET(pUnlockObject), rAX, true);
branch2->target = NewLIR0(kPseudoTargetLabel);
}
@@ -243,7 +243,7 @@ void X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) {
if (!skip_overflow_check) {
// cmp rX86_SP, fs:[stack_end_]; jcc throw_launchpad
LIR* tgt = RawLIR(0, kPseudoThrowTarget, kThrowStackOverflow, 0, 0, 0, 0);
- OpRegThreadMem(kOpCmp, rX86_SP, Thread::StackEndOffset().Int32Value());
+ OpRegThreadMem(kOpCmp, rX86_SP, Thread::StackEndOffset());
OpCondBranch(kCondUlt, tgt);
// Remember branch target - will process later
throw_launchpads_.Insert(tgt);
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index edb5ae5..21328d5 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -29,7 +29,7 @@ class X86Mir2Lir : public Mir2Lir {
// Required for target - codegen helpers.
bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src,
RegLocation rl_dest, int lit);
- int LoadHelper(int offset);
+ int LoadHelper(ThreadOffset offset);
LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
int s_reg);
@@ -154,14 +154,14 @@ class X86Mir2Lir : public Mir2Lir {
LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
LIR* OpTestSuspend(LIR* target);
- LIR* OpThreadMem(OpKind op, int thread_offset);
+ LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
LIR* OpVldm(int rBase, int count);
LIR* OpVstm(int rBase, int count);
void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
- void OpTlsCmp(int offset, int val);
+ void OpTlsCmp(ThreadOffset offset, int val);
- void OpRegThreadMem(OpKind op, int r_dest, int thread_offset);
+ void OpRegThreadMem(OpKind op, int r_dest, ThreadOffset thread_offset);
void SpillCoreRegs();
void UnSpillCoreRegs();
static const X86EncodingMap EncodingMap[kX86Last];
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 0b4b4be..377d134 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -240,8 +240,8 @@ void X86Mir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
NewLIR5(kX86Lea32RA, rBase, reg1, reg2, scale, offset);
}
-void X86Mir2Lir::OpTlsCmp(int offset, int val) {
- NewLIR2(kX86Cmp16TI8, offset, val);
+void X86Mir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
+ NewLIR2(kX86Cmp16TI8, offset.Int32Value(), val);
}
bool X86Mir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) {
@@ -285,7 +285,7 @@ void X86Mir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
// Test suspend flag, return target of taken suspend branch
LIR* X86Mir2Lir::OpTestSuspend(LIR* target) {
- OpTlsCmp(Thread::ThreadFlagsOffset().Int32Value(), 0);
+ OpTlsCmp(Thread::ThreadFlagsOffset(), 0);
return OpCondBranch((target == NULL) ? kCondNe : kCondEq, target);
}
@@ -403,7 +403,7 @@ void X86Mir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
StoreValueWide(rl_dest, rl_result);
}
-void X86Mir2Lir::OpRegThreadMem(OpKind op, int r_dest, int thread_offset) {
+void X86Mir2Lir::OpRegThreadMem(OpKind op, int r_dest, ThreadOffset thread_offset) {
X86OpCode opcode = kX86Bkpt;
switch (op) {
case kOpCmp: opcode = kX86Cmp32RT; break;
@@ -412,7 +412,7 @@ void X86Mir2Lir::OpRegThreadMem(OpKind op, int r_dest, int thread_offset) {
LOG(FATAL) << "Bad opcode: " << op;
break;
}
- NewLIR2(opcode, r_dest, thread_offset);
+ NewLIR2(opcode, r_dest, thread_offset.Int32Value());
}
/*
@@ -532,7 +532,7 @@ void X86Mir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array,
// Get the array's class.
LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class);
- CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value,
+ CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElement), r_value,
r_array_class, true);
// Redo LoadValues in case they didn't survive the call.
LoadValueDirectFixed(rl_array, r_array); // Reload array
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 2c9b3c8..699f3ae 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -524,7 +524,7 @@ Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
}
// Not used in x86
-int X86Mir2Lir::LoadHelper(int offset) {
+int X86Mir2Lir::LoadHelper(ThreadOffset offset) {
LOG(FATAL) << "Unexpected use of LoadHelper in x86";
return INVALID_REG;
}
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index e15995f..c519bfe 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -292,7 +292,7 @@ LIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src,
return OpRegImm(op, r_dest, value);
}
-LIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset) {
+LIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
X86OpCode opcode = kX86Bkpt;
switch (op) {
case kOpBlx: opcode = kX86CallT; break;
@@ -300,7 +300,7 @@ LIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset) {
LOG(FATAL) << "Bad opcode: " << op;
break;
}
- return NewLIR1(opcode, thread_offset);
+ return NewLIR1(opcode, thread_offset.Int32Value());
}
LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 38d00a0..8b09df7 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -41,9 +41,9 @@
#include "mirror/throwable.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
-#include "stubs/stubs.h"
#include "thread.h"
#include "thread_pool.h"
+#include "trampolines/trampoline_compiler.h"
#include "verifier/method_verifier.h"
#if defined(ART_USE_PORTABLE_COMPILER)
@@ -433,64 +433,38 @@ CompilerTls* CompilerDriver::GetTls() {
return res;
}
+const std::vector<uint8_t>* CompilerDriver::CreateInterpreterToInterpreterBridge() const {
+ return CreateTrampoline(instruction_set_, kInterpreterAbi,
+ INTERPRETER_ENTRYPOINT_OFFSET(pInterpreterToInterpreterBridge));
+}
+
+const std::vector<uint8_t>* CompilerDriver::CreateInterpreterToCompiledCodeBridge() const {
+ return CreateTrampoline(instruction_set_, kInterpreterAbi,
+ INTERPRETER_ENTRYPOINT_OFFSET(pInterpreterToCompiledCodeBridge));
+}
+
+const std::vector<uint8_t>* CompilerDriver::CreateJniDlsymLookup() const {
+ return CreateTrampoline(instruction_set_, kJniAbi, JNI_ENTRYPOINT_OFFSET(pDlsymLookup));
+}
+
const std::vector<uint8_t>* CompilerDriver::CreatePortableResolutionTrampoline() const {
- switch (instruction_set_) {
- case kArm:
- case kThumb2:
- return arm::CreatePortableResolutionTrampoline();
- case kMips:
- return mips::CreatePortableResolutionTrampoline();
- case kX86:
- return x86::CreatePortableResolutionTrampoline();
- default:
- LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
- return NULL;
- }
+ return CreateTrampoline(instruction_set_, kPortableAbi,
+ PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampoline));
}
-const std::vector<uint8_t>* CompilerDriver::CreateQuickResolutionTrampoline() const {
- switch (instruction_set_) {
- case kArm:
- case kThumb2:
- return arm::CreateQuickResolutionTrampoline();
- case kMips:
- return mips::CreateQuickResolutionTrampoline();
- case kX86:
- return x86::CreateQuickResolutionTrampoline();
- default:
- LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
- return NULL;
- }
+const std::vector<uint8_t>* CompilerDriver::CreatePortableToInterpreterBridge() const {
+ return CreateTrampoline(instruction_set_, kPortableAbi,
+ PORTABLE_ENTRYPOINT_OFFSET(pPortableToInterpreterBridge));
}
-const std::vector<uint8_t>* CompilerDriver::CreateInterpreterToInterpreterEntry() const {
- switch (instruction_set_) {
- case kArm:
- case kThumb2:
- return arm::CreateInterpreterToInterpreterEntry();
- case kMips:
- return mips::CreateInterpreterToInterpreterEntry();
- case kX86:
- return x86::CreateInterpreterToInterpreterEntry();
- default:
- LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
- return NULL;
- }
+const std::vector<uint8_t>* CompilerDriver::CreateQuickResolutionTrampoline() const {
+ return CreateTrampoline(instruction_set_, kQuickAbi,
+ QUICK_ENTRYPOINT_OFFSET(pQuickResolutionTrampoline));
}
-const std::vector<uint8_t>* CompilerDriver::CreateInterpreterToQuickEntry() const {
- switch (instruction_set_) {
- case kArm:
- case kThumb2:
- return arm::CreateInterpreterToQuickEntry();
- case kMips:
- return mips::CreateInterpreterToQuickEntry();
- case kX86:
- return x86::CreateInterpreterToQuickEntry();
- default:
- LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
- return NULL;
- }
+const std::vector<uint8_t>* CompilerDriver::CreateQuickToInterpreterBridge() const {
+ return CreateTrampoline(instruction_set_, kQuickAbi,
+ QUICK_ENTRYPOINT_OFFSET(pQuickToInterpreterBridge));
}
void CompilerDriver::CompileAll(jobject class_loader,
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 18f852d..b5222c9 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -48,6 +48,17 @@ enum CompilerBackend {
kNoBackend
};
+enum EntryPointCallingConvention {
+ // ABI of invocations to a method's interpreter entry point.
+ kInterpreterAbi,
+ // ABI of calls to a method's native code, only used for native methods.
+ kJniAbi,
+ // ABI of calls to a method's portable code entry point.
+ kPortableAbi,
+ // ABI of calls to a method's quick code entry point.
+ kQuickAbi
+};
+
enum DexToDexCompilationLevel {
kDontDexToDexCompile, // Only meaning wrt image time interpretation.
kRequired, // Dex-to-dex compilation required for correctness.
@@ -110,13 +121,19 @@ class CompilerDriver {
CompilerTls* GetTls();
// Generate the trampolines that are invoked by unresolved direct methods.
+ const std::vector<uint8_t>* CreateInterpreterToInterpreterBridge() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const std::vector<uint8_t>* CreateInterpreterToCompiledCodeBridge() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const std::vector<uint8_t>* CreateJniDlsymLookup() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::vector<uint8_t>* CreatePortableResolutionTrampoline() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const std::vector<uint8_t>* CreateQuickResolutionTrampoline() const
+ const std::vector<uint8_t>* CreatePortableToInterpreterBridge() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry() const
+ const std::vector<uint8_t>* CreateQuickResolutionTrampoline() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const std::vector<uint8_t>* CreateInterpreterToQuickEntry() const
+ const std::vector<uint8_t>* CreateQuickToInterpreterBridge() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
CompiledClass* GetCompiledClass(ClassReference ref) const
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index e73d021..550d642 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -90,11 +90,23 @@ bool ImageWriter::Write(const std::string& image_filename,
return false;
}
class_linker->RegisterOatFile(*oat_file_);
- interpreter_to_interpreter_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToInterpreterEntryOffset();
- interpreter_to_quick_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToQuickEntryOffset();
- portable_resolution_trampoline_offset_ = oat_file_->GetOatHeader().GetPortableResolutionTrampolineOffset();
- quick_resolution_trampoline_offset_ = oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset();
+ interpreter_to_interpreter_bridge_offset_ =
+ oat_file_->GetOatHeader().GetInterpreterToInterpreterBridgeOffset();
+ interpreter_to_compiled_code_bridge_offset_ =
+ oat_file_->GetOatHeader().GetInterpreterToCompiledCodeBridgeOffset();
+
+ jni_dlsym_lookup_offset_ = oat_file_->GetOatHeader().GetJniDlsymLookupOffset();
+
+ portable_resolution_trampoline_offset_ =
+ oat_file_->GetOatHeader().GetPortableResolutionTrampolineOffset();
+ portable_to_interpreter_bridge_offset_ =
+ oat_file_->GetOatHeader().GetPortableToInterpreterBridgeOffset();
+
+ quick_resolution_trampoline_offset_ =
+ oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset();
+ quick_to_interpreter_bridge_offset_ =
+ oat_file_->GetOatHeader().GetQuickToInterpreterBridgeOffset();
{
Thread::Current()->TransitionFromSuspendedToRunnable();
PruneNonImageClasses(); // Remove junk
@@ -490,57 +502,62 @@ void ImageWriter::FixupClass(const Class* orig, Class* copy) {
void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) {
FixupInstanceFields(orig, copy);
- // OatWriter replaces the code_ with an offset value.
- // Here we readjust to a pointer relative to oat_begin_
- if (orig->IsAbstract()) {
- // Code for abstract methods is set to the abstract method error stub when we load the image.
- copy->SetEntryPointFromCompiledCode(NULL);
- copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
- (GetOatAddress(interpreter_to_interpreter_entry_offset_)));
- return;
- } else {
- copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
- (GetOatAddress(interpreter_to_quick_entry_offset_)));
- }
+ // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
+ // oat_begin_
- if (orig == Runtime::Current()->GetResolutionMethod()) {
+ // The resolution method has a special trampoline to call.
+ if (UNLIKELY(orig == Runtime::Current()->GetResolutionMethod())) {
#if defined(ART_USE_PORTABLE_COMPILER)
copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
#else
copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
#endif
- return;
- }
-
- // Use original code if it exists. Otherwise, set the code pointer to the resolution trampoline.
- const byte* code = GetOatAddress(orig->GetOatCodeOffset());
- if (code != NULL) {
- copy->SetEntryPointFromCompiledCode(code);
} else {
+ // We assume all methods have code. If they don't currently then we set them to the use the
+ // resolution trampoline. Abstract methods never have code and so we need to make sure their
+ // use results in an AbstractMethodError. We use the interpreter to achieve this.
+ if (UNLIKELY(orig->IsAbstract())) {
#if defined(ART_USE_PORTABLE_COMPILER)
- copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
+ copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_to_interpreter_bridge_offset_));
#else
- copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
+ copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_to_interpreter_bridge_offset_));
#endif
- }
-
- if (orig->IsNative()) {
- // The native method's pointer is set to a stub to lookup via dlsym when we load the image.
- // Note this is not the code_ pointer, that is handled above.
- copy->SetNativeMethod(NULL);
- } else {
- // normal (non-abstract non-native) methods have mapping tables to relocate
- uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
- const byte* mapping_table = GetOatAddress(mapping_table_off);
- copy->SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table));
-
- uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
- const byte* vmap_table = GetOatAddress(vmap_table_offset);
- copy->SetVmapTable(reinterpret_cast<const uint16_t*>(vmap_table));
-
- uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset();
- const byte* native_gc_map = GetOatAddress(native_gc_map_offset);
- copy->SetNativeGcMap(reinterpret_cast<const uint8_t*>(native_gc_map));
+ copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
+ (GetOatAddress(interpreter_to_interpreter_bridge_offset_)));
+ } else {
+ copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*>
+ (GetOatAddress(interpreter_to_compiled_code_bridge_offset_)));
+ // Use original code if it exists. Otherwise, set the code pointer to the resolution
+ // trampoline.
+ const byte* code = GetOatAddress(orig->GetOatCodeOffset());
+ if (code != NULL) {
+ copy->SetEntryPointFromCompiledCode(code);
+ } else {
+#if defined(ART_USE_PORTABLE_COMPILER)
+ copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_));
+#else
+ copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_));
+#endif
+ }
+ if (orig->IsNative()) {
+ // The native method's pointer is set to a stub to lookup via dlsym.
+ // Note this is not the code_ pointer, that is handled above.
+ copy->SetNativeMethod(GetOatAddress(jni_dlsym_lookup_offset_));
+ } else {
+ // Normal (non-abstract non-native) methods have various tables to relocate.
+ uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
+ const byte* mapping_table = GetOatAddress(mapping_table_off);
+ copy->SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table));
+
+ uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
+ const byte* vmap_table = GetOatAddress(vmap_table_offset);
+ copy->SetVmapTable(reinterpret_cast<const uint16_t*>(vmap_table));
+
+ uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset();
+ const byte* native_gc_map = GetOatAddress(native_gc_map_offset);
+ copy->SetNativeGcMap(reinterpret_cast<const uint8_t*>(native_gc_map));
+ }
+ }
}
}
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index e43ec63..545534f 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -39,8 +39,8 @@ class ImageWriter {
public:
explicit ImageWriter(const CompilerDriver& compiler_driver)
: compiler_driver_(compiler_driver), oat_file_(NULL), image_end_(0), image_begin_(NULL),
- oat_data_begin_(NULL), interpreter_to_interpreter_entry_offset_(0),
- interpreter_to_quick_entry_offset_(0), portable_resolution_trampoline_offset_(0),
+ oat_data_begin_(NULL), interpreter_to_interpreter_bridge_offset_(0),
+ interpreter_to_compiled_code_bridge_offset_(0), portable_resolution_trampoline_offset_(0),
quick_resolution_trampoline_offset_(0) {}
~ImageWriter() {}
@@ -195,10 +195,13 @@ class ImageWriter {
const byte* oat_data_begin_;
// Offset from oat_data_begin_ to the stubs.
- uint32_t interpreter_to_interpreter_entry_offset_;
- uint32_t interpreter_to_quick_entry_offset_;
+ uint32_t interpreter_to_interpreter_bridge_offset_;
+ uint32_t interpreter_to_compiled_code_bridge_offset_;
+ uint32_t jni_dlsym_lookup_offset_;
uint32_t portable_resolution_trampoline_offset_;
+ uint32_t portable_to_interpreter_bridge_offset_;
uint32_t quick_resolution_trampoline_offset_;
+ uint32_t quick_to_interpreter_bridge_offset_;
// DexCaches seen while scanning for fixing up CodeAndDirectMethods
typedef std::set<mirror::DexCache*> Set;
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index b069fbd..9713fe9 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -172,8 +172,8 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver& compiler,
// can occur. The result is the saved JNI local state that is restored by the exit call. We
// abuse the JNI calling convention here, that is guaranteed to support passing 2 pointer
// arguments.
- uintptr_t jni_start = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(pJniMethodStartSynchronized)
- : QUICK_ENTRYPOINT_OFFSET(pJniMethodStart);
+ ThreadOffset jni_start = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(pJniMethodStartSynchronized)
+ : QUICK_ENTRYPOINT_OFFSET(pJniMethodStart);
main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
FrameOffset locked_object_sirt_offset(0);
if (is_synchronized) {
@@ -301,7 +301,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver& compiler,
// 12. Call into JNI method end possibly passing a returned reference, the method and the current
// thread.
end_jni_conv->ResetIterator(FrameOffset(end_out_arg_size));
- uintptr_t jni_end;
+ ThreadOffset jni_end(-1);
if (reference_return) {
// Pass result.
jni_end = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(pJniMethodEndWithReferenceSynchronized)
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 5eb837b..21c5317 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -51,11 +51,14 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
size_oat_header_(0),
size_oat_header_image_file_location_(0),
size_dex_file_(0),
- size_interpreter_to_interpreter_entry_(0),
- size_interpreter_to_quick_entry_(0),
+ size_interpreter_to_interpreter_bridge_(0),
+ size_interpreter_to_compiled_code_bridge_(0),
+ size_jni_dlsym_lookup_(0),
size_portable_resolution_trampoline_(0),
+ size_portable_to_interpreter_bridge_(0),
size_quick_resolution_trampoline_(0),
- size_stubs_alignment_(0),
+ size_quick_to_interpreter_bridge_(0),
+ size_trampoline_alignment_(0),
size_code_size_(0),
size_code_(0),
size_code_alignment_(0),
@@ -176,30 +179,30 @@ size_t OatWriter::InitOatCode(size_t offset) {
size_executable_offset_alignment_ = offset - old_offset;
if (compiler_driver_->IsImage()) {
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
- oat_header_->SetInterpreterToInterpreterEntryOffset(offset);
- interpreter_to_interpreter_entry_.reset(
- compiler_driver_->CreateInterpreterToInterpreterEntry());
- offset += interpreter_to_interpreter_entry_->size();
-
- offset = CompiledCode::AlignCode(offset, instruction_set);
- oat_header_->SetInterpreterToQuickEntryOffset(offset);
- interpreter_to_quick_entry_.reset(compiler_driver_->CreateInterpreterToQuickEntry());
- offset += interpreter_to_quick_entry_->size();
-
- offset = CompiledCode::AlignCode(offset, instruction_set);
- oat_header_->SetPortableResolutionTrampolineOffset(offset);
- portable_resolution_trampoline_.reset(compiler_driver_->CreatePortableResolutionTrampoline());
- offset += portable_resolution_trampoline_->size();
-
- offset = CompiledCode::AlignCode(offset, instruction_set);
- oat_header_->SetQuickResolutionTrampolineOffset(offset);
- quick_resolution_trampoline_.reset(compiler_driver_->CreateQuickResolutionTrampoline());
- offset += quick_resolution_trampoline_->size();
+
+ #define DO_TRAMPOLINE(field, fn_name) \
+ offset = CompiledCode::AlignCode(offset, instruction_set); \
+ oat_header_->Set ## fn_name ## Offset(offset); \
+ field.reset(compiler_driver_->Create ## fn_name()); \
+ offset += field->size();
+
+ DO_TRAMPOLINE(interpreter_to_interpreter_bridge_, InterpreterToInterpreterBridge);
+ DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_, InterpreterToCompiledCodeBridge);
+ DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup);
+ DO_TRAMPOLINE(portable_resolution_trampoline_, PortableResolutionTrampoline);
+ DO_TRAMPOLINE(portable_to_interpreter_bridge_, PortableToInterpreterBridge);
+ DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
+ DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
+
+ #undef DO_TRAMPOLINE
} else {
- oat_header_->SetInterpreterToInterpreterEntryOffset(0);
- oat_header_->SetInterpreterToQuickEntryOffset(0);
+ oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
+ oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
+ oat_header_->SetJniDlsymLookupOffset(0);
oat_header_->SetPortableResolutionTrampolineOffset(0);
+ oat_header_->SetPortableToInterpreterBridgeOffset(0);
oat_header_->SetQuickResolutionTrampolineOffset(0);
+ oat_header_->SetQuickToInterpreterBridgeOffset(0);
}
return offset;
}
@@ -469,11 +472,14 @@ bool OatWriter::Write(OutputStream& out) {
DO_STAT(size_oat_header_);
DO_STAT(size_oat_header_image_file_location_);
DO_STAT(size_dex_file_);
- DO_STAT(size_interpreter_to_interpreter_entry_);
- DO_STAT(size_interpreter_to_quick_entry_);
+ DO_STAT(size_interpreter_to_interpreter_bridge_);
+ DO_STAT(size_interpreter_to_compiled_code_bridge_);
+ DO_STAT(size_jni_dlsym_lookup_);
DO_STAT(size_portable_resolution_trampoline_);
+ DO_STAT(size_portable_to_interpreter_bridge_);
DO_STAT(size_quick_resolution_trampoline_);
- DO_STAT(size_stubs_alignment_);
+ DO_STAT(size_quick_to_interpreter_bridge_);
+ DO_STAT(size_trampoline_alignment_);
DO_STAT(size_code_size_);
DO_STAT(size_code_);
DO_STAT(size_code_alignment_);
@@ -545,52 +551,30 @@ size_t OatWriter::WriteCode(OutputStream& out, const size_t file_offset) {
DCHECK_OFFSET();
if (compiler_driver_->IsImage()) {
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
- if (!out.WriteFully(&(*interpreter_to_interpreter_entry_)[0],
- interpreter_to_interpreter_entry_->size())) {
- PLOG(ERROR) << "Failed to write interpreter to interpreter entry to " << out.GetLocation();
- return false;
- }
- size_interpreter_to_interpreter_entry_ += interpreter_to_interpreter_entry_->size();
- relative_offset += interpreter_to_interpreter_entry_->size();
- DCHECK_OFFSET();
-
- uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set);
- uint32_t alignment_padding = aligned_offset - relative_offset;
- out.Seek(alignment_padding, kSeekCurrent);
- size_stubs_alignment_ += alignment_padding;
- if (!out.WriteFully(&(*interpreter_to_quick_entry_)[0], interpreter_to_quick_entry_->size())) {
- PLOG(ERROR) << "Failed to write interpreter to quick entry to " << out.GetLocation();
- return false;
- }
- size_interpreter_to_quick_entry_ += interpreter_to_quick_entry_->size();
- relative_offset += alignment_padding + interpreter_to_quick_entry_->size();
- DCHECK_OFFSET();
- aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set);
- alignment_padding = aligned_offset - relative_offset;
- out.Seek(alignment_padding, kSeekCurrent);
- size_stubs_alignment_ += alignment_padding;
- if (!out.WriteFully(&(*portable_resolution_trampoline_)[0],
- portable_resolution_trampoline_->size())) {
- PLOG(ERROR) << "Failed to write portable resolution trampoline to " << out.GetLocation();
- return false;
- }
- size_portable_resolution_trampoline_ += portable_resolution_trampoline_->size();
- relative_offset += alignment_padding + portable_resolution_trampoline_->size();
- DCHECK_OFFSET();
-
- aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set);
- alignment_padding = aligned_offset - relative_offset;
- out.Seek(alignment_padding, kSeekCurrent);
- size_stubs_alignment_ += alignment_padding;
- if (!out.WriteFully(&(*quick_resolution_trampoline_)[0],
- quick_resolution_trampoline_->size())) {
- PLOG(ERROR) << "Failed to write quick resolution trampoline to " << out.GetLocation();
- return false;
- }
- size_quick_resolution_trampoline_ += quick_resolution_trampoline_->size();
- relative_offset += alignment_padding + quick_resolution_trampoline_->size();
- DCHECK_OFFSET();
+ #define DO_TRAMPOLINE(field) \
+ do { \
+ uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \
+ uint32_t alignment_padding = aligned_offset - relative_offset; \
+ out.Seek(alignment_padding, kSeekCurrent); \
+ size_trampoline_alignment_ += alignment_padding; \
+ if (!out.WriteFully(&(*field)[0], field->size())) { \
+ PLOG(ERROR) << "Failed to write " # field " to " << out.GetLocation(); \
+ return false; \
+ } \
+ size_ ## field += field->size(); \
+ relative_offset += alignment_padding + field->size(); \
+ DCHECK_OFFSET(); \
+ } while (false)
+
+ DO_TRAMPOLINE(interpreter_to_interpreter_bridge_);
+ DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_);
+ DO_TRAMPOLINE(jni_dlsym_lookup_);
+ DO_TRAMPOLINE(portable_resolution_trampoline_);
+ DO_TRAMPOLINE(portable_to_interpreter_bridge_);
+ DO_TRAMPOLINE(quick_resolution_trampoline_);
+ DO_TRAMPOLINE(quick_to_interpreter_bridge_);
+ #undef DO_TRAMPOLINE
}
return relative_offset;
}
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index f2c5626..e6cc0bc 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -181,10 +181,13 @@ class OatWriter {
OatHeader* oat_header_;
std::vector<OatDexFile*> oat_dex_files_;
std::vector<OatClass*> oat_classes_;
- UniquePtr<const std::vector<uint8_t> > interpreter_to_interpreter_entry_;
- UniquePtr<const std::vector<uint8_t> > interpreter_to_quick_entry_;
+ UniquePtr<const std::vector<uint8_t> > interpreter_to_interpreter_bridge_;
+ UniquePtr<const std::vector<uint8_t> > interpreter_to_compiled_code_bridge_;
+ UniquePtr<const std::vector<uint8_t> > jni_dlsym_lookup_;
UniquePtr<const std::vector<uint8_t> > portable_resolution_trampoline_;
+ UniquePtr<const std::vector<uint8_t> > portable_to_interpreter_bridge_;
UniquePtr<const std::vector<uint8_t> > quick_resolution_trampoline_;
+ UniquePtr<const std::vector<uint8_t> > quick_to_interpreter_bridge_;
// output stats
uint32_t size_dex_file_alignment_;
@@ -192,11 +195,14 @@ class OatWriter {
uint32_t size_oat_header_;
uint32_t size_oat_header_image_file_location_;
uint32_t size_dex_file_;
- uint32_t size_interpreter_to_interpreter_entry_;
- uint32_t size_interpreter_to_quick_entry_;
+ uint32_t size_interpreter_to_interpreter_bridge_;
+ uint32_t size_interpreter_to_compiled_code_bridge_;
+ uint32_t size_jni_dlsym_lookup_;
uint32_t size_portable_resolution_trampoline_;
+ uint32_t size_portable_to_interpreter_bridge_;
uint32_t size_quick_resolution_trampoline_;
- uint32_t size_stubs_alignment_;
+ uint32_t size_quick_to_interpreter_bridge_;
+ uint32_t size_trampoline_alignment_;
uint32_t size_code_size_;
uint32_t size_code_;
uint32_t size_code_alignment_;
diff --git a/compiler/stubs/portable/stubs.cc b/compiler/stubs/portable/stubs.cc
deleted file mode 100644
index def43e2..0000000
--- a/compiler/stubs/portable/stubs.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "stubs/stubs.h"
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "jni_internal.h"
-#include "utils/arm/assembler_arm.h"
-#include "utils/mips/assembler_mips.h"
-#include "utils/x86/assembler_x86.h"
-#include "stack_indirect_reference_table.h"
-#include "sirt_ref.h"
-
-#define __ assembler->
-
-namespace art {
-
-namespace arm {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
- UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
- RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
-
- __ PushList(save);
- __ LoadFromOffset(kLoadWord, R12, TR,
- PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
- __ mov(R3, ShifterOperand(TR)); // Pass Thread::Current() in R3
- __ mov(R2, ShifterOperand(SP)); // Pass sp for Method** callee_addr
- __ IncreaseFrameSize(12); // 3 words of space for alignment
- // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)
- __ blx(R12);
- __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
- __ DecreaseFrameSize(12);
- __ PopList(save);
- __ cmp(R12, ShifterOperand(0));
- __ bx(R12, NE); // If R12 != 0 tail call method's code
- __ bx(LR); // Return to caller to handle exception
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-} // namespace arm
-
-namespace mips {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
- UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
- // Build frame and save argument registers and RA.
- __ AddConstant(SP, SP, -32);
- __ StoreToOffset(kStoreWord, RA, SP, 28);
- __ StoreToOffset(kStoreWord, A3, SP, 12);
- __ StoreToOffset(kStoreWord, A2, SP, 8);
- __ StoreToOffset(kStoreWord, A1, SP, 4);
- __ StoreToOffset(kStoreWord, A0, SP, 0);
-
- __ LoadFromOffset(kLoadWord, T9, S1,
- PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
- __ Move(A3, S1); // Pass Thread::Current() in A3
- __ Move(A2, SP); // Pass SP for Method** callee_addr
- __ Jalr(T9); // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)
-
- // Restore frame, argument registers, and RA.
- __ LoadFromOffset(kLoadWord, A0, SP, 0);
- __ LoadFromOffset(kLoadWord, A1, SP, 4);
- __ LoadFromOffset(kLoadWord, A2, SP, 8);
- __ LoadFromOffset(kLoadWord, A3, SP, 12);
- __ LoadFromOffset(kLoadWord, RA, SP, 28);
- __ AddConstant(SP, SP, 32);
-
- Label resolve_fail;
- __ EmitBranch(V0, ZERO, &resolve_fail, true);
- __ Jr(V0); // If V0 != 0 tail call method's code
- __ Bind(&resolve_fail, false);
- __ Jr(RA); // Return to caller to handle exception
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-} // namespace mips
-
-namespace x86 {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
- UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
-
- __ pushl(EBP);
- __ movl(EBP, ESP); // save ESP
- __ subl(ESP, Immediate(8)); // Align stack
- __ movl(EAX, Address(EBP, 8)); // Method* called
- __ leal(EDX, Address(EBP, 8)); // Method** called_addr
- __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // pass thread
- __ pushl(EDX); // pass called_addr
- __ pushl(ECX); // pass receiver
- __ pushl(EAX); // pass called
- // Call to resolve method.
- __ Call(ThreadOffset(PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode)),
- X86ManagedRegister::FromCpuRegister(ECX));
- __ leave();
-
- Label resolve_fail; // forward declaration
- __ cmpl(EAX, Immediate(0));
- __ j(kEqual, &resolve_fail);
- __ jmp(EAX);
- // Tail call to intended method.
- __ Bind(&resolve_fail);
- __ ret();
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-} // namespace x86
-
-} // namespace art
diff --git a/compiler/stubs/quick/stubs.cc b/compiler/stubs/quick/stubs.cc
deleted file mode 100644
index 912f1c0..0000000
--- a/compiler/stubs/quick/stubs.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "stubs/stubs.h"
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "jni_internal.h"
-#include "utils/arm/assembler_arm.h"
-#include "utils/mips/assembler_mips.h"
-#include "utils/x86/assembler_x86.h"
-#include "sirt_ref.h"
-#include "stack_indirect_reference_table.h"
-
-#define __ assembler->
-
-namespace art {
-
-namespace arm {
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline() {
- UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
- // | Out args |
- // | Method* | <- SP on entry
- // | LR | return address into caller
- // | ... | callee saves
- // | R3 | possible argument
- // | R2 | possible argument
- // | R1 | possible argument
- // | R0 | junk on call to QuickResolutionTrampolineFromCode, holds result Method*
- // | Method* | Callee save Method* set up by QuickResoltuionTrampolineFromCode
- // Save callee saves and ready frame for exception delivery
- RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
- (1 << R10) | (1 << R11) | (1 << LR);
- // TODO: enable when GetCalleeSaveMethod is available at stub generation time
- // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
- __ PushList(save);
- __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(pQuickResolutionTrampolineFromCode));
- __ mov(R3, ShifterOperand(TR)); // Pass Thread::Current() in R3
- __ IncreaseFrameSize(8); // 2 words of space for alignment
- __ mov(R2, ShifterOperand(SP)); // Pass SP
- // Call to resolution trampoline (method_idx, receiver, sp, Thread*)
- __ blx(R12);
- __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
- // Restore registers which may have been modified by GC, "R0" will hold the Method*
- __ DecreaseFrameSize(4);
- __ PopList((1 << R0) | save);
- __ bx(R12); // Leaf call to method's code
- __ bkpt(0);
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry() {
- UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
-
- __ LoadFromOffset(kLoadWord, PC, R0, QUICK_ENTRYPOINT_OFFSET(pInterpreterToInterpreterEntry));
- __ bkpt(0);
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry() {
- UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
-
- __ LoadFromOffset(kLoadWord, PC, R0, QUICK_ENTRYPOINT_OFFSET(pInterpreterToQuickEntry));
- __ bkpt(0);
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-} // namespace arm
-
-namespace mips {
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline() {
- UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
- // | Out args |
- // | Method* | <- SP on entry
- // | RA | return address into caller
- // | ... | callee saves
- // | A3 | possible argument
- // | A2 | possible argument
- // | A1 | possible argument
- // | A0/Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
- // Save callee saves and ready frame for exception delivery
- __ AddConstant(SP, SP, -64);
- __ StoreToOffset(kStoreWord, RA, SP, 60);
- __ StoreToOffset(kStoreWord, FP, SP, 56);
- __ StoreToOffset(kStoreWord, GP, SP, 52);
- __ StoreToOffset(kStoreWord, S7, SP, 48);
- __ StoreToOffset(kStoreWord, S6, SP, 44);
- __ StoreToOffset(kStoreWord, S5, SP, 40);
- __ StoreToOffset(kStoreWord, S4, SP, 36);
- __ StoreToOffset(kStoreWord, S3, SP, 32);
- __ StoreToOffset(kStoreWord, S2, SP, 28);
- __ StoreToOffset(kStoreWord, A3, SP, 12);
- __ StoreToOffset(kStoreWord, A2, SP, 8);
- __ StoreToOffset(kStoreWord, A1, SP, 4);
-
- __ LoadFromOffset(kLoadWord, T9, S1, QUICK_ENTRYPOINT_OFFSET(pQuickResolutionTrampolineFromCode));
- __ Move(A3, S1); // Pass Thread::Current() in A3
- __ Move(A2, SP); // Pass SP for Method** callee_addr
- __ Jalr(T9); // Call to resolution trampoline (method_idx, receiver, sp, Thread*)
-
- // Restore registers which may have been modified by GC
- __ LoadFromOffset(kLoadWord, A0, SP, 0);
- __ LoadFromOffset(kLoadWord, A1, SP, 4);
- __ LoadFromOffset(kLoadWord, A2, SP, 8);
- __ LoadFromOffset(kLoadWord, A3, SP, 12);
- __ LoadFromOffset(kLoadWord, S2, SP, 28);
- __ LoadFromOffset(kLoadWord, S3, SP, 32);
- __ LoadFromOffset(kLoadWord, S4, SP, 36);
- __ LoadFromOffset(kLoadWord, S5, SP, 40);
- __ LoadFromOffset(kLoadWord, S6, SP, 44);
- __ LoadFromOffset(kLoadWord, S7, SP, 48);
- __ LoadFromOffset(kLoadWord, GP, SP, 52);
- __ LoadFromOffset(kLoadWord, FP, SP, 56);
- __ LoadFromOffset(kLoadWord, RA, SP, 60);
- __ AddConstant(SP, SP, 64);
-
- __ Move(T9, V0); // Put method's code in T9
- __ Jr(T9); // Leaf call to method's code
-
- __ Break();
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry() {
- UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
-
- __ LoadFromOffset(kLoadWord, T9, A0, QUICK_ENTRYPOINT_OFFSET(pInterpreterToInterpreterEntry));
- __ Jr(T9);
- __ Break();
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry() {
- UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
-
- __ LoadFromOffset(kLoadWord, T9, A0, QUICK_ENTRYPOINT_OFFSET(pInterpreterToInterpreterEntry));
- __ Jr(T9);
- __ Break();
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-} // namespace mips
-
-namespace x86 {
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline() {
- UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
- // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
- // return address
- __ pushl(EDI);
- __ pushl(ESI);
- __ pushl(EBP);
- __ pushl(EBX);
- __ pushl(EDX);
- __ pushl(ECX);
- __ pushl(EAX); // <-- callee save Method* to go here
- __ movl(EDX, ESP); // save ESP
- __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // pass Thread*
- __ pushl(EDX); // pass ESP for Method*
- __ pushl(ECX); // pass receiver
- __ pushl(EAX); // pass Method*
-
- // Call to resolve method.
- __ Call(ThreadOffset(QUICK_ENTRYPOINT_OFFSET(pQuickResolutionTrampolineFromCode)),
- X86ManagedRegister::FromCpuRegister(ECX));
-
- __ movl(EDI, EAX); // save code pointer in EDI
- __ addl(ESP, Immediate(16)); // Pop arguments
- __ popl(EAX); // Restore args.
- __ popl(ECX);
- __ popl(EDX);
- __ popl(EBX);
- __ popl(EBP); // Restore callee saves.
- __ popl(ESI);
- // Swap EDI callee save with code pointer
- __ xchgl(EDI, Address(ESP, 0));
- // Tail call to intended method.
- __ ret();
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry() {
- UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
-
- __ fs()->jmp(Address::Absolute(ThreadOffset(QUICK_ENTRYPOINT_OFFSET(pInterpreterToInterpreterEntry))));
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry() {
- UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
-
- __ fs()->jmp(Address::Absolute(ThreadOffset(QUICK_ENTRYPOINT_OFFSET(pInterpreterToQuickEntry))));
-
- size_t cs = assembler->CodeSize();
- UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
- MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
- assembler->FinalizeInstructions(code);
-
- return entry_stub.release();
-}
-} // namespace x86
-
-} // namespace art
diff --git a/compiler/stubs/stubs.h b/compiler/stubs/stubs.h
deleted file mode 100644
index d85eae8..0000000
--- a/compiler/stubs/stubs.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_STUBS_STUBS_H_
-#define ART_COMPILER_STUBS_STUBS_H_
-
-#include "runtime.h"
-
-namespace art {
-
-namespace arm {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-}
-
-namespace mips {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-}
-
-namespace x86 {
-const std::vector<uint8_t>* CreatePortableResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateQuickResolutionTrampoline()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToInterpreterEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-const std::vector<uint8_t>* CreateInterpreterToQuickEntry()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-}
-
-} // namespace art
-
-#endif // ART_COMPILER_STUBS_STUBS_H_
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index fa202c3..f0d11d8 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -1246,10 +1246,10 @@ bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) {
// Implementation note: this method must emit at most one instruction when
// Address::CanHoldLoadOffset.
void ArmAssembler::LoadFromOffset(LoadOperandType type,
- Register reg,
- Register base,
- int32_t offset,
- Condition cond) {
+ Register reg,
+ Register base,
+ int32_t offset,
+ Condition cond) {
if (!Address::CanHoldLoadOffset(type, offset)) {
CHECK(base != IP);
LoadImmediate(IP, offset, cond);
@@ -1884,7 +1884,7 @@ void ArmExceptionSlowPath::Emit(Assembler* sasm) {
// Don't care about preserving R0 as this call won't return
__ mov(R0, ShifterOperand(scratch_.AsCoreRegister()));
// Set up call to Thread::Current()->pDeliverException
- __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(pDeliverException));
+ __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(pDeliverException).Int32Value());
__ blx(R12);
// Call never returns
__ bkpt(0);
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 931d7ab..2be3d56 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -813,14 +813,7 @@ void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOff
void MipsAssembler::Copy(FrameOffset /*dest*/, FrameOffset /*src_base*/, Offset /*src_offset*/,
ManagedRegister /*mscratch*/, size_t /*size*/) {
- UNIMPLEMENTED(FATAL) << "no arm implementation";
-#if 0
- Register scratch = mscratch.AsMips().AsCoreRegister();
- CHECK_EQ(size, 4u);
- movl(scratch, Address(ESP, src_base));
- movl(scratch, Address(scratch, src_offset));
- movl(Address(ESP, dest), scratch);
-#endif
+ UNIMPLEMENTED(FATAL) << "no mips implementation";
}
void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
@@ -834,24 +827,11 @@ void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
void MipsAssembler::Copy(FrameOffset /*dest*/, Offset /*dest_offset*/, FrameOffset /*src*/, Offset /*src_offset*/,
ManagedRegister /*mscratch*/, size_t /*size*/) {
- UNIMPLEMENTED(FATAL) << "no arm implementation";
-#if 0
- Register scratch = mscratch.AsMips().AsCoreRegister();
- CHECK_EQ(size, 4u);
- CHECK_EQ(dest.Int32Value(), src.Int32Value());
- movl(scratch, Address(ESP, src));
- pushl(Address(scratch, src_offset));
- popl(Address(scratch, dest_offset));
-#endif
+ UNIMPLEMENTED(FATAL) << "no mips implementation";
}
void MipsAssembler::MemoryBarrier(ManagedRegister) {
- UNIMPLEMENTED(FATAL) << "NEEDS TO BE IMPLEMENTED";
-#if 0
-#if ANDROID_SMP != 0
- mfence();
-#endif
-#endif
+ UNIMPLEMENTED(FATAL) << "no mips implementation";
}
void MipsAssembler::CreateSirtEntry(ManagedRegister mout_reg,
@@ -953,10 +933,7 @@ void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscrat
}
void MipsAssembler::Call(ThreadOffset /*offset*/, ManagedRegister /*mscratch*/) {
- UNIMPLEMENTED(FATAL) << "no arm implementation";
-#if 0
- fs()->call(Address::Absolute(offset));
-#endif
+ UNIMPLEMENTED(FATAL) << "no mips implementation";
}
void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
@@ -988,7 +965,7 @@ void MipsExceptionSlowPath::Emit(Assembler* sasm) {
// Don't care about preserving A0 as this call won't return
__ Move(A0, scratch_.AsCoreRegister());
// Set up call to Thread::Current()->pDeliverException
- __ LoadFromOffset(kLoadWord, T9, S1, QUICK_ENTRYPOINT_OFFSET(pDeliverException));
+ __ LoadFromOffset(kLoadWord, T9, S1, QUICK_ENTRYPOINT_OFFSET(pDeliverException).Int32Value());
__ Jr(T9);
// Call never returns
__ Break();
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 51bb3eb..4f25c00 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -142,6 +142,7 @@ LIBART_COMMON_SRC_FILES += \
arch/x86/registers_x86.cc \
arch/mips/registers_mips.cc \
entrypoints/entrypoint_utils.cc \
+ entrypoints/interpreter/interpreter_entrypoints.cc \
entrypoints/jni/jni_entrypoints.cc \
entrypoints/math_entrypoints.cc \
entrypoints/portable/portable_alloc_entrypoints.cc \
@@ -163,15 +164,13 @@ LIBART_COMMON_SRC_FILES += \
entrypoints/quick/quick_field_entrypoints.cc \
entrypoints/quick/quick_fillarray_entrypoints.cc \
entrypoints/quick/quick_instrumentation_entrypoints.cc \
- entrypoints/quick/quick_interpreter_entrypoints.cc \
entrypoints/quick/quick_invoke_entrypoints.cc \
entrypoints/quick/quick_jni_entrypoints.cc \
entrypoints/quick/quick_lock_entrypoints.cc \
entrypoints/quick/quick_math_entrypoints.cc \
- entrypoints/quick/quick_proxy_entrypoints.cc \
- entrypoints/quick/quick_stub_entrypoints.cc \
entrypoints/quick/quick_thread_entrypoints.cc \
- entrypoints/quick/quick_throw_entrypoints.cc
+ entrypoints/quick/quick_throw_entrypoints.cc \
+ entrypoints/quick/quick_trampoline_entrypoints.cc
LIBART_TARGET_SRC_FILES := \
$(LIBART_COMMON_SRC_FILES) \
diff --git a/runtime/arch/arm/asm_support_arm.S b/runtime/arch/arm/asm_support_arm.S
index ed655e9..559788f 100644
--- a/runtime/arch/arm/asm_support_arm.S
+++ b/runtime/arch/arm/asm_support_arm.S
@@ -35,4 +35,11 @@
.size \name, .-\name
.endm
+.macro UNIMPLEMENTED name
+ ENTRY \name
+ bkpt
+ bkpt
+ END \name
+.endm
+
#endif // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index b71a158..848bacc 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "entrypoints/interpreter/interpreter_entrypoints.h"
#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/entrypoint_utils.h"
@@ -21,49 +22,61 @@
namespace art {
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterperterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+
+// Portable entrypoints.
+extern "C" void art_portable_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_portable_to_interpreter_bridge(mirror::AbstractMethod*);
+
// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_with_access_check(uint32_t, void*, int32_t);
// Cast entrypoints.
extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
+extern "C" void art_quick_can_put_array_element(void*, void*);
+extern "C" void art_quick_check_cast(void*, void*);
// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+extern "C" void* art_quick_initialize_static_storage(uint32_t, void*);
+extern "C" void* art_quick_initialize_type(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, void*);
+extern "C" void* art_quick_resolve_string(void*, uint32_t);
// Exception entrypoints.
extern "C" void* GetAndClearException(Thread*);
// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+extern "C" int art_quick_set32_instance(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static(uint32_t);
+extern "C" int64_t art_quick_get64_instance(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static(uint32_t);
+extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static(uint32_t);
// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+extern "C" void art_quick_handle_fill_data(void*, void*);
// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_unlock_object_from_code(void*);
+extern "C" void art_quick_lock_object(void*);
+extern "C" void art_quick_unlock_object(void*);
// Math entrypoints.
extern int32_t CmpgDouble(double a, double b);
@@ -93,26 +106,14 @@ extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-
// Intrinsic entrypoints.
extern "C" int32_t __memcmp16(void*, void*, int32_t);
extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
extern "C" int32_t art_quick_string_compareto(void*, void*);
// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_quick_to_interpreter_bridge(mirror::AbstractMethod*);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -125,49 +126,61 @@ extern void CheckSuspendFromCode(Thread* thread);
extern "C" void art_quick_test_suspend();
// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+extern "C" void art_quick_deliver_exception(void*);
+extern "C" void art_quick_throw_array_bounds(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero();
+extern "C" void art_quick_throw_no_such_method(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception();
+extern "C" void art_quick_throw_stack_overflow(void*);
+
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
+ // Interpreter
+ ipoints->pInterpreterToInterpreterBridge = artInterpreterToInterpreterBridge;
+ ipoints->pInterpreterToCompiledCodeBridge = artInterperterToCompiledCodeBridge;
+
+ // JNI
+ jpoints->pDlsymLookup = art_jni_dlsym_lookup_stub;
+
+ // Portable
+ ppoints->pPortableResolutionTrampoline = art_portable_resolution_trampoline;
+ ppoints->pPortableToInterpreterBridge = art_portable_to_interpreter_bridge;
+
// Alloc
- qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
- qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
- qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
- qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
- qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
- qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+ qpoints->pAllocArray = art_quick_alloc_array;
+ qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check;
+ qpoints->pAllocObject = art_quick_alloc_object;
+ qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check;
+ qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array;
+ qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check;
// Cast
- qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
- qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
- qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+ qpoints->pInstanceofNonTrivial = artIsAssignableFromCode;
+ qpoints->pCanPutArrayElement = art_quick_can_put_array_element;
+ qpoints->pCheckCast = art_quick_check_cast;
// DexCache
- qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
- qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
- qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
- qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+ qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
+ qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access;
+ qpoints->pInitializeType = art_quick_initialize_type;
+ qpoints->pResolveString = art_quick_resolve_string;
// Field
- qpoints->pSet32Instance = art_quick_set32_instance_from_code;
- qpoints->pSet32Static = art_quick_set32_static_from_code;
- qpoints->pSet64Instance = art_quick_set64_instance_from_code;
- qpoints->pSet64Static = art_quick_set64_static_from_code;
- qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
- qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
- qpoints->pGet32Instance = art_quick_get32_instance_from_code;
- qpoints->pGet64Instance = art_quick_get64_instance_from_code;
- qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
- qpoints->pGet32Static = art_quick_get32_static_from_code;
- qpoints->pGet64Static = art_quick_get64_static_from_code;
- qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+ qpoints->pSet32Instance = art_quick_set32_instance;
+ qpoints->pSet32Static = art_quick_set32_static;
+ qpoints->pSet64Instance = art_quick_set64_instance;
+ qpoints->pSet64Static = art_quick_set64_static;
+ qpoints->pSetObjInstance = art_quick_set_obj_instance;
+ qpoints->pSetObjStatic = art_quick_set_obj_static;
+ qpoints->pGet32Instance = art_quick_get32_instance;
+ qpoints->pGet64Instance = art_quick_get64_instance;
+ qpoints->pGetObjInstance = art_quick_get_obj_instance;
+ qpoints->pGet32Static = art_quick_get32_static;
+ qpoints->pGet64Static = art_quick_get64_static;
+ qpoints->pGetObjStatic = art_quick_get_obj_static;
// FillArray
- qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
// JNI
qpoints->pJniMethodStart = JniMethodStart;
@@ -178,8 +191,8 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
- qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ qpoints->pLockObject = art_quick_lock_object;
+ qpoints->pUnlockObject = art_quick_unlock_object;
// Math
qpoints->pCmpgDouble = CmpgDouble;
@@ -203,10 +216,6 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pShrLong = art_quick_shr_long;
qpoints->pUshrLong = art_quick_ushr_long;
- // Interpreter
- qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
-
// Intrinsics
qpoints->pIndexOf = art_quick_indexof;
qpoints->pMemcmp16 = __memcmp16;
@@ -214,7 +223,8 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pMemcpy = memcpy;
// Invocation
- qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+ qpoints->pQuickResolutionTrampoline = art_quick_resolution_trampoline;
+ qpoints->pQuickToInterpreterBridge = art_quick_to_interpreter_bridge;
qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -223,19 +233,16 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
// Thread
- qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
- qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspend = CheckSuspendFromCode;
+ qpoints->pTestSuspend = art_quick_test_suspend;
// Throws
- qpoints->pDeliverException = art_quick_deliver_exception_from_code;
- qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
- qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
- qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
- qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
- qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-
- // Portable
- ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+ qpoints->pDeliverException = art_quick_deliver_exception;
+ qpoints->pThrowArrayBounds = art_quick_throw_array_bounds;
+ qpoints->pThrowDivZero = art_quick_throw_div_zero;
+ qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
+ qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
+ qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
};
} // namespace art
diff --git a/runtime/arch/arm/jni_entrypoints_arm.S b/runtime/arch/arm/jni_entrypoints_arm.S
index 0af470c..f51f121 100644
--- a/runtime/arch/arm/jni_entrypoints_arm.S
+++ b/runtime/arch/arm/jni_entrypoints_arm.S
@@ -30,8 +30,7 @@ ENTRY art_jni_dlsym_lookup_stub
sub sp, #12 @ pad stack pointer to align frame
.pad #12
.cfi_adjust_cfa_offset 12
- mov r0, r9 @ pass Thread::Current
- blx artFindNativeMethod @ (Thread*)
+ blx artFindNativeMethod
mov r12, r0 @ save result in r12
add sp, #12 @ restore stack pointer
.cfi_adjust_cfa_offset -12
@@ -46,7 +45,7 @@ END art_jni_dlsym_lookup_stub
* Entry point of native methods when JNI bug compatibility is enabled.
*/
.extern artWorkAroundAppJniBugs
-ENTRY art_quick_work_around_app_jni_bugs
+ENTRY art_work_around_app_jni_bugs
@ save registers that may contain arguments and LR that will be crushed by a call
push {r0-r3, lr}
.save {r0-r3, lr}
@@ -64,4 +63,4 @@ ENTRY art_quick_work_around_app_jni_bugs
pop {r0-r3, lr} @ restore possibly modified argument registers
.cfi_adjust_cfa_offset -16
bx r12 @ tail call into JNI routine
-END art_quick_work_around_app_jni_bugs
+END art_work_around_app_jni_bugs
diff --git a/runtime/arch/arm/portable_entrypoints_arm.S b/runtime/arch/arm/portable_entrypoints_arm.S
index 56333ba..adfd22b 100644
--- a/runtime/arch/arm/portable_entrypoints_arm.S
+++ b/runtime/arch/arm/portable_entrypoints_arm.S
@@ -96,3 +96,6 @@ ENTRY art_portable_proxy_invoke_handler
.cfi_adjust_cfa_offset -48
bx lr @ return
END art_portable_proxy_invoke_handler
+
+UNIMPLEMENTED art_portable_resolution_trampoline
+UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 4de8c4d..d9bb433 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -159,33 +159,33 @@ END \c_name
* Called by managed code, saves callee saves and then calls artThrowException
* that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception_from_code, artDeliverExceptionFromCode
+ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_code, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero_from_code, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds_from_code, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow_from_code, artThrowStackOverflowFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
/*
* Called by managed code to create and deliver a NoSuchMethodError.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method_from_code, artThrowNoSuchMethodFromCode
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
/*
* All generated callsites for interface invokes and invocation slow paths will load arguments
@@ -296,7 +296,7 @@ END art_quick_do_long_jump
* failure.
*/
.extern artHandleFillArrayDataFromCode
-ENTRY art_quick_handle_fill_data_from_code
+ENTRY art_quick_handle_fill_data
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -305,25 +305,25 @@ ENTRY art_quick_handle_fill_data_from_code
cmp r0, #0 @ success?
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_handle_fill_data_from_code
+END art_quick_handle_fill_data
/*
* Entry from managed code that calls artLockObjectFromCode, may block for GC.
*/
.extern artLockObjectFromCode
-ENTRY art_quick_lock_object_from_code
+ENTRY art_quick_lock_object
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case we block
mov r1, r9 @ pass Thread::Current
mov r2, sp @ pass SP
bl artLockObjectFromCode @ (Object* obj, Thread*, SP)
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
-END art_quick_lock_object_from_code
+END art_quick_lock_object
/*
* Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
*/
.extern artUnlockObjectFromCode
-ENTRY art_quick_unlock_object_from_code
+ENTRY art_quick_unlock_object
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
mov r1, r9 @ pass Thread::Current
mov r2, sp @ pass SP
@@ -332,13 +332,13 @@ ENTRY art_quick_unlock_object_from_code
cmp r0, #0 @ success?
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_unlock_object_from_code
+END art_quick_unlock_object
/*
* Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
*/
.extern artCheckCastFromCode
-ENTRY art_quick_check_cast_from_code
+ENTRY art_quick_check_cast
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -347,14 +347,14 @@ ENTRY art_quick_check_cast_from_code
cmp r0, #0 @ success?
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_check_cast_from_code
+END art_quick_check_cast
/*
* Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
* failure.
*/
.extern artCanPutArrayElementFromCode
-ENTRY art_quick_can_put_array_element_from_code
+ENTRY art_quick_can_put_array_element
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -363,7 +363,7 @@ ENTRY art_quick_can_put_array_element_from_code
cmp r0, #0 @ success?
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_can_put_array_element_from_code
+END art_quick_can_put_array_element
/*
* Entry from managed code when uninitialized static storage, this stub will run the class
@@ -371,7 +371,7 @@ END art_quick_can_put_array_element_from_code
* returned.
*/
.extern artInitializeStaticStorageFromCode
-ENTRY art_quick_initialize_static_storage_from_code
+ENTRY art_quick_initialize_static_storage
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -381,13 +381,13 @@ ENTRY art_quick_initialize_static_storage_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_initialize_static_storage_from_code
+END art_quick_initialize_static_storage
/*
* Entry from managed code when dex cache misses for a type_idx
*/
.extern artInitializeTypeFromCode
-ENTRY art_quick_initialize_type_from_code
+ENTRY art_quick_initialize_type
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -397,14 +397,14 @@ ENTRY art_quick_initialize_type_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_initialize_type_from_code
+END art_quick_initialize_type
/*
* Entry from managed code when type_idx needs to be checked for access and dex cache may also
* miss.
*/
.extern artInitializeTypeAndVerifyAccessFromCode
-ENTRY art_quick_initialize_type_and_verify_access_from_code
+ENTRY art_quick_initialize_type_and_verify_access
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -414,13 +414,13 @@ ENTRY art_quick_initialize_type_and_verify_access_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_initialize_type_and_verify_access_from_code
+END art_quick_initialize_type_and_verify_access
/*
* Called by managed code to resolve a static field and load a 32-bit primitive value.
*/
.extern artGet32StaticFromCode
-ENTRY art_quick_get32_static_from_code
+ENTRY art_quick_get32_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r1, [sp, #32] @ pass referrer
mov r2, r9 @ pass Thread::Current
@@ -431,13 +431,13 @@ ENTRY art_quick_get32_static_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get32_static_from_code
+END art_quick_get32_static
/*
* Called by managed code to resolve a static field and load a 64-bit primitive value.
*/
.extern artGet64StaticFromCode
-ENTRY art_quick_get64_static_from_code
+ENTRY art_quick_get64_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r1, [sp, #32] @ pass referrer
mov r2, r9 @ pass Thread::Current
@@ -448,13 +448,13 @@ ENTRY art_quick_get64_static_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get64_static_from_code
+END art_quick_get64_static
/*
* Called by managed code to resolve a static field and load an object reference.
*/
.extern artGetObjStaticFromCode
-ENTRY art_quick_get_obj_static_from_code
+ENTRY art_quick_get_obj_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r1, [sp, #32] @ pass referrer
mov r2, r9 @ pass Thread::Current
@@ -465,13 +465,13 @@ ENTRY art_quick_get_obj_static_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get_obj_static_from_code
+END art_quick_get_obj_static
/*
* Called by managed code to resolve an instance field and load a 32-bit primitive value.
*/
.extern artGet32InstanceFromCode
-ENTRY art_quick_get32_instance_from_code
+ENTRY art_quick_get32_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
@@ -484,13 +484,13 @@ ENTRY art_quick_get32_instance_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get32_instance_from_code
+END art_quick_get32_instance
/*
* Called by managed code to resolve an instance field and load a 64-bit primitive value.
*/
.extern artGet64InstanceFromCode
-ENTRY art_quick_get64_instance_from_code
+ENTRY art_quick_get64_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
@@ -506,13 +506,13 @@ ENTRY art_quick_get64_instance_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get64_instance_from_code
+END art_quick_get64_instance
/*
* Called by managed code to resolve an instance field and load an object reference.
*/
.extern artGetObjInstanceFromCode
-ENTRY art_quick_get_obj_instance_from_code
+ENTRY art_quick_get_obj_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
@@ -528,13 +528,13 @@ ENTRY art_quick_get_obj_instance_from_code
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_get_obj_instance_from_code
+END art_quick_get_obj_instance
/*
* Called by managed code to resolve a static field and store a 32-bit primitive value.
*/
.extern artSet32StaticFromCode
-ENTRY art_quick_set32_static_from_code
+ENTRY art_quick_set32_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
@@ -549,14 +549,14 @@ ENTRY art_quick_set32_static_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set32_static_from_code
+END art_quick_set32_static
/*
* Called by managed code to resolve a static field and store a 64-bit primitive value.
* On entry r0 holds field index, r1:r2 hold new_val
*/
.extern artSet64StaticFromCode
-ENTRY art_quick_set64_static_from_code
+ENTRY art_quick_set64_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r2 @ pass one half of wide argument
mov r2, r1 @ pass other half of wide argument
@@ -575,13 +575,13 @@ ENTRY art_quick_set64_static_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set64_static_from_code
+END art_quick_set64_static
/*
* Called by managed code to resolve a static field and store an object reference.
*/
.extern artSetObjStaticFromCode
-ENTRY art_quick_set_obj_static_from_code
+ENTRY art_quick_set_obj_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
@@ -596,13 +596,13 @@ ENTRY art_quick_set_obj_static_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set_obj_static_from_code
+END art_quick_set_obj_static
/*
* Called by managed code to resolve an instance field and store a 32-bit primitive value.
*/
.extern artSet32InstanceFromCode
-ENTRY art_quick_set32_instance_from_code
+ENTRY art_quick_set32_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r3, [sp, #32] @ pass referrer
mov r12, sp @ save SP
@@ -621,13 +621,13 @@ ENTRY art_quick_set32_instance_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set32_instance_from_code
+END art_quick_set32_instance
/*
* Called by managed code to resolve an instance field and store a 64-bit primitive value.
*/
.extern artSet32InstanceFromCode
-ENTRY art_quick_set64_instance_from_code
+ENTRY art_quick_set64_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r12, sp @ save SP
sub sp, #8 @ grow frame for alignment with stack args
@@ -644,13 +644,13 @@ ENTRY art_quick_set64_instance_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set64_instance_from_code
+END art_quick_set64_instance
/*
* Called by managed code to resolve an instance field and store an object reference.
*/
.extern artSetObjInstanceFromCode
-ENTRY art_quick_set_obj_instance_from_code
+ENTRY art_quick_set_obj_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r3, [sp, #32] @ pass referrer
mov r12, sp @ save SP
@@ -668,7 +668,7 @@ ENTRY art_quick_set_obj_instance_from_code
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_set_obj_instance_from_code
+END art_quick_set_obj_instance
/*
* Entry from managed code to resolve a string, this stub will allocate a String and deliver an
@@ -677,7 +677,7 @@ END art_quick_set_obj_instance_from_code
* performed.
*/
.extern artResolveStringFromCode
-ENTRY art_quick_resolve_string_from_code
+ENTRY art_quick_resolve_string
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -687,13 +687,13 @@ ENTRY art_quick_resolve_string_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_resolve_string_from_code
+END art_quick_resolve_string
/*
* Called by managed code to allocate an object
*/
.extern artAllocObjectFromCode
-ENTRY art_quick_alloc_object_from_code
+ENTRY art_quick_alloc_object
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -702,14 +702,14 @@ ENTRY art_quick_alloc_object_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_alloc_object_from_code
+END art_quick_alloc_object
/*
* Called by managed code to allocate an object when the caller doesn't know whether it has
* access to the created type.
*/
.extern artAllocObjectFromCodeWithAccessCheck
-ENTRY art_quick_alloc_object_from_code_with_access_check
+ENTRY art_quick_alloc_object_with_access_check
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -718,13 +718,13 @@ ENTRY art_quick_alloc_object_from_code_with_access_check
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_alloc_object_from_code_with_access_check
+END art_quick_alloc_object_with_access_check
/*
* Called by managed code to allocate an array.
*/
.extern artAllocArrayFromCode
-ENTRY art_quick_alloc_array_from_code
+ENTRY art_quick_alloc_array
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
mov r12, sp
@@ -739,14 +739,14 @@ ENTRY art_quick_alloc_array_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_alloc_array_from_code
+END art_quick_alloc_array
/*
* Called by managed code to allocate an array when the caller doesn't know whether it has
* access to the created type.
*/
.extern artAllocArrayFromCodeWithAccessCheck
-ENTRY art_quick_alloc_array_from_code_with_access_check
+ENTRY art_quick_alloc_array_with_access_check
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
mov r12, sp
@@ -761,13 +761,13 @@ ENTRY art_quick_alloc_array_from_code_with_access_check
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_alloc_array_from_code_with_access_check
+END art_quick_alloc_array_with_access_check
/*
* Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
*/
.extern artCheckAndAllocArrayFromCode
-ENTRY art_quick_check_and_alloc_array_from_code
+ENTRY art_quick_check_and_alloc_array
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
mov r12, sp
@@ -782,13 +782,13 @@ ENTRY art_quick_check_and_alloc_array_from_code
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_check_and_alloc_array_from_code
+END art_quick_check_and_alloc_array
/*
* Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
*/
.extern artCheckAndAllocArrayFromCodeWithAccessCheck
-ENTRY art_quick_check_and_alloc_array_from_code_with_access_check
+ENTRY art_quick_check_and_alloc_array_with_access_check
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
mov r12, sp
@@ -803,7 +803,7 @@ ENTRY art_quick_check_and_alloc_array_from_code_with_access_check
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_check_and_alloc_array_from_code_with_access_check
+END art_quick_check_and_alloc_array_with_access_check
/*
* Called by managed code when the value in rSUSPEND has been decremented to 0.
@@ -842,13 +842,33 @@ ENTRY art_quick_proxy_invoke_handler
DELIVER_PENDING_EXCEPTION
END art_quick_proxy_invoke_handler
- .extern artInterpreterEntry
-ENTRY art_quick_interpreter_entry
+ .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ blx artQuickResolutionTrampoline @ (Method* called, receiver, Thread*, SP)
+ cmp r0, #0 @ is code pointer null?
+ beq 1f @ goto exception
+ mov r12, r0
+ ldr r0, [sp, #0] @ load resolved method in r0
+ ldr r1, [sp, #8] @ restore non-callee save r1
+ ldrd r2, [sp, #12] @ restore non-callee saves r2-r3
+ ldr lr, [sp, #44] @ restore lr
+ add sp, #48 @ rewind sp
+ .cfi_adjust_cfa_offset -48
+ bx r12 @ tail-call into actual code
+1:
+ RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ DELIVER_PENDING_EXCEPTION
+END art_quick_resolution_trampoline
+
+ .extern artQuickToInterpreterBridge
+ENTRY art_quick_to_interpreter_bridge
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
- str r0, [sp, #0] @ place proxy method at bottom of frame
mov r1, r9 @ pass Thread::Current
mov r2, sp @ pass SP
- blx artInterpreterEntry @ (Method* method, Thread*, SP)
+ blx artQuickToInterpreterBridge @ (Method* method, Thread*, SP)
ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
ldr lr, [sp, #44] @ restore lr
add sp, #48 @ pop frame
@@ -856,14 +876,14 @@ ENTRY art_quick_interpreter_entry
cmp r12, #0 @ success if no exception is pending
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
-END art_quick_interpreter_entry
+END art_quick_to_interpreter_bridge
/*
* Routine that intercepts method calls and returns.
*/
.extern artInstrumentationMethodEntryFromCode
.extern artInstrumentationMethodExitFromCode
-ENTRY art_quick_instrumentation_entry_from_code
+ENTRY art_quick_instrumentation_entry
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
str r0, [sp, #4] @ preserve r0
mov r12, sp @ remember sp
@@ -879,11 +899,11 @@ ENTRY art_quick_instrumentation_entry_from_code
mov r12, r0 @ r12 holds reference to code
ldr r0, [sp, #4] @ restore r0
RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
- blx r12 @ call method with lr set to art_quick_instrumentation_exit_from_code
-END art_quick_instrumentation_entry_from_code
- .type art_quick_instrumentation_exit_from_code, #function
- .global art_quick_instrumentation_exit_from_code
-art_quick_instrumentation_exit_from_code:
+ blx r12 @ call method with lr set to art_quick_instrumentation_exit
+END art_quick_instrumentation_entry
+ .type art_quick_instrumentation_exit, #function
+ .global art_quick_instrumentation_exit
+art_quick_instrumentation_exit:
.cfi_startproc
.fnstart
mov lr, #0 @ link register is to here, so clobber with 0 for later checks
@@ -912,7 +932,7 @@ art_quick_instrumentation_exit_from_code:
add sp, #32 @ remove callee save frame
.cfi_adjust_cfa_offset -32
bx r2 @ return
-END art_quick_instrumentation_exit_from_code
+END art_quick_instrumentation_exit
/*
* Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
@@ -927,25 +947,6 @@ ENTRY art_quick_deoptimize
END art_quick_deoptimize
/*
- * Portable abstract method error stub. r0 contains method* on entry. SP unused in portable.
- */
- .extern artThrowAbstractMethodErrorFromCode
-ENTRY art_portable_abstract_method_error_stub
- mov r1, r9 @ pass Thread::Current
- b artThrowAbstractMethodErrorFromCode @ (Method*, Thread*, SP)
-END art_portable_abstract_method_error_stub
-
- /*
- * Quick abstract method error stub. r0 contains method* on entry.
- */
-ENTRY art_quick_abstract_method_error_stub
- SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
- mov r1, r9 @ pass Thread::Current
- mov r2, sp @ pass SP
- b artThrowAbstractMethodErrorFromCode @ (Method*, Thread*, SP)
-END art_quick_abstract_method_error_stub
-
- /*
* Signed 64-bit integer multiply.
*
* Consider WXxYZ (r1r0 x r3r2) with a long multiply:
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 8a34b9d..fe932d2 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -38,4 +38,12 @@
.cpload $t9
.endm
+.macro UNIMPLEMENTED name
+ ENTRY \name
+ break
+ break
+ END \name
+.endm
+
+
#endif // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index 0a62a40..a18079b 100644
--- a/runtime/arch/mips/entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -21,49 +21,61 @@
namespace art {
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterperterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+
+// Portable entrypoints.
+extern "C" void art_portable_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_portable_to_interpreter_bridge(mirror::AbstractMethod*);
+
// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_with_access_check(uint32_t, void*, int32_t);
// Cast entrypoints.
extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
+extern "C" void art_quick_can_put_array_element(void*, void*);
+extern "C" void art_quick_check_cast(void*, void*);
// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+extern "C" void* art_quick_initialize_static_storage(uint32_t, void*);
+extern "C" void* art_quick_initialize_type(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, void*);
+extern "C" void* art_quick_resolve_string(void*, uint32_t);
// Exception entrypoints.
extern "C" void* GetAndClearException(Thread*);
// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+extern "C" int art_quick_set32_instance(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static(uint32_t);
+extern "C" int64_t art_quick_get64_instance(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static(uint32_t);
+extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static(uint32_t);
// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+extern "C" void art_quick_handle_fill_data(void*, void*);
// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_unlock_object_from_code(void*);
+extern "C" void art_quick_lock_object(void*);
+extern "C" void art_quick_unlock_object(void*);
// Math entrypoints.
extern int32_t CmpgDouble(double a, double b);
@@ -95,26 +107,14 @@ extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-
// Intrinsic entrypoints.
extern "C" int32_t __memcmp16(void*, void*, int32_t);
extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
extern "C" int32_t art_quick_string_compareto(void*, void*);
// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_quick_to_interpreter_bridge(mirror::AbstractMethod*);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -127,49 +127,61 @@ extern void CheckSuspendFromCode(Thread* thread);
extern "C" void art_quick_test_suspend();
// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+extern "C" void art_quick_deliver_exception(void*);
+extern "C" void art_quick_throw_array_bounds(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero();
+extern "C" void art_quick_throw_no_such_method(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception();
+extern "C" void art_quick_throw_stack_overflow(void*);
+
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
+ // Interpreter
+ ipoints->pInterpreterToInterpreterBridge = artInterpreterToInterpreterBridge;
+ ipoints->pInterpreterToCompiledCodeBridge = artInterperterToCompiledCodeBridge;
+
+ // JNI
+ jpoints->pDlsymLookup = art_jni_dlsym_lookup_stub;
+
+ // Portable
+ ppoints->pPortableResolutionTrampoline = art_portable_resolution_trampoline;
+ ppoints->pPortableToInterpreterBridge = art_portable_to_interpreter_bridge;
+
// Alloc
- qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
- qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
- qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
- qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
- qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
- qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+ qpoints->pAllocArray = art_quick_alloc_array;
+ qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check;
+ qpoints->pAllocObject = art_quick_alloc_object;
+ qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check;
+ qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array;
+ qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check;
// Cast
- qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
- qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
- qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+ qpoints->pInstanceofNonTrivial = artIsAssignableFromCode;
+ qpoints->pCanPutArrayElement = art_quick_can_put_array_element;
+ qpoints->pCheckCast = art_quick_check_cast;
// DexCache
- qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
- qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
- qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
- qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+ qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
+ qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access;
+ qpoints->pInitializeType = art_quick_initialize_type;
+ qpoints->pResolveString = art_quick_resolve_string;
// Field
- qpoints->pSet32Instance = art_quick_set32_instance_from_code;
- qpoints->pSet32Static = art_quick_set32_static_from_code;
- qpoints->pSet64Instance = art_quick_set64_instance_from_code;
- qpoints->pSet64Static = art_quick_set64_static_from_code;
- qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
- qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
- qpoints->pGet32Instance = art_quick_get32_instance_from_code;
- qpoints->pGet64Instance = art_quick_get64_instance_from_code;
- qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
- qpoints->pGet32Static = art_quick_get32_static_from_code;
- qpoints->pGet64Static = art_quick_get64_static_from_code;
- qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+ qpoints->pSet32Instance = art_quick_set32_instance;
+ qpoints->pSet32Static = art_quick_set32_static;
+ qpoints->pSet64Instance = art_quick_set64_instance;
+ qpoints->pSet64Static = art_quick_set64_static;
+ qpoints->pSetObjInstance = art_quick_set_obj_instance;
+ qpoints->pSetObjStatic = art_quick_set_obj_static;
+ qpoints->pGet32Instance = art_quick_get32_instance;
+ qpoints->pGet64Instance = art_quick_get64_instance;
+ qpoints->pGetObjInstance = art_quick_get_obj_instance;
+ qpoints->pGet32Static = art_quick_get32_static;
+ qpoints->pGet64Static = art_quick_get64_static;
+ qpoints->pGetObjStatic = art_quick_get_obj_static;
// FillArray
- qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
// JNI
qpoints->pJniMethodStart = JniMethodStart;
@@ -180,8 +192,8 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
- qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ qpoints->pLockObject = art_quick_lock_object;
+ qpoints->pUnlockObject = art_quick_unlock_object;
// Math
qpoints->pCmpgDouble = CmpgDouble;
@@ -204,10 +216,6 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pShrLong = art_quick_shr_long;
qpoints->pUshrLong = art_quick_ushr_long;
- // Interpreter
- qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
-
// Intrinsics
qpoints->pIndexOf = art_quick_indexof;
qpoints->pMemcmp16 = __memcmp16;
@@ -215,7 +223,8 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pMemcpy = memcpy;
// Invocation
- qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+ qpoints->pQuickResolutionTrampoline = art_quick_resolution_trampoline;
+ qpoints->pQuickToInterpreterBridge = art_quick_to_interpreter_bridge;
qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -224,19 +233,16 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
// Thread
- qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
- qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspend = CheckSuspendFromCode;
+ qpoints->pTestSuspend = art_quick_test_suspend;
// Throws
- qpoints->pDeliverException = art_quick_deliver_exception_from_code;
- qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
- qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
- qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
- qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
- qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-
- // Portable
- ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+ qpoints->pDeliverException = art_quick_deliver_exception;
+ qpoints->pThrowArrayBounds = art_quick_throw_array_bounds;
+ qpoints->pThrowDivZero = art_quick_throw_div_zero;
+ qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
+ qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
+ qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
};
} // namespace art
diff --git a/runtime/arch/mips/jni_entrypoints_mips.S b/runtime/arch/mips/jni_entrypoints_mips.S
index fca6d77..ad7c021 100644
--- a/runtime/arch/mips/jni_entrypoints_mips.S
+++ b/runtime/arch/mips/jni_entrypoints_mips.S
@@ -59,7 +59,7 @@ END art_jni_dlsym_lookup_stub
* Entry point of native methods when JNI bug compatibility is enabled.
*/
.extern artWorkAroundAppJniBugs
-ENTRY art_quick_work_around_app_jni_bugs
+ENTRY art_work_around_app_jni_bugs
GENERATE_GLOBAL_POINTER
# save registers that may contain arguments and LR that will be crushed by a call
addiu $sp, $sp, -32
@@ -86,4 +86,4 @@ ENTRY art_quick_work_around_app_jni_bugs
jr $t9 # tail call into JNI routine
addiu $sp, $sp, 32
.cfi_adjust_cfa_offset -32
-END art_quick_work_around_app_jni_bugs
+END art_work_around_app_jni_bugs
diff --git a/runtime/arch/mips/portable_entrypoints_mips.S b/runtime/arch/mips/portable_entrypoints_mips.S
index e7a9b0f..9208a8a 100644
--- a/runtime/arch/mips/portable_entrypoints_mips.S
+++ b/runtime/arch/mips/portable_entrypoints_mips.S
@@ -61,13 +61,5 @@ ENTRY art_portable_proxy_invoke_handler
.cfi_adjust_cfa_offset -64
END art_portable_proxy_invoke_handler
- /*
- * Portable abstract method error stub. $a0 contains method* on entry. SP unused in portable.
- */
- .extern artThrowAbstractMethodErrorFromCode
-ENTRY art_portable_abstract_method_error_stub
- GENERATE_GLOBAL_POINTER
- la $t9, artThrowAbstractMethodErrorFromCode
- jr $t9 # (Method*, Thread*, SP)
- move $a1, $s1 # pass Thread::Current
-END art_portable_abstract_method_error_stub
+UNIMPLEMENTED art_portable_resolution_trampoline
+UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index d32a2b4..004fda6 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -143,7 +143,7 @@
lw $a1, 4($sp) # restore non-callee save $a1
lw $a2, 8($sp) # restore non-callee save $a2
lw $a3, 12($sp) # restore non-callee save $a3
- addiu $sp, $sp, 64 # strip frame
+ addiu $sp, $sp, 64 # pop frame
.cfi_adjust_cfa_offset -64
.endm
@@ -268,79 +268,79 @@ END art_quick_do_long_jump
* the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
* the bottom of the thread. On entry r0 holds Throwable*
*/
-ENTRY art_quick_deliver_exception_from_code
+ENTRY art_quick_deliver_exception
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a1, rSELF # pass Thread::Current
la $t9, artDeliverExceptionFromCode
jr $t9 # artDeliverExceptionFromCode(Throwable*, Thread*, $sp)
move $a2, $sp # pass $sp
-END art_quick_deliver_exception_from_code
+END art_quick_deliver_exception
/*
* Called by managed code to create and deliver a NullPointerException
*/
.extern artThrowNullPointerExceptionFromCode
-ENTRY art_quick_throw_null_pointer_exception_from_code
+ENTRY art_quick_throw_null_pointer_exception
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a0, rSELF # pass Thread::Current
la $t9, artThrowNullPointerExceptionFromCode
jr $t9 # artThrowNullPointerExceptionFromCode(Thread*, $sp)
move $a1, $sp # pass $sp
-END art_quick_throw_null_pointer_exception_from_code
+END art_quick_throw_null_pointer_exception
/*
* Called by managed code to create and deliver an ArithmeticException
*/
.extern artThrowDivZeroFromCode
-ENTRY art_quick_throw_div_zero_from_code
+ENTRY art_quick_throw_div_zero
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a0, rSELF # pass Thread::Current
la $t9, artThrowDivZeroFromCode
jr $t9 # artThrowDivZeroFromCode(Thread*, $sp)
move $a1, $sp # pass $sp
-END art_quick_throw_div_zero_from_code
+END art_quick_throw_div_zero
/*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
*/
.extern artThrowArrayBoundsFromCode
-ENTRY art_quick_throw_array_bounds_from_code
+ENTRY art_quick_throw_array_bounds
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a2, rSELF # pass Thread::Current
la $t9, artThrowArrayBoundsFromCode
jr $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*, $sp)
move $a3, $sp # pass $sp
-END art_quick_throw_array_bounds_from_code
+END art_quick_throw_array_bounds
/*
* Called by managed code to create and deliver a StackOverflowError.
*/
.extern artThrowStackOverflowFromCode
-ENTRY art_quick_throw_stack_overflow_from_code
+ENTRY art_quick_throw_stack_overflow
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a0, rSELF # pass Thread::Current
la $t9, artThrowStackOverflowFromCode
jr $t9 # artThrowStackOverflowFromCode(Thread*, $sp)
move $a1, $sp # pass $sp
-END art_quick_throw_stack_overflow_from_code
+END art_quick_throw_stack_overflow
/*
* Called by managed code to create and deliver a NoSuchMethodError.
*/
.extern artThrowNoSuchMethodFromCode
-ENTRY art_quick_throw_no_such_method_from_code
+ENTRY art_quick_throw_no_such_method
GENERATE_GLOBAL_POINTER
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
move $a1, rSELF # pass Thread::Current
la $t9, artThrowNoSuchMethodFromCode
jr $t9 # artThrowNoSuchMethodFromCode(method_idx, Thread*, $sp)
move $a2, $sp # pass $sp
-END art_quick_throw_no_such_method_from_code
+END art_quick_throw_no_such_method
/*
* All generated callsites for interface invokes and invocation slow paths will load arguments
@@ -466,67 +466,67 @@ END art_quick_invoke_stub
* failure.
*/
.extern artHandleFillArrayDataFromCode
-ENTRY art_quick_handle_fill_data_from_code
+ENTRY art_quick_handle_fill_data
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
move $a2, rSELF # pass Thread::Current
jal artHandleFillArrayDataFromCode # (Array*, const DexFile::Payload*, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_ZERO
-END art_quick_handle_fill_data_from_code
+END art_quick_handle_fill_data
/*
* Entry from managed code that calls artLockObjectFromCode, may block for GC.
*/
.extern artLockObjectFromCode
-ENTRY art_quick_lock_object_from_code
+ENTRY art_quick_lock_object
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case we block
move $a1, rSELF # pass Thread::Current
jal artLockObjectFromCode # (Object* obj, Thread*, $sp)
move $a2, $sp # pass $sp
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
-END art_quick_lock_object_from_code
+END art_quick_lock_object
/*
* Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
*/
.extern artUnlockObjectFromCode
-ENTRY art_quick_unlock_object_from_code
+ENTRY art_quick_unlock_object
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
move $a1, rSELF # pass Thread::Current
jal artUnlockObjectFromCode # (Object* obj, Thread*, $sp)
move $a2, $sp # pass $sp
RETURN_IF_ZERO
-END art_quick_unlock_object_from_code
+END art_quick_unlock_object
/*
* Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
*/
.extern artCheckCastFromCode
-ENTRY art_quick_check_cast_from_code
+ENTRY art_quick_check_cast
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
move $a2, rSELF # pass Thread::Current
jal artCheckCastFromCode # (Class* a, Class* b, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_ZERO
-END art_quick_check_cast_from_code
+END art_quick_check_cast
/*
* Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
* failure.
*/
.extern artCanPutArrayElementFromCode
-ENTRY art_quick_can_put_array_element_from_code
+ENTRY art_quick_can_put_array_element
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case exception allocation triggers GC
move $a2, rSELF # pass Thread::Current
jal artCanPutArrayElementFromCode # (Object* element, Class* array_class, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_ZERO
-END art_quick_can_put_array_element_from_code
+END art_quick_can_put_array_element
/*
* Entry from managed code when uninitialized static storage, this stub will run the class
@@ -534,7 +534,7 @@ END art_quick_can_put_array_element_from_code
* returned.
*/
.extern artInitializeStaticStorageFromCode
-ENTRY art_quick_initialize_static_storage_from_code
+ENTRY art_quick_initialize_static_storage
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
@@ -542,13 +542,13 @@ ENTRY art_quick_initialize_static_storage_from_code
jal artInitializeStaticStorageFromCode
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_initialize_static_storage_from_code
+END art_quick_initialize_static_storage
/*
* Entry from managed code when dex cache misses for a type_idx.
*/
.extern artInitializeTypeFromCode
-ENTRY art_quick_initialize_type_from_code
+ENTRY art_quick_initialize_type
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
@@ -556,14 +556,14 @@ ENTRY art_quick_initialize_type_from_code
jal artInitializeTypeFromCode
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_initialize_type_from_code
+END art_quick_initialize_type
/*
* Entry from managed code when type_idx needs to be checked for access and dex cache may also
* miss.
*/
.extern artInitializeTypeAndVerifyAccessFromCode
-ENTRY art_quick_initialize_type_and_verify_access_from_code
+ENTRY art_quick_initialize_type_and_verify_access
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
@@ -571,13 +571,13 @@ ENTRY art_quick_initialize_type_and_verify_access_from_code
jal artInitializeTypeAndVerifyAccessFromCode
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_initialize_type_and_verify_access_from_code
+END art_quick_initialize_type_and_verify_access
/*
* Called by managed code to resolve a static field and load a 32-bit primitive value.
*/
.extern artGet32StaticFromCode
-ENTRY art_quick_get32_static_from_code
+ENTRY art_quick_get32_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a1, 64($sp) # pass referrer's Method*
@@ -585,13 +585,13 @@ ENTRY art_quick_get32_static_from_code
jal artGet32StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get32_static_from_code
+END art_quick_get32_static
/*
* Called by managed code to resolve a static field and load a 64-bit primitive value.
*/
.extern artGet64StaticFromCode
-ENTRY art_quick_get64_static_from_code
+ENTRY art_quick_get64_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a1, 64($sp) # pass referrer's Method*
@@ -599,13 +599,13 @@ ENTRY art_quick_get64_static_from_code
jal artGet64StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get64_static_from_code
+END art_quick_get64_static
/*
* Called by managed code to resolve a static field and load an object reference.
*/
.extern artGetObjStaticFromCode
-ENTRY art_quick_get_obj_static_from_code
+ENTRY art_quick_get_obj_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a1, 64($sp) # pass referrer's Method*
@@ -613,13 +613,13 @@ ENTRY art_quick_get_obj_static_from_code
jal artGetObjStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get_obj_static_from_code
+END art_quick_get_obj_static
/*
* Called by managed code to resolve an instance field and load a 32-bit primitive value.
*/
.extern artGet32InstanceFromCode
-ENTRY art_quick_get32_instance_from_code
+ENTRY art_quick_get32_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a2, 64($sp) # pass referrer's Method*
@@ -627,13 +627,13 @@ ENTRY art_quick_get32_instance_from_code
jal artGet32InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get32_instance_from_code
+END art_quick_get32_instance
/*
* Called by managed code to resolve an instance field and load a 64-bit primitive value.
*/
.extern artGet64InstanceFromCode
-ENTRY art_quick_get64_instance_from_code
+ENTRY art_quick_get64_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a2, 64($sp) # pass referrer's Method*
@@ -641,13 +641,13 @@ ENTRY art_quick_get64_instance_from_code
jal artGet64InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get64_instance_from_code
+END art_quick_get64_instance
/*
* Called by managed code to resolve an instance field and load an object reference.
*/
.extern artGetObjInstanceFromCode
-ENTRY art_quick_get_obj_instance_from_code
+ENTRY art_quick_get_obj_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a2, 64($sp) # pass referrer's Method*
@@ -655,13 +655,13 @@ ENTRY art_quick_get_obj_instance_from_code
jal artGetObjInstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
-END art_quick_get_obj_instance_from_code
+END art_quick_get_obj_instance
/*
* Called by managed code to resolve a static field and store a 32-bit primitive value.
*/
.extern artSet32StaticFromCode
-ENTRY art_quick_set32_static_from_code
+ENTRY art_quick_set32_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a2, 64($sp) # pass referrer's Method*
@@ -669,13 +669,13 @@ ENTRY art_quick_set32_static_from_code
jal artSet32StaticFromCode # (field_idx, new_val, referrer, Thread*, $sp)
sw $sp, 16($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set32_static_from_code
+END art_quick_set32_static
/*
* Called by managed code to resolve a static field and store a 64-bit primitive value.
*/
.extern artSet32StaticFromCode
-ENTRY art_quick_set64_static_from_code
+ENTRY art_quick_set64_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a1, 64($sp) # pass referrer's Method*
@@ -683,13 +683,13 @@ ENTRY art_quick_set64_static_from_code
jal artSet64StaticFromCode # (field_idx, referrer, new_val, Thread*, $sp)
sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set64_static_from_code
+END art_quick_set64_static
/*
* Called by managed code to resolve a static field and store an object reference.
*/
.extern artSetObjStaticFromCode
-ENTRY art_quick_set_obj_static_from_code
+ENTRY art_quick_set_obj_static
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a2, 64($sp) # pass referrer's Method*
@@ -697,13 +697,13 @@ ENTRY art_quick_set_obj_static_from_code
jal artSetObjStaticFromCode # (field_idx, new_val, referrer, Thread*, $sp)
sw $sp, 16($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set_obj_static_from_code
+END art_quick_set_obj_static
/*
* Called by managed code to resolve an instance field and store a 32-bit primitive value.
*/
.extern artSet32InstanceFromCode
-ENTRY art_quick_set32_instance_from_code
+ENTRY art_quick_set32_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a3, 64($sp) # pass referrer's Method*
@@ -711,26 +711,26 @@ ENTRY art_quick_set32_instance_from_code
jal artSet32InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp)
sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set32_instance_from_code
+END art_quick_set32_instance
/*
* Called by managed code to resolve an instance field and store a 64-bit primitive value.
*/
.extern artSet32InstanceFromCode
-ENTRY art_quick_set64_instance_from_code
+ENTRY art_quick_set64_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
sw rSELF, 16($sp) # pass Thread::Current
jal artSet64InstanceFromCode # (field_idx, Object*, new_val, Thread*, $sp)
sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set64_instance_from_code
+END art_quick_set64_instance
/*
* Called by managed code to resolve an instance field and store an object reference.
*/
.extern artSetObjInstanceFromCode
-ENTRY art_quick_set_obj_instance_from_code
+ENTRY art_quick_set_obj_instance
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
lw $a3, 64($sp) # pass referrer's Method*
@@ -738,7 +738,7 @@ ENTRY art_quick_set_obj_instance_from_code
jal artSetObjInstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp)
sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
-END art_quick_set_obj_instance_from_code
+END art_quick_set_obj_instance
/*
* Entry from managed code to resolve a string, this stub will allocate a String and deliver an
@@ -747,7 +747,7 @@ END art_quick_set_obj_instance_from_code
* performed.
*/
.extern artResolveStringFromCode
-ENTRY art_quick_resolve_string_from_code
+ENTRY art_quick_resolve_string
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
@@ -755,40 +755,40 @@ ENTRY art_quick_resolve_string_from_code
jal artResolveStringFromCode
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_resolve_string_from_code
+END art_quick_resolve_string
/*
* Called by managed code to allocate an object.
*/
.extern artAllocObjectFromCode
-ENTRY art_quick_alloc_object_from_code
+ENTRY art_quick_alloc_object
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
jal artAllocObjectFromCode # (uint32_t type_idx, Method* method, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_alloc_object_from_code
+END art_quick_alloc_object
/*
* Called by managed code to allocate an object when the caller doesn't know whether it has
* access to the created type.
*/
.extern artAllocObjectFromCodeWithAccessCheck
-ENTRY art_quick_alloc_object_from_code_with_access_check
+ENTRY art_quick_alloc_object_with_access_check
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a2, rSELF # pass Thread::Current
jal artAllocObjectFromCodeWithAccessCheck # (uint32_t type_idx, Method* method, Thread*, $sp)
move $a3, $sp # pass $sp
RETURN_IF_NONZERO
-END art_quick_alloc_object_from_code_with_access_check
+END art_quick_alloc_object_with_access_check
/*
* Called by managed code to allocate an array.
*/
.extern artAllocArrayFromCode
-ENTRY art_quick_alloc_array_from_code
+ENTRY art_quick_alloc_array
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
@@ -796,14 +796,14 @@ ENTRY art_quick_alloc_array_from_code
jal artAllocArrayFromCode
sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
-END art_quick_alloc_array_from_code
+END art_quick_alloc_array
/*
* Called by managed code to allocate an array when the caller doesn't know whether it has
* access to the created type.
*/
.extern artAllocArrayFromCodeWithAccessCheck
-ENTRY art_quick_alloc_array_from_code_with_access_check
+ENTRY art_quick_alloc_array_with_access_check
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
@@ -811,13 +811,13 @@ ENTRY art_quick_alloc_array_from_code_with_access_check
jal artAllocArrayFromCodeWithAccessCheck
sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
-END art_quick_alloc_array_from_code_with_access_check
+END art_quick_alloc_array_with_access_check
/*
* Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
*/
.extern artCheckAndAllocArrayFromCode
-ENTRY art_quick_check_and_alloc_array_from_code
+ENTRY art_quick_check_and_alloc_array
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
@@ -825,13 +825,13 @@ ENTRY art_quick_check_and_alloc_array_from_code
jal artCheckAndAllocArrayFromCode
sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
-END art_quick_check_and_alloc_array_from_code
+END art_quick_check_and_alloc_array
/*
* Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
*/
.extern artCheckAndAllocArrayFromCodeWithAccessCheck
-ENTRY art_quick_check_and_alloc_array_from_code_with_access_check
+ENTRY art_quick_check_and_alloc_array_with_access_check
GENERATE_GLOBAL_POINTER
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
@@ -839,7 +839,7 @@ ENTRY art_quick_check_and_alloc_array_from_code_with_access_check
jal artCheckAndAllocArrayFromCodeWithAccessCheck
sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
-END art_quick_check_and_alloc_array_from_code_with_access_check
+END art_quick_check_and_alloc_array_with_access_check
/*
* Called by managed code when the value in rSUSPEND has been decremented to 0.
@@ -884,13 +884,33 @@ ENTRY art_quick_proxy_invoke_handler
DELIVER_PENDING_EXCEPTION
END art_quick_proxy_invoke_handler
- .extern artInterpreterEntry
-ENTRY art_quick_interpreter_entry
+ .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+ GENERATE_GLOBAL_POINTER
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ move $a2, rSELF # pass Thread::Current
+ jal artQuickProxyInvokeHandler # (Method* called, receiver, Thread*, SP)
+ move $a3, $sp # pass $sp
+ lw $gp, 52($sp) # restore $gp
+ lw $ra, 60($sp) # restore $ra
+ beqz $v0, 1f
+ lw $a0, 0($sp) # load resolved method to $a0
+ lw $a1, 4($sp) # restore non-callee save $a1
+ lw $a2, 8($sp) # restore non-callee save $a2
+ lw $a3, 12($sp) # restore non-callee save $a3
+ jr $v0 # tail call to method
+1:
+ addiu $sp, $sp, 64 # pop frame
+ .cfi_adjust_cfa_offset -64
+ DELIVER_PENDING_EXCEPTION
+END art_quick_resolution_trampoline
+
+ .extern artQuickToInterpreterBridge
+ENTRY art_quick_to_interpreter_bridge
GENERATE_GLOBAL_POINTER
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
- sw $a0, 0($sp) # place proxy method at bottom of frame
move $a1, rSELF # pass Thread::Current
- jal artInterpreterEntry # (Method* method, Thread*, SP)
+ jal artQuickToInterpreterBridge # (Method* method, Thread*, SP)
move $a2, $sp # pass $sp
lw $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
lw $gp, 52($sp) # restore $gp
@@ -902,14 +922,14 @@ ENTRY art_quick_interpreter_entry
nop
1:
DELIVER_PENDING_EXCEPTION
-END art_quick_interpreter_entry
+END art_quick_to_interpreter_bridge
/*
* Routine that intercepts method calls and returns.
*/
.extern artInstrumentationMethodEntryFromCode
.extern artInstrumentationMethodExitFromCode
-ENTRY art_quick_instrumentation_entry_from_code
+ENTRY art_quick_instrumentation_entry
GENERATE_GLOBAL_POINTER
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
move $t0, $sp # remember bottom of caller's frame
@@ -927,10 +947,10 @@ ENTRY art_quick_instrumentation_entry_from_code
RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
jalr $t9 # call method
nop
-END art_quick_instrumentation_entry_from_code
+END art_quick_instrumentation_entry
/* intentional fallthrough */
- .global art_quick_instrumentation_exit_from_code
-art_quick_instrumentation_exit_from_code:
+ .global art_quick_instrumentation_exit
+art_quick_instrumentation_exit:
.cfi_startproc
addiu $t9, $ra, 4 # put current address into $t9 to rebuild $gp
GENERATE_GLOBAL_POINTER
@@ -960,7 +980,7 @@ art_quick_instrumentation_exit_from_code:
jr $t0 # return
addiu $sp, $sp, 112 # 48 bytes of args + 64 bytes of callee save frame
.cfi_adjust_cfa_offset -112
-END art_quick_instrumentation_exit_from_code
+END art_quick_instrumentation_exit
/*
* Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
@@ -978,18 +998,6 @@ ENTRY art_quick_deoptimize
END art_quick_deoptimize
/*
- * Quick abstract method error stub. $a0 contains method* on entry.
- */
-ENTRY art_quick_abstract_method_error_stub
- GENERATE_GLOBAL_POINTER
- SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
- move $a1, $s1 # pass Thread::Current
- la $t9, artThrowAbstractMethodErrorFromCode
- jr $t9 # (Method*, Thread*, SP)
- move $a2, $sp # pass SP
-END art_quick_abstract_method_error_stub
-
- /*
* Long integer shift. This is different from the generic 32/64-bit
* binary operations because vAA/vBB are 64-bit but vCC (the shift
* distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S
index 7e6dce9..7a3fdfa 100644
--- a/runtime/arch/x86/asm_support_x86.S
+++ b/runtime/arch/x86/asm_support_x86.S
@@ -88,4 +88,16 @@ MACRO1(POP, reg)
.cfi_restore REG_VAR(reg,0)
END_MACRO
+MACRO1(UNIMPLEMENTED,name)
+ .type VAR(name, 0), @function
+ .globl VAR(name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(name, 0):
+ .cfi_startproc
+ int3
+ int3
+ .cfi_endproc
+ .size \name, .-\name
+END_MACRO
+
#endif // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index d47dfef..9152674 100644
--- a/runtime/arch/x86/entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -20,69 +20,73 @@
namespace art {
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterperterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+
+// Portable entrypoints.
+extern "C" void art_portable_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_portable_to_interpreter_bridge(mirror::AbstractMethod*);
+
// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_with_access_check(uint32_t, void*, int32_t);
// Cast entrypoints.
-extern "C" uint32_t art_quick_is_assignable_from_code(const mirror::Class* klass,
+extern "C" uint32_t art_quick_is_assignable(const mirror::Class* klass,
const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
+extern "C" void art_quick_can_put_array_element(void*, void*);
+extern "C" void art_quick_check_cast(void*, void*);
// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+extern "C" void* art_quick_initialize_static_storage(uint32_t, void*);
+extern "C" void* art_quick_initialize_type(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, void*);
+extern "C" void* art_quick_resolve_string(void*, uint32_t);
// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+extern "C" int art_quick_set32_instance(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static(uint32_t);
+extern "C" int64_t art_quick_get64_instance(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static(uint32_t);
+extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static(uint32_t);
// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+extern "C" void art_quick_handle_fill_data(void*, void*);
// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_unlock_object_from_code(void*);
+extern "C" void art_quick_lock_object(void*);
+extern "C" void art_quick_unlock_object(void*);
// Math entrypoints.
-extern "C" double art_quick_fmod_from_code(double, double);
-extern "C" float art_quick_fmodf_from_code(float, float);
-extern "C" double art_quick_l2d_from_code(int64_t);
-extern "C" float art_quick_l2f_from_code(int64_t);
-extern "C" int64_t art_quick_d2l_from_code(double);
-extern "C" int64_t art_quick_f2l_from_code(float);
-extern "C" int32_t art_quick_idivmod_from_code(int32_t, int32_t);
-extern "C" int64_t art_quick_ldiv_from_code(int64_t, int64_t);
-extern "C" int64_t art_quick_ldivmod_from_code(int64_t, int64_t);
-extern "C" int64_t art_quick_lmul_from_code(int64_t, int64_t);
-extern "C" uint64_t art_quick_lshl_from_code(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_lshr_from_code(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_lushr_from_code(uint64_t, uint32_t);
-
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
+extern "C" double art_quick_fmod(double, double);
+extern "C" float art_quick_fmodf(float, float);
+extern "C" double art_quick_l2d(int64_t);
+extern "C" float art_quick_l2f(int64_t);
+extern "C" int64_t art_quick_d2l(double);
+extern "C" int64_t art_quick_f2l(float);
+extern "C" int32_t art_quick_idivmod(int32_t, int32_t);
+extern "C" int64_t art_quick_ldiv(int64_t, int64_t);
+extern "C" int64_t art_quick_ldivmod(int64_t, int64_t);
+extern "C" int64_t art_quick_lmul(int64_t, int64_t);
+extern "C" uint64_t art_quick_lshl(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lshr(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lushr(uint64_t, uint32_t);
// Intrinsic entrypoints.
extern "C" int32_t art_quick_memcmp16(void*, void*, int32_t);
@@ -91,12 +95,8 @@ extern "C" int32_t art_quick_string_compareto(void*, void*);
extern "C" void* art_quick_memcpy(void*, const void*, size_t);
// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_resolution_trampoline(mirror::AbstractMethod*);
+extern "C" void art_quick_to_interpreter_bridge(mirror::AbstractMethod*);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -109,49 +109,61 @@ extern void CheckSuspendFromCode(Thread* thread);
extern "C" void art_quick_test_suspend();
// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+extern "C" void art_quick_deliver_exception(void*);
+extern "C" void art_quick_throw_array_bounds(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero();
+extern "C" void art_quick_throw_no_such_method(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception();
+extern "C" void art_quick_throw_stack_overflow(void*);
+
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
+ // Interpreter
+ ipoints->pInterpreterToInterpreterBridge = artInterpreterToInterpreterBridge;
+ ipoints->pInterpreterToCompiledCodeBridge = artInterperterToCompiledCodeBridge;
+
+ // JNI
+ jpoints->pDlsymLookup = art_jni_dlsym_lookup_stub;
+
+ // Portable
+ ppoints->pPortableResolutionTrampoline = art_portable_resolution_trampoline;
+ ppoints->pPortableToInterpreterBridge = art_portable_to_interpreter_bridge;
+
// Alloc
- qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
- qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
- qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
- qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
- qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
- qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+ qpoints->pAllocArray = art_quick_alloc_array;
+ qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check;
+ qpoints->pAllocObject = art_quick_alloc_object;
+ qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check;
+ qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array;
+ qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check;
// Cast
- qpoints->pInstanceofNonTrivialFromCode = art_quick_is_assignable_from_code;
- qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
- qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+ qpoints->pInstanceofNonTrivial = art_quick_is_assignable;
+ qpoints->pCanPutArrayElement = art_quick_can_put_array_element;
+ qpoints->pCheckCast = art_quick_check_cast;
// DexCache
- qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
- qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
- qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
- qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+ qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
+ qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access;
+ qpoints->pInitializeType = art_quick_initialize_type;
+ qpoints->pResolveString = art_quick_resolve_string;
// Field
- qpoints->pSet32Instance = art_quick_set32_instance_from_code;
- qpoints->pSet32Static = art_quick_set32_static_from_code;
- qpoints->pSet64Instance = art_quick_set64_instance_from_code;
- qpoints->pSet64Static = art_quick_set64_static_from_code;
- qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
- qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
- qpoints->pGet32Instance = art_quick_get32_instance_from_code;
- qpoints->pGet64Instance = art_quick_get64_instance_from_code;
- qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
- qpoints->pGet32Static = art_quick_get32_static_from_code;
- qpoints->pGet64Static = art_quick_get64_static_from_code;
- qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+ qpoints->pSet32Instance = art_quick_set32_instance;
+ qpoints->pSet32Static = art_quick_set32_static;
+ qpoints->pSet64Instance = art_quick_set64_instance;
+ qpoints->pSet64Static = art_quick_set64_static;
+ qpoints->pSetObjInstance = art_quick_set_obj_instance;
+ qpoints->pSetObjStatic = art_quick_set_obj_static;
+ qpoints->pGet32Instance = art_quick_get32_instance;
+ qpoints->pGet64Instance = art_quick_get64_instance;
+ qpoints->pGetObjInstance = art_quick_get_obj_instance;
+ qpoints->pGet32Static = art_quick_get32_static;
+ qpoints->pGet64Static = art_quick_get64_static;
+ qpoints->pGetObjStatic = art_quick_get_obj_static;
// FillArray
- qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
// JNI
qpoints->pJniMethodStart = JniMethodStart;
@@ -162,33 +174,29 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
- qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ qpoints->pLockObject = art_quick_lock_object;
+ qpoints->pUnlockObject = art_quick_unlock_object;
// Math
// points->pCmpgDouble = NULL; // Not needed on x86.
// points->pCmpgFloat = NULL; // Not needed on x86.
// points->pCmplDouble = NULL; // Not needed on x86.
// points->pCmplFloat = NULL; // Not needed on x86.
- qpoints->pFmod = art_quick_fmod_from_code;
- qpoints->pL2d = art_quick_l2d_from_code;
- qpoints->pFmodf = art_quick_fmodf_from_code;
- qpoints->pL2f = art_quick_l2f_from_code;
+ qpoints->pFmod = art_quick_fmod;
+ qpoints->pL2d = art_quick_l2d;
+ qpoints->pFmodf = art_quick_fmodf;
+ qpoints->pL2f = art_quick_l2f;
// points->pD2iz = NULL; // Not needed on x86.
// points->pF2iz = NULL; // Not needed on x86.
- qpoints->pIdivmod = art_quick_idivmod_from_code;
- qpoints->pD2l = art_quick_d2l_from_code;
- qpoints->pF2l = art_quick_f2l_from_code;
- qpoints->pLdiv = art_quick_ldiv_from_code;
- qpoints->pLdivmod = art_quick_ldivmod_from_code;
- qpoints->pLmul = art_quick_lmul_from_code;
- qpoints->pShlLong = art_quick_lshl_from_code;
- qpoints->pShrLong = art_quick_lshr_from_code;
- qpoints->pUshrLong = art_quick_lushr_from_code;
-
- // Interpreter
- qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+ qpoints->pIdivmod = art_quick_idivmod;
+ qpoints->pD2l = art_quick_d2l;
+ qpoints->pF2l = art_quick_f2l;
+ qpoints->pLdiv = art_quick_ldiv;
+ qpoints->pLdivmod = art_quick_ldivmod;
+ qpoints->pLmul = art_quick_lmul;
+ qpoints->pShlLong = art_quick_lshl;
+ qpoints->pShrLong = art_quick_lshr;
+ qpoints->pUshrLong = art_quick_lushr;
// Intrinsics
qpoints->pIndexOf = art_quick_indexof;
@@ -197,7 +205,8 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pMemcpy = art_quick_memcpy;
// Invocation
- qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+ qpoints->pQuickResolutionTrampoline = art_quick_resolution_trampoline;
+ qpoints->pQuickToInterpreterBridge = art_quick_to_interpreter_bridge;
qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -206,19 +215,16 @@ void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
// Thread
- qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
- qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspend = CheckSuspendFromCode;
+ qpoints->pTestSuspend = art_quick_test_suspend;
// Throws
- qpoints->pDeliverException = art_quick_deliver_exception_from_code;
- qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
- qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
- qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
- qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
- qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-
- // Portable
- ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+ qpoints->pDeliverException = art_quick_deliver_exception;
+ qpoints->pThrowArrayBounds = art_quick_throw_array_bounds;
+ qpoints->pThrowDivZero = art_quick_throw_div_zero;
+ qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
+ qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
+ qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
};
} // namespace art
diff --git a/runtime/arch/x86/portable_entrypoints_x86.S b/runtime/arch/x86/portable_entrypoints_x86.S
index a0fca6c..0313d4b 100644
--- a/runtime/arch/x86/portable_entrypoints_x86.S
+++ b/runtime/arch/x86/portable_entrypoints_x86.S
@@ -90,20 +90,5 @@ DEFINE_FUNCTION art_portable_proxy_invoke_handler
ret
END_FUNCTION art_portable_proxy_invoke_handler
- /*
- * Portable abstract method error stub. method* is at %esp + 4 on entry.
- */
-DEFINE_FUNCTION art_portable_abstract_method_error_stub
- PUSH ebp
- movl %esp, %ebp // Remember SP.
- .cfi_def_cfa_register ebp
- subl LITERAL(12), %esp // Align stack.
- PUSH esp // Pass sp (not used).
- pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current().
- pushl 8(%ebp) // Pass Method*.
- call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP)
- leave // Restore the stack and %ebp.
- .cfi_def_cfa esp, 4
- .cfi_restore ebp
- ret // Return to caller to handle pending exception.
-END_FUNCTION art_portable_abstract_method_error_stub
+UNIMPLEMENTED art_portable_resolution_trampoline
+UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 89ea71a..dbf552f 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -135,34 +135,34 @@ END_MACRO
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception_from_code, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero_from_code, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow_from_code, artThrowStackOverflowFromCode
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
/*
* Called by managed code, saves callee saves and then calls artThrowException
* that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception_from_code, artDeliverExceptionFromCode
+ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
/*
* Called by managed code to create and deliver a NoSuchMethodError.
*/
-ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method_from_code, artThrowNoSuchMethodFromCode
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
/*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds_from_code, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* All generated callsites for interface invokes and invocation slow paths will load arguments
@@ -382,24 +382,24 @@ MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
DELIVER_PENDING_EXCEPTION
END_MACRO
-TWO_ARG_DOWNCALL art_quick_alloc_object_from_code, artAllocObjectFromCode, RETURN_IF_EAX_NOT_ZERO
-TWO_ARG_DOWNCALL art_quick_alloc_object_from_code_with_access_check, artAllocObjectFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
-THREE_ARG_DOWNCALL art_quick_alloc_array_from_code, artAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
-THREE_ARG_DOWNCALL art_quick_alloc_array_from_code_with_access_check, artAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
-THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_from_code, artCheckAndAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
-THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_from_code_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_alloc_object, artAllocObjectFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check, artAllocObjectFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_quick_alloc_array, artAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check, artAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_quick_check_and_alloc_array, artCheckAndAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
-TWO_ARG_DOWNCALL art_quick_resolve_string_from_code, artResolveStringFromCode, RETURN_IF_EAX_NOT_ZERO
-TWO_ARG_DOWNCALL art_quick_initialize_static_storage_from_code, artInitializeStaticStorageFromCode, RETURN_IF_EAX_NOT_ZERO
-TWO_ARG_DOWNCALL art_quick_initialize_type_from_code, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO
-TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access_from_code, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO
-ONE_ARG_DOWNCALL art_quick_lock_object_from_code, artLockObjectFromCode, ret
-ONE_ARG_DOWNCALL art_quick_unlock_object_from_code, artUnlockObjectFromCode, RETURN_IF_EAX_ZERO
+ONE_ARG_DOWNCALL art_quick_lock_object, artLockObjectFromCode, ret
+ONE_ARG_DOWNCALL art_quick_unlock_object, artUnlockObjectFromCode, RETURN_IF_EAX_ZERO
-TWO_ARG_DOWNCALL art_quick_handle_fill_data_from_code, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
-DEFINE_FUNCTION art_quick_is_assignable_from_code
+DEFINE_FUNCTION art_quick_is_assignable
PUSH eax // alignment padding
PUSH ecx // pass arg2
PUSH eax // pass arg1
@@ -407,7 +407,7 @@ DEFINE_FUNCTION art_quick_is_assignable_from_code
addl LITERAL(12), %esp // pop arguments
.cfi_adjust_cfa_offset -12
ret
-END_FUNCTION art_quick_is_assignable_from_code
+END_FUNCTION art_quick_is_assignable
DEFINE_FUNCTION art_quick_memcpy
PUSH edx // pass arg3
@@ -419,12 +419,12 @@ DEFINE_FUNCTION art_quick_memcpy
ret
END_FUNCTION art_quick_memcpy
-TWO_ARG_DOWNCALL art_quick_check_cast_from_code, artCheckCastFromCode, RETURN_IF_EAX_ZERO
-TWO_ARG_DOWNCALL art_quick_can_put_array_element_from_code, artCanPutArrayElementFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_DOWNCALL art_quick_check_cast, artCheckCastFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_DOWNCALL art_quick_can_put_array_element, artCanPutArrayElementFromCode, RETURN_IF_EAX_ZERO
NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
-DEFINE_FUNCTION art_quick_fmod_from_code
+DEFINE_FUNCTION art_quick_fmod
subl LITERAL(12), %esp // alignment padding
.cfi_adjust_cfa_offset 12
PUSH ebx // pass arg4 b.hi
@@ -437,9 +437,9 @@ DEFINE_FUNCTION art_quick_fmod_from_code
addl LITERAL(28), %esp // pop arguments
.cfi_adjust_cfa_offset -28
ret
-END_FUNCTION art_quick_fmod_from_code
+END_FUNCTION art_quick_fmod
-DEFINE_FUNCTION art_quick_fmodf_from_code
+DEFINE_FUNCTION art_quick_fmodf
PUSH eax // alignment padding
PUSH ecx // pass arg2 b
PUSH eax // pass arg1 a
@@ -449,9 +449,9 @@ DEFINE_FUNCTION art_quick_fmodf_from_code
addl LITERAL(12), %esp // pop arguments
.cfi_adjust_cfa_offset -12
ret
-END_FUNCTION art_quick_fmodf_from_code
+END_FUNCTION art_quick_fmodf
-DEFINE_FUNCTION art_quick_l2d_from_code
+DEFINE_FUNCTION art_quick_l2d
PUSH ecx // push arg2 a.hi
PUSH eax // push arg1 a.lo
fildll (%esp) // load as integer and push into st0
@@ -460,9 +460,9 @@ DEFINE_FUNCTION art_quick_l2d_from_code
addl LITERAL(8), %esp // pop arguments
.cfi_adjust_cfa_offset -8
ret
-END_FUNCTION art_quick_l2d_from_code
+END_FUNCTION art_quick_l2d
-DEFINE_FUNCTION art_quick_l2f_from_code
+DEFINE_FUNCTION art_quick_l2f
PUSH ecx // push arg2 a.hi
PUSH eax // push arg1 a.lo
fildll (%esp) // load as integer and push into st0
@@ -471,9 +471,9 @@ DEFINE_FUNCTION art_quick_l2f_from_code
addl LITERAL(8), %esp // pop argument
.cfi_adjust_cfa_offset -8
ret
-END_FUNCTION art_quick_l2f_from_code
+END_FUNCTION art_quick_l2f
-DEFINE_FUNCTION art_quick_d2l_from_code
+DEFINE_FUNCTION art_quick_d2l
PUSH eax // alignment padding
PUSH ecx // pass arg2 a.hi
PUSH eax // pass arg1 a.lo
@@ -481,9 +481,9 @@ DEFINE_FUNCTION art_quick_d2l_from_code
addl LITERAL(12), %esp // pop arguments
.cfi_adjust_cfa_offset -12
ret
-END_FUNCTION art_quick_d2l_from_code
+END_FUNCTION art_quick_d2l
-DEFINE_FUNCTION art_quick_f2l_from_code
+DEFINE_FUNCTION art_quick_f2l
subl LITERAL(8), %esp // alignment padding
.cfi_adjust_cfa_offset 8
PUSH eax // pass arg1 a
@@ -491,9 +491,9 @@ DEFINE_FUNCTION art_quick_f2l_from_code
addl LITERAL(12), %esp // pop arguments
.cfi_adjust_cfa_offset -12
ret
-END_FUNCTION art_quick_f2l_from_code
+END_FUNCTION art_quick_f2l
-DEFINE_FUNCTION art_quick_idivmod_from_code
+DEFINE_FUNCTION art_quick_idivmod
cmpl LITERAL(0x80000000), %eax
je check_arg2 // special case
args_ok:
@@ -505,9 +505,9 @@ check_arg2:
jne args_ok
xorl %edx, %edx
ret // eax already holds min int
-END_FUNCTION art_quick_idivmod_from_code
+END_FUNCTION art_quick_idivmod
-DEFINE_FUNCTION art_quick_ldiv_from_code
+DEFINE_FUNCTION art_quick_ldiv
subl LITERAL(12), %esp // alignment padding
.cfi_adjust_cfa_offset 12
PUSH ebx // pass arg4 b.hi
@@ -518,9 +518,9 @@ DEFINE_FUNCTION art_quick_ldiv_from_code
addl LITERAL(28), %esp // pop arguments
.cfi_adjust_cfa_offset -28
ret
-END_FUNCTION art_quick_ldiv_from_code
+END_FUNCTION art_quick_ldiv
-DEFINE_FUNCTION art_quick_ldivmod_from_code
+DEFINE_FUNCTION art_quick_ldivmod
subl LITERAL(12), %esp // alignment padding
.cfi_adjust_cfa_offset 12
PUSH ebx // pass arg4 b.hi
@@ -531,18 +531,18 @@ DEFINE_FUNCTION art_quick_ldivmod_from_code
addl LITERAL(28), %esp // pop arguments
.cfi_adjust_cfa_offset -28
ret
-END_FUNCTION art_quick_ldivmod_from_code
+END_FUNCTION art_quick_ldivmod
-DEFINE_FUNCTION art_quick_lmul_from_code
+DEFINE_FUNCTION art_quick_lmul
imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx)
imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx)
mul %edx // edx:eax = a.lo(eax) * b.lo(edx)
add %ebx, %ecx
add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi)
ret
-END_FUNCTION art_quick_lmul_from_code
+END_FUNCTION art_quick_lmul
-DEFINE_FUNCTION art_quick_lshl_from_code
+DEFINE_FUNCTION art_quick_lshl
// ecx:eax << edx
xchg %edx, %ecx
shld %cl,%eax,%edx
@@ -553,9 +553,9 @@ DEFINE_FUNCTION art_quick_lshl_from_code
xor %eax, %eax
1:
ret
-END_FUNCTION art_quick_lshl_from_code
+END_FUNCTION art_quick_lshl
-DEFINE_FUNCTION art_quick_lshr_from_code
+DEFINE_FUNCTION art_quick_lshr
// ecx:eax >> edx
xchg %edx, %ecx
shrd %cl,%edx,%eax
@@ -566,9 +566,9 @@ DEFINE_FUNCTION art_quick_lshr_from_code
sar LITERAL(31), %edx
1:
ret
-END_FUNCTION art_quick_lshr_from_code
+END_FUNCTION art_quick_lshr
-DEFINE_FUNCTION art_quick_lushr_from_code
+DEFINE_FUNCTION art_quick_lushr
// ecx:eax >>> edx
xchg %edx, %ecx
shrd %cl,%edx,%eax
@@ -579,9 +579,9 @@ DEFINE_FUNCTION art_quick_lushr_from_code
xor %edx, %edx
1:
ret
-END_FUNCTION art_quick_lushr_from_code
+END_FUNCTION art_quick_lushr
-DEFINE_FUNCTION art_quick_set32_instance_from_code
+DEFINE_FUNCTION art_quick_set32_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
subl LITERAL(8), %esp // alignment padding
@@ -599,9 +599,9 @@ DEFINE_FUNCTION art_quick_set32_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set32_instance_from_code
+END_FUNCTION art_quick_set32_instance
-DEFINE_FUNCTION art_quick_set64_instance_from_code
+DEFINE_FUNCTION art_quick_set64_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
subl LITERAL(8), %esp // alignment padding
.cfi_adjust_cfa_offset 8
@@ -618,9 +618,9 @@ DEFINE_FUNCTION art_quick_set64_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set64_instance_from_code
+END_FUNCTION art_quick_set64_instance
-DEFINE_FUNCTION art_quick_set_obj_instance_from_code
+DEFINE_FUNCTION art_quick_set_obj_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
subl LITERAL(8), %esp // alignment padding
@@ -638,9 +638,9 @@ DEFINE_FUNCTION art_quick_set_obj_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set_obj_instance_from_code
+END_FUNCTION art_quick_set_obj_instance
-DEFINE_FUNCTION art_quick_get32_instance_from_code
+DEFINE_FUNCTION art_quick_get32_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
mov 32(%esp), %edx // get referrer
@@ -657,9 +657,9 @@ DEFINE_FUNCTION art_quick_get32_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get32_instance_from_code
+END_FUNCTION art_quick_get32_instance
-DEFINE_FUNCTION art_quick_get64_instance_from_code
+DEFINE_FUNCTION art_quick_get64_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
mov 32(%esp), %edx // get referrer
@@ -676,9 +676,9 @@ DEFINE_FUNCTION art_quick_get64_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get64_instance_from_code
+END_FUNCTION art_quick_get64_instance
-DEFINE_FUNCTION art_quick_get_obj_instance_from_code
+DEFINE_FUNCTION art_quick_get_obj_instance
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
mov 32(%esp), %edx // get referrer
@@ -695,9 +695,9 @@ DEFINE_FUNCTION art_quick_get_obj_instance_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get_obj_instance_from_code
+END_FUNCTION art_quick_get_obj_instance
-DEFINE_FUNCTION art_quick_set32_static_from_code
+DEFINE_FUNCTION art_quick_set32_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
mov 32(%esp), %edx // get referrer
@@ -714,9 +714,9 @@ DEFINE_FUNCTION art_quick_set32_static_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set32_static_from_code
+END_FUNCTION art_quick_set32_static
-DEFINE_FUNCTION art_quick_set64_static_from_code
+DEFINE_FUNCTION art_quick_set64_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
subl LITERAL(8), %esp // alignment padding
@@ -734,9 +734,9 @@ DEFINE_FUNCTION art_quick_set64_static_from_code
.cfi_adjust_cfa_offset -32
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set64_static_from_code
+END_FUNCTION art_quick_set64_static
-DEFINE_FUNCTION art_quick_set_obj_static_from_code
+DEFINE_FUNCTION art_quick_set_obj_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %ebx // remember SP
mov 32(%esp), %edx // get referrer
@@ -752,9 +752,9 @@ DEFINE_FUNCTION art_quick_set_obj_static_from_code
addl LITERAL(32), %esp // pop arguments
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_IF_EAX_ZERO // return or deliver exception
-END_FUNCTION art_quick_set_obj_static_from_code
+END_FUNCTION art_quick_set_obj_static
-DEFINE_FUNCTION art_quick_get32_static_from_code
+DEFINE_FUNCTION art_quick_get32_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %edx // remember SP
mov 32(%esp), %ecx // get referrer
@@ -768,9 +768,9 @@ DEFINE_FUNCTION art_quick_get32_static_from_code
.cfi_adjust_cfa_offset -16
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get32_static_from_code
+END_FUNCTION art_quick_get32_static
-DEFINE_FUNCTION art_quick_get64_static_from_code
+DEFINE_FUNCTION art_quick_get64_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %edx // remember SP
mov 32(%esp), %ecx // get referrer
@@ -784,9 +784,9 @@ DEFINE_FUNCTION art_quick_get64_static_from_code
.cfi_adjust_cfa_offset -16
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get64_static_from_code
+END_FUNCTION art_quick_get64_static
-DEFINE_FUNCTION art_quick_get_obj_static_from_code
+DEFINE_FUNCTION art_quick_get_obj_static
SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
mov %esp, %edx // remember SP
mov 32(%esp), %ecx // get referrer
@@ -800,7 +800,7 @@ DEFINE_FUNCTION art_quick_get_obj_static_from_code
.cfi_adjust_cfa_offset -16
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_get_obj_static_from_code
+END_FUNCTION art_quick_get_obj_static
DEFINE_FUNCTION art_quick_proxy_invoke_handler
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame and Method*
@@ -818,7 +818,32 @@ DEFINE_FUNCTION art_quick_proxy_invoke_handler
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
END_FUNCTION art_quick_proxy_invoke_handler
-DEFINE_FUNCTION art_quick_interpreter_entry
+DEFINE_FUNCTION art_quick_resolution_trampoline
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ PUSH esp // pass SP
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ .cfi_adjust_cfa_offset 4
+ PUSH ecx // pass receiver
+ PUSH eax // pass method
+ call SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP)
+ movl %eax, %edi // remember code pointer in EDI
+ addl LITERAL(16), %esp // pop arguments
+ test %eax, %eax // if code pointer is NULL goto deliver pending exception
+ jz 1f
+ POP eax // called method
+ POP ecx // restore args
+ POP edx
+ POP ebx
+ POP ebp // restore callee saves except EDI
+ POP esi
+ xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack
+ ret // tail call into method
+1:
+ RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ DELIVER_PENDING_EXCEPTION
+END_FUNCTION art_quick_resolution_trampoline
+
+DEFINE_FUNCTION art_quick_to_interpreter_bridge
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame
mov %esp, %edx // remember SP
PUSH eax // alignment padding
@@ -826,19 +851,19 @@ DEFINE_FUNCTION art_quick_interpreter_entry
pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
.cfi_adjust_cfa_offset 4
PUSH eax // pass method
- call SYMBOL(artInterpreterEntry) // (method, Thread*, SP)
+ call SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP)
movd %eax, %xmm0 // place return value also into floating point return value
movd %edx, %xmm1
punpckldq %xmm1, %xmm0
addl LITERAL(44), %esp // pop arguments
.cfi_adjust_cfa_offset -44
RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
-END_FUNCTION art_quick_interpreter_entry
+END_FUNCTION art_quick_to_interpreter_bridge
/*
* Routine that intercepts method calls and returns.
*/
-DEFINE_FUNCTION art_quick_instrumentation_entry_from_code
+DEFINE_FUNCTION art_quick_instrumentation_entry
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
movl %esp, %edx // Save SP.
PUSH eax // Save eax which will be clobbered by the callee-save method.
@@ -855,7 +880,7 @@ DEFINE_FUNCTION art_quick_instrumentation_entry_from_code
addl LITERAL(28), %esp // Pop arguments upto saved Method*.
movl 28(%esp), %edi // Restore edi.
movl %eax, 28(%esp) // Place code* over edi, just under return pc.
- movl LITERAL(SYMBOL(art_quick_instrumentation_exit_from_code)), 32(%esp)
+ movl LITERAL(SYMBOL(art_quick_instrumentation_exit)), 32(%esp)
// Place instrumentation exit as return pc.
movl (%esp), %eax // Restore eax.
movl 8(%esp), %ecx // Restore ecx.
@@ -865,9 +890,9 @@ DEFINE_FUNCTION art_quick_instrumentation_entry_from_code
movl 24(%esp), %esi // Restore esi.
addl LITERAL(28), %esp // Wind stack back upto code*.
ret // Call method (and pop).
-END_FUNCTION art_quick_instrumentation_entry_from_code
+END_FUNCTION art_quick_instrumentation_entry
-DEFINE_FUNCTION art_quick_instrumentation_exit_from_code
+DEFINE_FUNCTION art_quick_instrumentation_exit
pushl LITERAL(0) // Push a fake return PC as there will be none on the stack.
SETUP_REF_ONLY_CALLEE_SAVE_FRAME
mov %esp, %ecx // Remember SP
@@ -900,7 +925,7 @@ DEFINE_FUNCTION art_quick_instrumentation_exit_from_code
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
addl LITERAL(4), %esp // Remove fake return pc.
jmp *%ecx // Return.
-END_FUNCTION art_quick_instrumentation_exit_from_code
+END_FUNCTION art_quick_instrumentation_exit
/*
* Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
@@ -920,21 +945,6 @@ DEFINE_FUNCTION art_quick_deoptimize
END_FUNCTION art_quick_deoptimize
/*
- * Quick abstract method error stub. %eax contains method* on entry.
- */
-DEFINE_FUNCTION art_quick_abstract_method_error_stub
- SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
- movl %esp, %ecx // Remember SP.
- PUSH eax // Align frame.
- PUSH ecx // Pass SP for Method*.
- pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current().
- .cfi_adjust_cfa_offset 4
- PUSH eax // Pass Method*.
- call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP)
- int3 // Unreachable.
-END_FUNCTION art_quick_abstract_method_error_stub
-
- /*
* String's indexOf.
*
* On entry:
@@ -1030,12 +1040,5 @@ not_equal:
ret
END_FUNCTION art_quick_string_compareto
-MACRO1(UNIMPLEMENTED,name)
- .globl VAR(name, 0)
- ALIGN_FUNCTION_ENTRY
-VAR(name, 0):
- int3
-END_MACRO
-
// TODO: implement these!
UNIMPLEMENTED art_quick_memcmp16
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 84f186d..9629775 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -71,7 +71,7 @@
namespace art {
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
+extern "C" void artInterperterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
const DexFile::CodeItem* code_item,
ShadowFrame* shadow_frame, JValue* result);
@@ -920,6 +920,43 @@ const OatFile* ClassLinker::FindOatFileFromOatLocationLocked(const std::string&
return oat_file;
}
+static void InitFromImageCallbackCommon(mirror::Object* obj, ClassLinker* class_linker,
+ bool interpret_only_mode)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(obj != NULL);
+ DCHECK(class_linker != NULL);
+
+ if (obj->GetClass()->IsStringClass()) {
+ class_linker->GetInternTable()->RegisterStrong(obj->AsString());
+ } else if (obj->IsClass()) {
+ // Restore class to ClassLinker::classes_ table.
+ mirror::Class* klass = obj->AsClass();
+ ClassHelper kh(klass, class_linker);
+ mirror::Class* existing = class_linker->InsertClass(kh.GetDescriptor(), klass, true);
+ DCHECK(existing == NULL) << kh.GetDescriptor();
+ } else if (interpret_only_mode && obj->IsMethod()) {
+ mirror::AbstractMethod* method = obj->AsMethod();
+ if (!method->IsNative()) {
+ method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
+ if (method != Runtime::Current()->GetResolutionMethod()) {
+ method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ }
+ }
+ }
+}
+
+static void InitFromImageCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);
+ InitFromImageCallbackCommon(obj, class_linker, false);
+}
+
+static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);
+ InitFromImageCallbackCommon(obj, class_linker, true);
+}
+
void ClassLinker::InitFromImage() {
VLOG(startup) << "ClassLinker::InitFromImage entering";
CHECK(!init_done_);
@@ -973,7 +1010,11 @@ void ClassLinker::InitFromImage() {
{
ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
heap->FlushAllocStack();
- heap->GetLiveBitmap()->Walk(InitFromImageCallback, this);
+ if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
+ heap->GetLiveBitmap()->Walk(InitFromImageInterpretOnlyCallback, this);
+ } else {
+ heap->GetLiveBitmap()->Walk(InitFromImageCallback, this);
+ }
}
// reinit class_roots_
@@ -1001,40 +1042,6 @@ void ClassLinker::InitFromImage() {
VLOG(startup) << "ClassLinker::InitFromImage exiting";
}
-void ClassLinker::InitFromImageCallback(mirror::Object* obj, void* arg) {
- DCHECK(obj != NULL);
- DCHECK(arg != NULL);
- ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);
-
- if (obj->GetClass()->IsStringClass()) {
- class_linker->intern_table_->RegisterStrong(obj->AsString());
- return;
- }
- if (obj->IsClass()) {
- // restore class to ClassLinker::classes_ table
- mirror::Class* klass = obj->AsClass();
- ClassHelper kh(klass, class_linker);
- mirror::Class* existing = class_linker->InsertClass(kh.GetDescriptor(), klass, true);
- DCHECK(existing == NULL) << kh.GetDescriptor();
- return;
- }
-
- if (obj->IsMethod()) {
- mirror::AbstractMethod* method = obj->AsMethod();
- // Set entry points to interpreter for methods in interpreter only mode.
- if (Runtime::Current()->GetInstrumentation()->InterpretOnly() && !method->IsNative()) {
- method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterEntry);
- if (method != Runtime::Current()->GetResolutionMethod()) {
- method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
- }
- }
- // Populate native method pointer with jni lookup stub.
- if (method->IsNative()) {
- method->UnregisterNative(Thread::Current());
- }
- }
-}
-
// Keep in sync with InitCallback. Anything we visit, we need to
// reinit references to when reinitializing a ClassLinker from a
// mapped image.
@@ -1534,7 +1541,7 @@ const void* ClassLinker::GetOatCodeFor(const mirror::AbstractMethod* method) {
const void* result = GetOatMethodFor(method).GetCode();
if (result == NULL) {
// No code? You must mean to go into the interpreter.
- result = GetInterpreterEntryPoint();
+ result = GetCompiledCodeToInterpreterBridge();
}
return result;
}
@@ -1595,7 +1602,7 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
const bool enter_interpreter = NeedsInterpreter(method, code);
if (enter_interpreter) {
// Use interpreter entry point.
- code = GetInterpreterEntryPoint();
+ code = GetCompiledCodeToInterpreterBridge();
}
runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
}
@@ -1616,13 +1623,13 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat
Runtime* runtime = Runtime::Current();
bool enter_interpreter = NeedsInterpreter(method.get(), method->GetEntryPointFromCompiledCode());
if (enter_interpreter) {
- method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterEntry);
+ method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
- method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
+ method->SetEntryPointFromInterpreter(artInterperterToCompiledCodeBridge);
}
if (method->IsAbstract()) {
- method->SetEntryPointFromCompiledCode(GetAbstractMethodErrorStub());
+ method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
return;
}
@@ -1633,7 +1640,7 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat
method->SetEntryPointFromCompiledCode(GetResolutionTrampoline(runtime->GetClassLinker()));
} else if (enter_interpreter) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
- method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
+ method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
}
if (method->IsNative()) {
@@ -2601,12 +2608,8 @@ mirror::AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mir
method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
-#if !defined(ART_USE_PORTABLE_COMPILER)
- method->SetEntryPointFromCompiledCode(reinterpret_cast<void*>(art_quick_proxy_invoke_handler));
-#else
- method->SetEntryPointFromCompiledCode(reinterpret_cast<void*>(art_portable_proxy_invoke_handler));
-#endif
- method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
+ method->SetEntryPointFromCompiledCode(GetProxyInvokeHandler());
+ method->SetEntryPointFromInterpreter(artInterperterToCompiledCodeBridge);
return method;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index fdf75c2..060c26c 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -347,6 +347,17 @@ class ClassLinker {
return quick_resolution_trampoline_;
}
+ InternTable* GetInternTable() const {
+ return intern_table_;
+ }
+
+ // Attempts to insert a class into a class table. Returns NULL if
+ // the class was inserted, otherwise returns an existing class with
+ // the same descriptor and ClassLoader.
+ mirror::Class* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool image_class)
+ LOCKS_EXCLUDED(Locks::classlinker_classes_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
explicit ClassLinker(InternTable*);
@@ -362,8 +373,6 @@ class ClassLinker {
OatFile& GetImageOatFile(gc::space::ImageSpace* space)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void InitFromImageCallback(mirror::Object* obj, void* arg)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FinishInit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -423,13 +432,6 @@ class ClassLinker {
const OatFile::OatClass* GetOatClass(const DexFile& dex_file, const char* descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Attempts to insert a class into a class table. Returns NULL if
- // the class was inserted, otherwise returns an existing class with
- // the same descriptor and ClassLoader.
- mirror::Class* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool image_class)
- LOCKS_EXCLUDED(Locks::classlinker_classes_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
EXCLUSIVE_LOCKS_REQUIRED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/common_test.h b/runtime/common_test.h
index 7ee6fe2..a543617 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -192,10 +192,7 @@ class CommonTest : public testing::Test {
compiled_method =
compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
method->GetDexMethodIndex()));
-
-#ifndef ART_LIGHT_MODE
CHECK(compiled_method != NULL) << PrettyMethod(method);
-#endif
}
if (compiled_method != NULL) {
const std::vector<uint8_t>& code = compiled_method->GetCode();
@@ -213,12 +210,8 @@ class CommonTest : public testing::Test {
oat_method.LinkMethod(method);
} else {
const void* method_code;
- if (method->IsAbstract()) {
- method_code = GetAbstractMethodErrorStub();
- } else {
- // No code? You must mean to go into the interpreter.
- method_code = GetInterpreterEntryPoint();
- }
+ // No code? You must mean to go into the interpreter.
+ method_code = GetCompiledCodeToInterpreterBridge();
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
kStackAlignment,
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 3f28b5e..b6781c0 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -30,24 +30,13 @@
#include "object_utils.h"
#include "thread.h"
-extern "C" void art_interpreter_invoke_handler();
-extern "C" void art_jni_dlsym_lookup_stub();
-extern "C" void art_portable_abstract_method_error_stub();
-extern "C" void art_portable_proxy_invoke_handler();
-extern "C" void art_quick_abstract_method_error_stub();
-extern "C" void art_quick_deoptimize();
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_proxy_invoke_handler();
-extern "C" void art_work_around_app_jni_bugs();
-
namespace art {
+
namespace mirror {
-class Class;
-class Field;
-class Object;
-}
+ class Class;
+ class Field;
+ class Object;
+} // namespace mirror
// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
// cannot be resolved, throw an error. If it can, use it to create an instance.
@@ -350,25 +339,43 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Entry point for deoptimization.
-static inline uintptr_t GetDeoptimizationEntryPoint() {
+extern "C" void art_quick_deoptimize();
+static inline uintptr_t GetQuickDeoptimizationEntryPoint() {
return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
}
// Return address of instrumentation stub.
-static inline void* GetInstrumentationEntryPoint() {
- return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
+extern "C" void art_quick_instrumentation_entry(void*);
+static inline void* GetQuickInstrumentationEntryPoint() {
+ return reinterpret_cast<void*>(art_quick_instrumentation_entry);
}
// The return_pc of instrumentation exit stub.
-static inline uintptr_t GetInstrumentationExitPc() {
- return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
+extern "C" void art_quick_instrumentation_exit();
+static inline uintptr_t GetQuickInstrumentationExitPc() {
+ return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit);
+}
+
+extern "C" void art_portable_to_interpreter_bridge(mirror::AbstractMethod*);
+static inline const void* GetPortableToInterpreterBridge() {
+ return reinterpret_cast<void*>(art_portable_to_interpreter_bridge);
+}
+
+extern "C" void art_quick_to_interpreter_bridge(mirror::AbstractMethod*);
+static inline const void* GetQuickToInterpreterBridge() {
+ return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
// Return address of interpreter stub.
-static inline void* GetInterpreterEntryPoint() {
- return reinterpret_cast<void*>(art_quick_interpreter_entry);
+static inline const void* GetCompiledCodeToInterpreterBridge() {
+#if defined(ART_USE_PORTABLE_COMPILER)
+ return GetPortableToInterpreterBridge();
+#else
+ return GetQuickToInterpreterBridge();
+#endif
}
+
static inline const void* GetPortableResolutionTrampoline(ClassLinker* class_linker) {
return class_linker->GetPortableResolutionTrampoline();
}
@@ -386,23 +393,25 @@ static inline const void* GetResolutionTrampoline(ClassLinker* class_linker) {
#endif
}
-static inline void* GetPortableAbstractMethodErrorStub() {
- return reinterpret_cast<void*>(art_portable_abstract_method_error_stub);
+extern "C" void art_portable_proxy_invoke_handler();
+static inline const void* GetPortableProxyInvokeHandler() {
+ return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
}
-static inline void* GetQuickAbstractMethodErrorStub() {
- return reinterpret_cast<void*>(art_quick_abstract_method_error_stub);
+extern "C" void art_quick_proxy_invoke_handler();
+static inline const void* GetQuickProxyInvokeHandler() {
+ return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
}
-// Return address of abstract method error stub for defined compiler.
-static inline void* GetAbstractMethodErrorStub() {
+static inline const void* GetProxyInvokeHandler() {
#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableAbstractMethodErrorStub();
+ return GetPortableProxyInvokeHandler();
#else
- return GetQuickAbstractMethodErrorStub();
+ return GetQuickProxyInvokeHandler();
#endif
}
+extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
static inline void* GetJniDlsymLookupStub() {
return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
}
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
new file mode 100644
index 0000000..d99c43e
--- /dev/null
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "class_linker.h"
+#include "interpreter/interpreter.h"
+#include "invoke_arg_array_builder.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "object_utils.h"
+#include "runtime.h"
+#include "stack.h"
+
+namespace art {
+
+extern "C" void artInterperterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::AbstractMethod* method = shadow_frame->GetMethod();
+ // Ensure static methods are initialized.
+ if (method->IsStatic()) {
+ Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), true, true);
+ }
+ uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ arg_array.BuildArgArray(shadow_frame, arg_offset);
+ method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
+}
+
+} // namespace art
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.h b/runtime/entrypoints/interpreter/interpreter_entrypoints.h
new file mode 100644
index 0000000..c7df4e6
--- /dev/null
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_INTERPRETER_INTERPRETER_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_INTERPRETER_INTERPRETER_ENTRYPOINTS_H_
+
+#include "base/macros.h"
+#include "dex_file.h"
+#include "offsets.h"
+
+#define INTERPRETER_ENTRYPOINT_OFFSET(x) \
+ ThreadOffset(static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, interpreter_entrypoints_)) + \
+ static_cast<uintptr_t>(OFFSETOF_MEMBER(InterpreterEntryPoints, x)))
+
+namespace art {
+
+union JValue;
+class MethodHelper;
+class ShadowFrame;
+class Thread;
+
+// Pointers to functions that are called by interpreter trampolines via thread-local storage.
+struct PACKED(4) InterpreterEntryPoints {
+ void (*pInterpreterToInterpreterBridge)(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+ void (*pInterpreterToCompiledCodeBridge)(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_ENTRYPOINTS_INTERPRETER_INTERPRETER_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index 98f7b12..88b4936 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -15,23 +15,26 @@
*/
#include "base/logging.h"
-#include "mirror/abstract_method.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
namespace art {
// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
-extern "C" void* artFindNativeMethod(Thread* self) {
+extern "C" void* artFindNativeMethod() {
+ Thread* self = Thread::Current();
Locks::mutator_lock_->AssertNotHeld(self); // We come here as Native.
- DCHECK(Thread::Current() == self);
ScopedObjectAccess soa(self);
mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
DCHECK(method != NULL);
- // Lookup symbol address for method, on failure we'll return NULL with an
- // exception set, otherwise we return the address of the method we found.
+ // Lookup symbol address for method, on failure we'll return NULL with an exception set,
+ // otherwise we return the address of the method we found.
void* native_code = soa.Vm()->FindCodeForNativeMethod(method);
if (native_code == NULL) {
DCHECK(self->IsExceptionPending());
@@ -43,4 +46,78 @@ extern "C" void* artFindNativeMethod(Thread* self) {
}
}
+static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) {
+ intptr_t value = *arg_ptr;
+ mirror::Object** value_as_jni_rep = reinterpret_cast<mirror::Object**>(value);
+ mirror::Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL;
+ CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep))
+ << value_as_work_around_rep;
+ *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep);
+}
+
+extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(Thread::Current() == self);
+ // TODO: this code is specific to ARM
+ // On entry the stack pointed by sp is:
+ // | arg3 | <- Calling JNI method's frame (and extra bit for out args)
+ // | LR |
+ // | R3 | arg2
+ // | R2 | arg1
+ // | R1 | jclass/jobject
+ // | R0 | JNIEnv
+ // | unused |
+ // | unused |
+ // | unused | <- sp
+ mirror::AbstractMethod* jni_method = self->GetCurrentMethod(NULL);
+ DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method);
+ intptr_t* arg_ptr = sp + 4; // pointer to r1 on stack
+ // Fix up this/jclass argument
+ WorkAroundJniBugsForJobject(arg_ptr);
+ arg_ptr++;
+ // Fix up jobject arguments
+ MethodHelper mh(jni_method);
+ int reg_num = 2; // Current register being processed, -1 for stack arguments.
+ for (uint32_t i = 1; i < mh.GetShortyLength(); i++) {
+ char shorty_char = mh.GetShorty()[i];
+ if (shorty_char == 'L') {
+ WorkAroundJniBugsForJobject(arg_ptr);
+ }
+ if (shorty_char == 'J' || shorty_char == 'D') {
+ if (reg_num == 2) {
+ arg_ptr = sp + 8; // skip to out arguments
+ reg_num = -1;
+ } else if (reg_num == 3) {
+ arg_ptr = sp + 10; // skip to out arguments plus 2 slots as long must be aligned
+ reg_num = -1;
+ } else {
+ DCHECK_EQ(reg_num, -1);
+ if ((reinterpret_cast<intptr_t>(arg_ptr) & 7) == 4) {
+ arg_ptr += 3; // unaligned, pad and move through stack arguments
+ } else {
+ arg_ptr += 2; // aligned, move through stack arguments
+ }
+ }
+ } else {
+ if (reg_num == 2) {
+ arg_ptr++; // move through register arguments
+ reg_num++;
+ } else if (reg_num == 3) {
+ arg_ptr = sp + 8; // skip to outgoing stack arguments
+ reg_num = -1;
+ } else {
+ DCHECK_EQ(reg_num, -1);
+ arg_ptr++; // move through stack arguments
+ }
+ }
+ }
+ // Load expected destination, see Method::RegisterNative
+ const void* code = reinterpret_cast<const void*>(jni_method->GetNativeGcMap());
+ if (UNLIKELY(code == NULL)) {
+ code = GetJniDlsymLookupStub();
+ jni_method->RegisterNative(self, code);
+ }
+ return code;
+}
+
} // namespace art
diff --git a/runtime/entrypoints/jni/jni_entrypoints.h b/runtime/entrypoints/jni/jni_entrypoints.h
new file mode 100644
index 0000000..0a53447
--- /dev/null
+++ b/runtime/entrypoints/jni/jni_entrypoints.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_JNI_JNI_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_JNI_JNI_ENTRYPOINTS_H_
+
+#include "base/macros.h"
+#include "offsets.h"
+
+#define JNI_ENTRYPOINT_OFFSET(x) \
+ ThreadOffset(static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, jni_entrypoints_)) + \
+ static_cast<uintptr_t>(OFFSETOF_MEMBER(JniEntryPoints, x)))
+
+namespace art {
+
+// Pointers to functions that are called by JNI trampolines via thread-local storage.
+struct PACKED(4) JniEntryPoints {
+ // Called when the JNI method isn't registered.
+ void* (*pDlsymLookup)(JNIEnv* env, jobject);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_ENTRYPOINTS_JNI_JNI_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/portable/portable_entrypoints.h b/runtime/entrypoints/portable/portable_entrypoints.h
index a229c76..ec9e4f8 100644
--- a/runtime/entrypoints/portable/portable_entrypoints.h
+++ b/runtime/entrypoints/portable/portable_entrypoints.h
@@ -28,15 +28,15 @@ namespace mirror {
class Thread;
#define PORTABLE_ENTRYPOINT_OFFSET(x) \
- (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, portable_entrypoints_)) + \
- static_cast<uintptr_t>(OFFSETOF_MEMBER(PortableEntryPoints, x)))
+ ThreadOffset(static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, portable_entrypoints_)) + \
+ static_cast<uintptr_t>(OFFSETOF_MEMBER(PortableEntryPoints, x)))
// Pointers to functions that are called by code generated by compiler's adhering to the portable
// compiler ABI.
struct PACKED(4) PortableEntryPoints {
// Invocation
- const void* (*pPortableResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
- mirror::AbstractMethod**, Thread*);
+ void (*pPortableResolutionTrampoline)(mirror::AbstractMethod*);
+ void (*pPortableToInterpreterBridge)(mirror::AbstractMethod*);
};
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_argument_visitor.h b/runtime/entrypoints/quick/quick_argument_visitor.h
deleted file mode 100644
index 35fa972..0000000
--- a/runtime/entrypoints/quick/quick_argument_visitor.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ARGUMENT_VISITOR_H_
-#define ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ARGUMENT_VISITOR_H_
-
-#include "object_utils.h"
-
-namespace art {
-
-// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
-class QuickArgumentVisitor {
- public:
-// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
-// Size of Runtime::kRefAndArgs callee save frame.
-// Size of Method* and register parameters in out stack arguments.
-#if defined(__arm__)
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
-#define QUICK_STACK_ARG_SKIP 16
-#elif defined(__mips__)
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
-#define QUICK_STACK_ARG_SKIP 16
-#elif defined(__i386__)
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
-#define QUICK_STACK_ARG_SKIP 16
-#else
-#error "Unsupported architecture"
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
-#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
-#define QUICK_STACK_ARG_SKIP 0
-#endif
-
- QuickArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
- caller_mh_(caller_mh),
- args_in_regs_(ComputeArgsInRegs(caller_mh)),
- num_params_(caller_mh.NumArgs()),
- reg_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
- stack_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
- + QUICK_STACK_ARG_SKIP),
- cur_args_(reg_args_),
- cur_arg_index_(0),
- param_index_(0),
- is_split_long_or_double_(false) {
- }
-
- virtual ~QuickArgumentVisitor() {}
-
- virtual void Visit() = 0;
-
- bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return caller_mh_.IsParamAReference(param_index_);
- }
-
- bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return caller_mh_.IsParamALongOrDouble(param_index_);
- }
-
- Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return caller_mh_.GetParamPrimitiveType(param_index_);
- }
-
- byte* GetParamAddress() const {
- return cur_args_ + (cur_arg_index_ * kPointerSize);
- }
-
- bool IsSplitLongOrDouble() const {
- return is_split_long_or_double_;
- }
-
- uint64_t ReadSplitLongParam() const {
- DCHECK(IsSplitLongOrDouble());
- uint64_t low_half = *reinterpret_cast<uint32_t*>(GetParamAddress());
- uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args_);
- return (low_half & 0xffffffffULL) | (high_half << 32);
- }
-
- void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- for (cur_arg_index_ = 0; cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
- is_split_long_or_double_ = (cur_arg_index_ == 2) && IsParamALongOrDouble();
- Visit();
- cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
- param_index_++;
- }
- cur_args_ = stack_args_;
- cur_arg_index_ = is_split_long_or_double_ ? 1 : 0;
- is_split_long_or_double_ = false;
- while (param_index_ < num_params_) {
- Visit();
- cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
- param_index_++;
- }
- }
-
- private:
- static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- size_t args_in_regs = 0;
- size_t num_params = mh.NumArgs();
- for (size_t i = 0; i < num_params; i++) {
- args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1);
- if (args_in_regs > 3) {
- args_in_regs = 3;
- break;
- }
- }
- return args_in_regs;
- }
- MethodHelper& caller_mh_;
- const size_t args_in_regs_;
- const size_t num_params_;
- byte* const reg_args_;
- byte* const stack_args_;
- byte* cur_args_;
- size_t cur_arg_index_;
- size_t param_index_;
- // Does a 64bit parameter straddle the register and stack arguments?
- bool is_split_long_or_double_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ARGUMENT_VISITOR_H_
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 74b8cfd..e76679b 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -17,44 +17,45 @@
#ifndef ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_
#define ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_
-#include "dex_file-inl.h"
-#include "runtime.h"
+#include <jni.h>
+
+#include "base/macros.h"
+#include "offsets.h"
#define QUICK_ENTRYPOINT_OFFSET(x) \
- (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, quick_entrypoints_)) + \
- static_cast<uintptr_t>(OFFSETOF_MEMBER(QuickEntryPoints, x)))
+ ThreadOffset(static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, quick_entrypoints_)) + \
+ static_cast<uintptr_t>(OFFSETOF_MEMBER(QuickEntryPoints, x)))
namespace art {
+
namespace mirror {
class AbstractMethod;
class Class;
class Object;
} // namespace mirror
-class DvmDex;
-class MethodHelper;
-class ShadowFrame;
+
class Thread;
// Pointers to functions that are called by quick compiler generated code via thread-local storage.
struct PACKED(4) QuickEntryPoints {
// Alloc
- void* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
- void* (*pAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
- void* (*pAllocObjectFromCode)(uint32_t, void*);
- void* (*pAllocObjectFromCodeWithAccessCheck)(uint32_t, void*);
- void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
- void* (*pCheckAndAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
+ void* (*pAllocArray)(uint32_t, void*, int32_t);
+ void* (*pAllocArrayWithAccessCheck)(uint32_t, void*, int32_t);
+ void* (*pAllocObject)(uint32_t, void*);
+ void* (*pAllocObjectWithAccessCheck)(uint32_t, void*);
+ void* (*pCheckAndAllocArray)(uint32_t, void*, int32_t);
+ void* (*pCheckAndAllocArrayWithAccessCheck)(uint32_t, void*, int32_t);
// Cast
- uint32_t (*pInstanceofNonTrivialFromCode)(const mirror::Class*, const mirror::Class*);
- void (*pCanPutArrayElementFromCode)(void*, void*);
- void (*pCheckCastFromCode)(void*, void*);
+ uint32_t (*pInstanceofNonTrivial)(const mirror::Class*, const mirror::Class*);
+ void (*pCanPutArrayElement)(void*, void*);
+ void (*pCheckCast)(void*, void*);
// DexCache
void* (*pInitializeStaticStorage)(uint32_t, void*);
- void* (*pInitializeTypeAndVerifyAccessFromCode)(uint32_t, void*);
- void* (*pInitializeTypeFromCode)(uint32_t, void*);
- void* (*pResolveStringFromCode)(void*, uint32_t);
+ void* (*pInitializeTypeAndVerifyAccess)(uint32_t, void*);
+ void* (*pInitializeType)(uint32_t, void*);
+ void* (*pResolveString)(void*, uint32_t);
// Field
int (*pSet32Instance)(uint32_t, void*, int32_t); // field_idx, obj, src
@@ -71,7 +72,7 @@ struct PACKED(4) QuickEntryPoints {
void* (*pGetObjStatic)(uint32_t);
// FillArray
- void (*pHandleFillArrayDataFromCode)(void*, void*);
+ void (*pHandleFillArrayData)(void*, void*);
// JNI
uint32_t (*pJniMethodStart)(Thread*);
@@ -83,8 +84,8 @@ struct PACKED(4) QuickEntryPoints {
jobject locked, Thread* self);
// Locks
- void (*pLockObjectFromCode)(void*);
- void (*pUnlockObjectFromCode)(void*);
+ void (*pLockObject)(void*);
+ void (*pUnlockObject)(void*);
// Math
int32_t (*pCmpgDouble)(double, double);
@@ -108,14 +109,6 @@ struct PACKED(4) QuickEntryPoints {
uint64_t (*pShrLong)(uint64_t, uint32_t);
uint64_t (*pUshrLong)(uint64_t, uint32_t);
- // Interpreter
- void (*pInterpreterToInterpreterEntry)(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
- void (*pInterpreterToQuickEntry)(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
-
// Intrinsics
int32_t (*pIndexOf)(void*, uint32_t, uint32_t, uint32_t);
int32_t (*pMemcmp16)(void*, void*, int32_t);
@@ -123,8 +116,8 @@ struct PACKED(4) QuickEntryPoints {
void* (*pMemcpy)(void*, const void*, size_t);
// Invocation
- const void* (*pQuickResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
- mirror::AbstractMethod**, Thread*);
+ void (*pQuickResolutionTrampoline)(mirror::AbstractMethod*);
+ void (*pQuickToInterpreterBridge)(mirror::AbstractMethod*);
void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
void (*pInvokeInterfaceTrampolineWithAccessCheck)(uint32_t, void*);
@@ -133,22 +126,21 @@ struct PACKED(4) QuickEntryPoints {
void (*pInvokeVirtualTrampolineWithAccessCheck)(uint32_t, void*);
// Thread
- void (*pCheckSuspendFromCode)(Thread*); // Stub that is called when the suspend count is non-zero
- void (*pTestSuspendFromCode)(); // Stub that is periodically called to test the suspend count
+ void (*pCheckSuspend)(Thread*); // Stub that is called when the suspend count is non-zero
+ void (*pTestSuspend)(); // Stub that is periodically called to test the suspend count
// Throws
void (*pDeliverException)(void*);
- void (*pThrowArrayBoundsFromCode)(int32_t, int32_t);
- void (*pThrowDivZeroFromCode)();
- void (*pThrowNoSuchMethodFromCode)(int32_t);
- void (*pThrowNullPointerFromCode)();
- void (*pThrowStackOverflowFromCode)(void*);
+ void (*pThrowArrayBounds)(int32_t, int32_t);
+ void (*pThrowDivZero)();
+ void (*pThrowNoSuchMethod)(int32_t);
+ void (*pThrowNullPointer)();
+ void (*pThrowStackOverflow)(void*);
};
// JNI entrypoints.
-extern uint32_t JniMethodStart(Thread* self)
- UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+extern uint32_t JniMethodStart(Thread* self) UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self)
UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self)
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index 7ecd296..0e61942 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -32,7 +32,7 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(mirror::AbstractMet
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
const void* result = instrumentation->GetQuickCodeFor(method);
- bool interpreter_entry = (result == GetInterpreterEntryPoint());
+ bool interpreter_entry = (result == GetQuickToInterpreterBridge());
instrumentation->PushInstrumentationStackFrame(self, method->IsStatic() ? NULL : this_object,
method, lr, interpreter_entry);
CHECK(result != NULL) << PrettyMethod(method);
diff --git a/runtime/entrypoints/quick/quick_interpreter_entrypoints.cc b/runtime/entrypoints/quick/quick_interpreter_entrypoints.cc
deleted file mode 100644
index 656df8d..0000000
--- a/runtime/entrypoints/quick/quick_interpreter_entrypoints.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "quick_argument_visitor.h"
-#include "callee_save_frame.h"
-#include "dex_file-inl.h"
-#include "interpreter/interpreter.h"
-#include "invoke_arg_array_builder.h"
-#include "mirror/abstract_method-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "object_utils.h"
-
-namespace art {
-
-// Visits arguments on the stack placing them into the shadow frame.
-class BuildShadowFrameVisitor : public QuickArgumentVisitor {
- public:
- BuildShadowFrameVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
- ShadowFrame& sf, size_t first_arg_reg) :
- QuickArgumentVisitor(caller_mh, sp), sf_(sf), cur_reg_(first_arg_reg) {}
-
- virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Primitive::Type type = GetParamPrimitiveType();
- switch (type) {
- case Primitive::kPrimLong: // Fall-through.
- case Primitive::kPrimDouble:
- if (IsSplitLongOrDouble()) {
- sf_.SetVRegLong(cur_reg_, ReadSplitLongParam());
- } else {
- sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress()));
- }
- ++cur_reg_;
- break;
- case Primitive::kPrimNot:
- sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress()));
- break;
- case Primitive::kPrimBoolean: // Fall-through.
- case Primitive::kPrimByte: // Fall-through.
- case Primitive::kPrimChar: // Fall-through.
- case Primitive::kPrimShort: // Fall-through.
- case Primitive::kPrimInt: // Fall-through.
- case Primitive::kPrimFloat:
- sf_.SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress()));
- break;
- case Primitive::kPrimVoid:
- LOG(FATAL) << "UNREACHABLE";
- break;
- }
- ++cur_reg_;
- }
-
- private:
- ShadowFrame& sf_;
- size_t cur_reg_;
-
- DISALLOW_COPY_AND_ASSIGN(BuildShadowFrameVisitor);
-};
-
-extern "C" uint64_t artInterpreterEntry(mirror::AbstractMethod* method, Thread* self,
- mirror::AbstractMethod** sp)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Ensure we don't get thread suspension until the object arguments are safely in the shadow
- // frame.
- const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame");
- FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
-
- MethodHelper mh(method);
- const DexFile::CodeItem* code_item = mh.GetCodeItem();
- uint16_t num_regs = code_item->registers_size_;
- void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
- ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick.
- method, 0, memory));
- size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
- BuildShadowFrameVisitor shadow_frame_builder(mh, sp, *shadow_frame, first_arg_reg);
- shadow_frame_builder.VisitArguments();
- // Push a transition back into managed code onto the linked list in thread.
- ManagedStack fragment;
- self->PushManagedStackFragment(&fragment);
- self->PushShadowFrame(shadow_frame);
- self->EndAssertNoThreadSuspension(old_cause);
-
- if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
- // Ensure static method's class is initialized.
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
- true, true)) {
- DCHECK(Thread::Current()->IsExceptionPending());
- self->PopManagedStackFragment(fragment);
- return 0;
- }
- }
-
- JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame);
- // Pop transition.
- self->PopManagedStackFragment(fragment);
- return result.GetJ();
-}
-
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::AbstractMethod* method = shadow_frame->GetMethod();
- // Ensure static methods are initialized.
- if (method->IsStatic()) {
- Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), true, true);
- }
- uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArray(shadow_frame, arg_offset);
- method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
-}
-
-} // namespace art
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 23a28f9..9907c04 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -94,78 +94,4 @@ extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result,
return o;
}
-static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) {
- intptr_t value = *arg_ptr;
- mirror::Object** value_as_jni_rep = reinterpret_cast<mirror::Object**>(value);
- mirror::Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL;
- CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep))
- << value_as_work_around_rep;
- *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep);
-}
-
-extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(Thread::Current() == self);
- // TODO: this code is specific to ARM
- // On entry the stack pointed by sp is:
- // | arg3 | <- Calling JNI method's frame (and extra bit for out args)
- // | LR |
- // | R3 | arg2
- // | R2 | arg1
- // | R1 | jclass/jobject
- // | R0 | JNIEnv
- // | unused |
- // | unused |
- // | unused | <- sp
- mirror::AbstractMethod* jni_method = self->GetCurrentMethod(NULL);
- DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method);
- intptr_t* arg_ptr = sp + 4; // pointer to r1 on stack
- // Fix up this/jclass argument
- WorkAroundJniBugsForJobject(arg_ptr);
- arg_ptr++;
- // Fix up jobject arguments
- MethodHelper mh(jni_method);
- int reg_num = 2; // Current register being processed, -1 for stack arguments.
- for (uint32_t i = 1; i < mh.GetShortyLength(); i++) {
- char shorty_char = mh.GetShorty()[i];
- if (shorty_char == 'L') {
- WorkAroundJniBugsForJobject(arg_ptr);
- }
- if (shorty_char == 'J' || shorty_char == 'D') {
- if (reg_num == 2) {
- arg_ptr = sp + 8; // skip to out arguments
- reg_num = -1;
- } else if (reg_num == 3) {
- arg_ptr = sp + 10; // skip to out arguments plus 2 slots as long must be aligned
- reg_num = -1;
- } else {
- DCHECK_EQ(reg_num, -1);
- if ((reinterpret_cast<intptr_t>(arg_ptr) & 7) == 4) {
- arg_ptr += 3; // unaligned, pad and move through stack arguments
- } else {
- arg_ptr += 2; // aligned, move through stack arguments
- }
- }
- } else {
- if (reg_num == 2) {
- arg_ptr++; // move through register arguments
- reg_num++;
- } else if (reg_num == 3) {
- arg_ptr = sp + 8; // skip to outgoing stack arguments
- reg_num = -1;
- } else {
- DCHECK_EQ(reg_num, -1);
- arg_ptr++; // move through stack arguments
- }
- }
- }
- // Load expected destination, see Method::RegisterNative
- const void* code = reinterpret_cast<const void*>(jni_method->GetNativeGcMap());
- if (UNLIKELY(code == NULL)) {
- code = GetJniDlsymLookupStub();
- jni_method->RegisterNative(self, code);
- }
- return code;
-}
-
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc b/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
deleted file mode 100644
index 4e3d749..0000000
--- a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "quick_argument_visitor.h"
-#include "dex_file-inl.h"
-#include "entrypoints/entrypoint_utils.h"
-#include "mirror/abstract_method-inl.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/object-inl.h"
-#include "object_utils.h"
-#include "reflection.h"
-#include "scoped_thread_state_change.h"
-#include "thread.h"
-#include "well_known_classes.h"
-
-#include "ScopedLocalRef.h"
-
-namespace art {
-
-// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
-// to jobjects.
-class BuildQuickArgumentVisitor : public QuickArgumentVisitor {
- public:
- BuildQuickArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
- ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
- QuickArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
-
- virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- jvalue val;
- Primitive::Type type = GetParamPrimitiveType();
- switch (type) {
- case Primitive::kPrimNot: {
- mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
- val.l = soa_.AddLocalReference<jobject>(obj);
- break;
- }
- case Primitive::kPrimLong: // Fall-through.
- case Primitive::kPrimDouble:
- if (IsSplitLongOrDouble()) {
- val.j = ReadSplitLongParam();
- } else {
- val.j = *reinterpret_cast<jlong*>(GetParamAddress());
- }
- break;
- case Primitive::kPrimBoolean: // Fall-through.
- case Primitive::kPrimByte: // Fall-through.
- case Primitive::kPrimChar: // Fall-through.
- case Primitive::kPrimShort: // Fall-through.
- case Primitive::kPrimInt: // Fall-through.
- case Primitive::kPrimFloat:
- val.i = *reinterpret_cast<jint*>(GetParamAddress());
- break;
- case Primitive::kPrimVoid:
- LOG(FATAL) << "UNREACHABLE";
- val.j = 0;
- break;
- }
- args_.push_back(val);
- }
-
- private:
- ScopedObjectAccessUnchecked& soa_;
- std::vector<jvalue>& args_;
-
- DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor);
-};
-
-// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
-// which is responsible for recording callee save registers. We explicitly place into jobjects the
-// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
-// field within the proxy object, which will box the primitive arguments and deal with error cases.
-extern "C" uint64_t artQuickProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
- mirror::Object* receiver,
- Thread* self, mirror::AbstractMethod** sp)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
- const char* old_cause =
- self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
- // Register the top of the managed stack, making stack crawlable.
- DCHECK_EQ(*sp, proxy_method);
- self->SetTopOfStack(sp, 0);
- DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
- Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
- self->VerifyStack();
- // Start new JNI local reference state.
- JNIEnvExt* env = self->GetJniEnv();
- ScopedObjectAccessUnchecked soa(env);
- ScopedJniEnvLocalRefState env_state(env);
- // Create local ref. copies of proxy method and the receiver.
- jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
-
- // Placing arguments into args vector and remove the receiver.
- MethodHelper proxy_mh(proxy_method);
- std::vector<jvalue> args;
- BuildQuickArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
- local_ref_visitor.VisitArguments();
- args.erase(args.begin());
-
- // Convert proxy method into expected interface method.
- mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
- DCHECK(interface_method != NULL);
- DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
- jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
-
- // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
- // that performs allocations.
- self->EndAssertNoThreadSuspension(old_cause);
- JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
- rcvr_jobj, interface_method_jobj, args);
- return result.GetJ();
-}
-
-} // namespace art
diff --git a/runtime/entrypoints/quick/quick_stub_entrypoints.cc b/runtime/entrypoints/quick/quick_stub_entrypoints.cc
deleted file mode 100644
index d78bbf3..0000000
--- a/runtime/entrypoints/quick/quick_stub_entrypoints.cc
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "callee_save_frame.h"
-#include "class_linker-inl.h"
-#include "dex_file-inl.h"
-#include "dex_instruction-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/abstract_method-inl.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/object-inl.h"
-#include "object_utils.h"
-#include "scoped_thread_state_change.h"
-
-// Architecture specific assembler helper to deliver exception.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-
-namespace art {
-
-// Lazily resolve a method for quick. Called by stub code.
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
- mirror::Object* receiver,
- mirror::AbstractMethod** sp, Thread* thread)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-#if defined(__arm__)
- // On entry the stack pointed by sp is:
- // | argN | |
- // | ... | |
- // | arg4 | |
- // | arg3 spill | | Caller's frame
- // | arg2 spill | |
- // | arg1 spill | |
- // | Method* | ---
- // | LR |
- // | ... | callee saves
- // | R3 | arg3
- // | R2 | arg2
- // | R1 | arg1
- // | R0 |
- // | Method* | <- sp
- DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
- mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
- uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
- uint32_t pc_offset = 10;
- uintptr_t caller_pc = regs[pc_offset];
-#elif defined(__i386__)
- // On entry the stack pointed by sp is:
- // | argN | |
- // | ... | |
- // | arg4 | |
- // | arg3 spill | | Caller's frame
- // | arg2 spill | |
- // | arg1 spill | |
- // | Method* | ---
- // | Return |
- // | EBP,ESI,EDI | callee saves
- // | EBX | arg3
- // | EDX | arg2
- // | ECX | arg1
- // | EAX/Method* | <- sp
- DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
- mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
- uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
- uintptr_t caller_pc = regs[7];
-#elif defined(__mips__)
- // On entry the stack pointed by sp is:
- // | argN | |
- // | ... | |
- // | arg4 | |
- // | arg3 spill | | Caller's frame
- // | arg2 spill | |
- // | arg1 spill | |
- // | Method* | ---
- // | RA |
- // | ... | callee saves
- // | A3 | arg3
- // | A2 | arg2
- // | A1 | arg1
- // | A0/Method* | <- sp
- DCHECK_EQ(64U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
- mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 64);
- uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
- uint32_t pc_offset = 15;
- uintptr_t caller_pc = regs[pc_offset];
-#else
- UNIMPLEMENTED(FATAL);
- mirror::AbstractMethod** caller_sp = NULL;
- uintptr_t* regs = NULL;
- uintptr_t caller_pc = 0;
-#endif
- FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
- // Start new JNI local reference state
- JNIEnvExt* env = thread->GetJniEnv();
- ScopedObjectAccessUnchecked soa(env);
- ScopedJniEnvLocalRefState env_state(env);
-
- // Compute details about the called method (avoid GCs)
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- mirror::AbstractMethod* caller = *caller_sp;
- InvokeType invoke_type;
- uint32_t dex_method_idx;
-#if !defined(__i386__)
- const char* shorty;
- uint32_t shorty_len;
-#endif
- if (called->IsRuntimeMethod()) {
- uint32_t dex_pc = caller->ToDexPc(caller_pc);
- const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
- CHECK_LT(dex_pc, code->insns_size_in_code_units_);
- const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
- Instruction::Code instr_code = instr->Opcode();
- bool is_range;
- switch (instr_code) {
- case Instruction::INVOKE_DIRECT:
- invoke_type = kDirect;
- is_range = false;
- break;
- case Instruction::INVOKE_DIRECT_RANGE:
- invoke_type = kDirect;
- is_range = true;
- break;
- case Instruction::INVOKE_STATIC:
- invoke_type = kStatic;
- is_range = false;
- break;
- case Instruction::INVOKE_STATIC_RANGE:
- invoke_type = kStatic;
- is_range = true;
- break;
- case Instruction::INVOKE_SUPER:
- invoke_type = kSuper;
- is_range = false;
- break;
- case Instruction::INVOKE_SUPER_RANGE:
- invoke_type = kSuper;
- is_range = true;
- break;
- case Instruction::INVOKE_VIRTUAL:
- invoke_type = kVirtual;
- is_range = false;
- break;
- case Instruction::INVOKE_VIRTUAL_RANGE:
- invoke_type = kVirtual;
- is_range = true;
- break;
- case Instruction::INVOKE_INTERFACE:
- invoke_type = kInterface;
- is_range = false;
- break;
- case Instruction::INVOKE_INTERFACE_RANGE:
- invoke_type = kInterface;
- is_range = true;
- break;
- default:
- LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
- // Avoid used uninitialized warnings.
- invoke_type = kDirect;
- is_range = false;
- }
- dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
-#if !defined(__i386__)
- shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
-#endif
- } else {
- invoke_type = kStatic;
- dex_method_idx = called->GetDexMethodIndex();
-#if !defined(__i386__)
- MethodHelper mh(called);
- shorty = mh.GetShorty();
- shorty_len = mh.GetShortyLength();
-#endif
- }
-#if !defined(__i386__)
- // Discover shorty (avoid GCs)
- size_t args_in_regs = 0;
- for (size_t i = 1; i < shorty_len; i++) {
- char c = shorty[i];
- args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
- if (args_in_regs > 3) {
- args_in_regs = 3;
- break;
- }
- }
- // Place into local references incoming arguments from the caller's register arguments
- size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
- if (invoke_type != kStatic) {
- mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
- cur_arg++;
- if (args_in_regs < 3) {
- // If we thought we had fewer than 3 arguments in registers, account for the receiver
- args_in_regs++;
- }
- soa.AddLocalReference<jobject>(obj);
- }
- size_t shorty_index = 1; // skip return value
- // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
- // R0)
- while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
- char c = shorty[shorty_index];
- shorty_index++;
- if (c == 'L') {
- mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
- soa.AddLocalReference<jobject>(obj);
- }
- cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
- }
- // Place into local references incoming arguments from the caller's stack arguments
- cur_arg += pc_offset + 1; // skip LR/RA, Method* and spills for R1-R3/A1-A3 and callee saves
- while (shorty_index < shorty_len) {
- char c = shorty[shorty_index];
- shorty_index++;
- if (c == 'L') {
- mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
- soa.AddLocalReference<jobject>(obj);
- }
- cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
- }
-#endif
- // Resolve method filling in dex cache
- if (called->IsRuntimeMethod()) {
- called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
- }
- const void* code = NULL;
- if (LIKELY(!thread->IsExceptionPending())) {
- // Incompatible class change should have been handled in resolve method.
- CHECK(!called->CheckIncompatibleClassChange(invoke_type));
- // Refine called method based on receiver.
- if (invoke_type == kVirtual) {
- called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
- } else if (invoke_type == kInterface) {
- called = receiver->GetClass()->FindVirtualMethodForInterface(called);
- }
- // Ensure that the called method's class is initialized.
- mirror::Class* called_class = called->GetDeclaringClass();
- linker->EnsureInitialized(called_class, true, true);
- if (LIKELY(called_class->IsInitialized())) {
- code = called->GetEntryPointFromCompiledCode();
- } else if (called_class->IsInitializing()) {
- if (invoke_type == kStatic) {
- // 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);
- } else {
- // No trampoline for non-static methods.
- code = called->GetEntryPointFromCompiledCode();
- }
- } else {
- DCHECK(called_class->IsErroneous());
- }
- }
- if (UNLIKELY(code == NULL)) {
- // Something went wrong in ResolveMethod or EnsureInitialized,
- // go into deliver exception with the pending exception in r0
- CHECK(thread->IsExceptionPending());
- code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
- regs[0] = reinterpret_cast<uintptr_t>(thread->GetException(NULL));
- thread->ClearException();
- } else {
- // Expect class to at least be initializing.
- DCHECK(called->GetDeclaringClass()->IsInitializing());
- // Don't want infinite recursion.
- DCHECK(code != GetResolutionTrampoline(linker));
- // Set up entry into main method
- regs[0] = reinterpret_cast<uintptr_t>(called);
- }
- return code;
-}
-
-// Called by the abstract method error stub.
-extern "C" void artThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
- mirror::AbstractMethod** sp)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-#if !defined(ART_USE_PORTABLE_COMPILER)
- FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-#else
- UNUSED(sp);
-#endif
- ThrowAbstractMethodError(method);
- self->QuickDeliverException();
-}
-
-} // namespace art
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
new file mode 100644
index 0000000..9bf02e8
--- /dev/null
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "callee_save_frame.h"
+#include "dex_file-inl.h"
+#include "dex_instruction-inl.h"
+#include "interpreter/interpreter.h"
+#include "invoke_arg_array_builder.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "object_utils.h"
+#include "runtime.h"
+
+namespace art {
+
+// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
+class QuickArgumentVisitor {
+ public:
+// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
+// Size of Runtime::kRefAndArgs callee save frame.
+// Size of Method* and register parameters in out stack arguments.
+#if defined(__arm__)
+ // The callee save frame is pointed to by SP.
+ // | argN | |
+ // | ... | |
+ // | arg4 | |
+ // | arg3 spill | | Caller's frame
+ // | arg2 spill | |
+ // | arg1 spill | |
+ // | Method* | ---
+ // | LR |
+ // | ... | callee saves
+ // | R3 | arg3
+ // | R2 | arg2
+ // | R1 | arg1
+ // | R0 |
+ // | Method* | <- sp
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 44
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
+#define QUICK_STACK_ARG_SKIP 16
+#elif defined(__mips__)
+ // The callee save frame is pointed to by SP.
+ // | argN | |
+ // | ... | |
+ // | arg4 | |
+ // | arg3 spill | | Caller's frame
+ // | arg2 spill | |
+ // | arg1 spill | |
+ // | Method* | ---
+ // | RA |
+ // | ... | callee saves
+ // | A3 | arg3
+ // | A2 | arg2
+ // | A1 | arg1
+ // | A0/Method* | <- sp
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 60
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
+#define QUICK_STACK_ARG_SKIP 16
+#elif defined(__i386__)
+ // The callee save frame is pointed to by SP.
+ // | argN | |
+ // | ... | |
+ // | arg4 | |
+ // | arg3 spill | | Caller's frame
+ // | arg2 spill | |
+ // | arg1 spill | |
+ // | Method* | ---
+ // | Return |
+ // | EBP,ESI,EDI | callee saves
+ // | EBX | arg3
+ // | EDX | arg2
+ // | ECX | arg1
+ // | EAX/Method* | <- sp
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 28
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
+#define QUICK_STACK_ARG_SKIP 16
+#else
+#error "Unsupported architecture"
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 0
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
+#define QUICK_STACK_ARG_SKIP 0
+#endif
+
+ static mirror::AbstractMethod* GetCallingMethod(mirror::AbstractMethod** sp) {
+ byte* previous_sp = reinterpret_cast<byte*>(sp) +
+ QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE;
+ return *reinterpret_cast<mirror::AbstractMethod**>(previous_sp);
+ }
+
+ static uintptr_t GetCallingPc(mirror::AbstractMethod** sp) {
+ byte* lr = reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET;
+ return *reinterpret_cast<uintptr_t*>(lr);
+ }
+
+ QuickArgumentVisitor(mirror::AbstractMethod** sp, bool is_static,
+ const char* shorty, uint32_t shorty_len)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+ is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len),
+ args_in_regs_(ComputeArgsInRegs(is_static, shorty, shorty_len)),
+ num_params_((is_static ? 0 : 1) + shorty_len - 1), // +1 for this, -1 for return type
+ reg_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
+ stack_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
+ + QUICK_STACK_ARG_SKIP),
+ cur_args_(reg_args_),
+ cur_arg_index_(0),
+ param_index_(0),
+ is_split_long_or_double_(false) {
+ DCHECK_EQ(static_cast<size_t>(QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE),
+ Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+ }
+
+ virtual ~QuickArgumentVisitor() {}
+
+ virtual void Visit() = 0;
+
+ Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t index = param_index_;
+ if (is_static_) {
+ index++; // 0th argument must skip return value at start of the shorty
+ } else if (index == 0) {
+ return Primitive::kPrimNot;
+ }
+ CHECK_LT(index, shorty_len_);
+ return Primitive::GetType(shorty_[index]);
+ }
+
+ byte* GetParamAddress() const {
+ return cur_args_ + (cur_arg_index_ * kPointerSize);
+ }
+
+ bool IsSplitLongOrDouble() const {
+ return is_split_long_or_double_;
+ }
+
+ bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetParamPrimitiveType() == Primitive::kPrimNot;
+ }
+
+ bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Primitive::Type type = GetParamPrimitiveType();
+ return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
+ }
+
+ uint64_t ReadSplitLongParam() const {
+ DCHECK(IsSplitLongOrDouble());
+ uint64_t low_half = *reinterpret_cast<uint32_t*>(GetParamAddress());
+ uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args_);
+ return (low_half & 0xffffffffULL) | (high_half << 32);
+ }
+
+ void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ for (cur_arg_index_ = 0; cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
+ is_split_long_or_double_ = (cur_arg_index_ == 2) && IsParamALongOrDouble();
+ Visit();
+ cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+ param_index_++;
+ }
+ cur_args_ = stack_args_;
+ cur_arg_index_ = is_split_long_or_double_ ? 1 : 0;
+ is_split_long_or_double_ = false;
+ while (param_index_ < num_params_) {
+ Visit();
+ cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+ param_index_++;
+ }
+ }
+
+ private:
+ static size_t ComputeArgsInRegs(bool is_static, const char* shorty, uint32_t shorty_len)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t args_in_regs = (is_static ? 0 : 1);
+ for (size_t i = 0; i < shorty_len; i++) {
+ char s = shorty[i];
+ if (s == 'J' || s == 'D') {
+ args_in_regs += 2;
+ } else {
+ args_in_regs++;
+ }
+ if (args_in_regs > 3) {
+ args_in_regs = 3;
+ break;
+ }
+ }
+ return args_in_regs;
+ }
+
+ const bool is_static_;
+ const char* const shorty_;
+ const uint32_t shorty_len_;
+ const size_t args_in_regs_;
+ const size_t num_params_;
+ byte* const reg_args_;
+ byte* const stack_args_;
+ byte* cur_args_;
+ size_t cur_arg_index_;
+ size_t param_index_;
+ // Does a 64bit parameter straddle the register and stack arguments?
+ bool is_split_long_or_double_;
+};
+
+// Visits arguments on the stack placing them into the shadow frame.
+class BuildShadowFrameVisitor : public QuickArgumentVisitor {
+ public:
+ BuildShadowFrameVisitor(mirror::AbstractMethod** sp, bool is_static, const char* shorty,
+ uint32_t shorty_len, ShadowFrame& sf, size_t first_arg_reg) :
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {}
+
+ virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Primitive::Type type = GetParamPrimitiveType();
+ switch (type) {
+ case Primitive::kPrimLong: // Fall-through.
+ case Primitive::kPrimDouble:
+ if (IsSplitLongOrDouble()) {
+ sf_.SetVRegLong(cur_reg_, ReadSplitLongParam());
+ } else {
+ sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress()));
+ }
+ ++cur_reg_;
+ break;
+ case Primitive::kPrimNot:
+ sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress()));
+ break;
+ case Primitive::kPrimBoolean: // Fall-through.
+ case Primitive::kPrimByte: // Fall-through.
+ case Primitive::kPrimChar: // Fall-through.
+ case Primitive::kPrimShort: // Fall-through.
+ case Primitive::kPrimInt: // Fall-through.
+ case Primitive::kPrimFloat:
+ sf_.SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress()));
+ break;
+ case Primitive::kPrimVoid:
+ LOG(FATAL) << "UNREACHABLE";
+ break;
+ }
+ ++cur_reg_;
+ }
+
+ private:
+ ShadowFrame& sf_;
+ size_t cur_reg_;
+
+ DISALLOW_COPY_AND_ASSIGN(BuildShadowFrameVisitor);
+};
+
+extern "C" uint64_t artQuickToInterpreterBridge(mirror::AbstractMethod* method, Thread* self,
+ mirror::AbstractMethod** sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // Ensure we don't get thread suspension until the object arguments are safely in the shadow
+ // frame.
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
+
+ if (method->IsAbstract()) {
+ ThrowAbstractMethodError(method);
+ return 0;
+ } else {
+ const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame");
+ MethodHelper mh(method);
+ const DexFile::CodeItem* code_item = mh.GetCodeItem();
+ uint16_t num_regs = code_item->registers_size_;
+ void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
+ ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick.
+ method, 0, memory));
+ size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
+ BuildShadowFrameVisitor shadow_frame_builder(sp, mh.IsStatic(), mh.GetShorty(),
+ mh.GetShortyLength(),
+ *shadow_frame, first_arg_reg);
+ shadow_frame_builder.VisitArguments();
+ // Push a transition back into managed code onto the linked list in thread.
+ ManagedStack fragment;
+ self->PushManagedStackFragment(&fragment);
+ self->PushShadowFrame(shadow_frame);
+ self->EndAssertNoThreadSuspension(old_cause);
+
+ if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
+ // Ensure static method's class is initialized.
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
+ true, true)) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ self->PopManagedStackFragment(fragment);
+ return 0;
+ }
+ }
+
+ JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame);
+ // Pop transition.
+ self->PopManagedStackFragment(fragment);
+ return result.GetJ();
+ }
+}
+
+// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
+// to jobjects.
+class BuildQuickArgumentVisitor : public QuickArgumentVisitor {
+ public:
+ BuildQuickArgumentVisitor(mirror::AbstractMethod** sp, bool is_static, const char* shorty,
+ uint32_t shorty_len, ScopedObjectAccessUnchecked* soa,
+ std::vector<jvalue>* args) :
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {}
+
+ virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ jvalue val;
+ Primitive::Type type = GetParamPrimitiveType();
+ switch (type) {
+ case Primitive::kPrimNot: {
+ mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
+ val.l = soa_->AddLocalReference<jobject>(obj);
+ break;
+ }
+ case Primitive::kPrimLong: // Fall-through.
+ case Primitive::kPrimDouble:
+ if (IsSplitLongOrDouble()) {
+ val.j = ReadSplitLongParam();
+ } else {
+ val.j = *reinterpret_cast<jlong*>(GetParamAddress());
+ }
+ break;
+ case Primitive::kPrimBoolean: // Fall-through.
+ case Primitive::kPrimByte: // Fall-through.
+ case Primitive::kPrimChar: // Fall-through.
+ case Primitive::kPrimShort: // Fall-through.
+ case Primitive::kPrimInt: // Fall-through.
+ case Primitive::kPrimFloat:
+ val.i = *reinterpret_cast<jint*>(GetParamAddress());
+ break;
+ case Primitive::kPrimVoid:
+ LOG(FATAL) << "UNREACHABLE";
+ val.j = 0;
+ break;
+ }
+ args_->push_back(val);
+ }
+
+ private:
+ ScopedObjectAccessUnchecked* soa_;
+ std::vector<jvalue>* args_;
+
+ DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor);
+};
+
+// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
+// which is responsible for recording callee save registers. We explicitly place into jobjects the
+// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
+// field within the proxy object, which will box the primitive arguments and deal with error cases.
+extern "C" uint64_t artQuickProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
+ mirror::Object* receiver,
+ Thread* self, mirror::AbstractMethod** sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
+ const char* old_cause =
+ self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
+ // Register the top of the managed stack, making stack crawlable.
+ DCHECK_EQ(*sp, proxy_method);
+ self->SetTopOfStack(sp, 0);
+ DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
+ Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+ self->VerifyStack();
+ // Start new JNI local reference state.
+ JNIEnvExt* env = self->GetJniEnv();
+ ScopedObjectAccessUnchecked soa(env);
+ ScopedJniEnvLocalRefState env_state(env);
+ // Create local ref. copies of proxy method and the receiver.
+ jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
+
+ // Placing arguments into args vector and remove the receiver.
+ MethodHelper proxy_mh(proxy_method);
+ std::vector<jvalue> args;
+ BuildQuickArgumentVisitor local_ref_visitor(sp, proxy_mh.IsStatic(), proxy_mh.GetShorty(),
+ proxy_mh.GetShortyLength(), &soa, &args);
+ local_ref_visitor.VisitArguments();
+ args.erase(args.begin());
+
+ // Convert proxy method into expected interface method.
+ mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
+ DCHECK(interface_method != NULL);
+ DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
+ jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
+
+ // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
+ // that performs allocations.
+ self->EndAssertNoThreadSuspension(old_cause);
+ JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
+ rcvr_jobj, interface_method_jobj, args);
+ return result.GetJ();
+}
+
+// Read object references held in arguments from quick frames and place in a JNI local references,
+// so they don't get garbage collected.
+class RememberFoGcArgumentVisitor : public QuickArgumentVisitor {
+ public:
+ RememberFoGcArgumentVisitor(mirror::AbstractMethod** sp, bool is_static, const char* shorty,
+ uint32_t shorty_len, ScopedObjectAccessUnchecked* soa) :
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {}
+
+ virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (IsParamAReference()) {
+ soa_->AddLocalReference<jobject>(*reinterpret_cast<mirror::Object**>(GetParamAddress()));
+ }
+ }
+
+ private:
+ ScopedObjectAccessUnchecked* soa_;
+
+ DISALLOW_COPY_AND_ASSIGN(RememberFoGcArgumentVisitor);
+};
+
+// Lazily resolve a method for quick. Called by stub code.
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+ mirror::Object* receiver,
+ Thread* thread, mirror::AbstractMethod** sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
+ // Start new JNI local reference state
+ JNIEnvExt* env = thread->GetJniEnv();
+ ScopedObjectAccessUnchecked soa(env);
+ ScopedJniEnvLocalRefState env_state(env);
+ const char* old_cause = thread->StartAssertNoThreadSuspension("Quick method resolution set up");
+
+ // Compute details about the called method (avoid GCs)
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ mirror::AbstractMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
+ InvokeType invoke_type;
+ const DexFile* dex_file;
+ uint32_t dex_method_idx;
+ if (called->IsRuntimeMethod()) {
+ uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
+ const DexFile::CodeItem* code;
+ {
+ MethodHelper mh(caller);
+ dex_file = &mh.GetDexFile();
+ code = mh.GetCodeItem();
+ }
+ CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+ const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+ Instruction::Code instr_code = instr->Opcode();
+ bool is_range;
+ switch (instr_code) {
+ case Instruction::INVOKE_DIRECT:
+ invoke_type = kDirect;
+ is_range = false;
+ break;
+ case Instruction::INVOKE_DIRECT_RANGE:
+ invoke_type = kDirect;
+ is_range = true;
+ break;
+ case Instruction::INVOKE_STATIC:
+ invoke_type = kStatic;
+ is_range = false;
+ break;
+ case Instruction::INVOKE_STATIC_RANGE:
+ invoke_type = kStatic;
+ is_range = true;
+ break;
+ case Instruction::INVOKE_SUPER:
+ invoke_type = kSuper;
+ is_range = false;
+ break;
+ case Instruction::INVOKE_SUPER_RANGE:
+ invoke_type = kSuper;
+ is_range = true;
+ break;
+ case Instruction::INVOKE_VIRTUAL:
+ invoke_type = kVirtual;
+ is_range = false;
+ break;
+ case Instruction::INVOKE_VIRTUAL_RANGE:
+ invoke_type = kVirtual;
+ is_range = true;
+ break;
+ case Instruction::INVOKE_INTERFACE:
+ invoke_type = kInterface;
+ is_range = false;
+ break;
+ case Instruction::INVOKE_INTERFACE_RANGE:
+ invoke_type = kInterface;
+ is_range = true;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
+ // Avoid used uninitialized warnings.
+ invoke_type = kDirect;
+ is_range = false;
+ }
+ dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+
+ } else {
+ invoke_type = kStatic;
+ dex_file = &MethodHelper(called).GetDexFile();
+ dex_method_idx = called->GetDexMethodIndex();
+ }
+ uint32_t shorty_len;
+ const char* shorty =
+ dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), &shorty_len);
+ RememberFoGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa);
+ visitor.VisitArguments();
+ thread->EndAssertNoThreadSuspension(old_cause);
+ // Resolve method filling in dex cache.
+ if (called->IsRuntimeMethod()) {
+ called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
+ }
+ const void* code = NULL;
+ if (LIKELY(!thread->IsExceptionPending())) {
+ // Incompatible class change should have been handled in resolve method.
+ CHECK(!called->CheckIncompatibleClassChange(invoke_type));
+ // Refine called method based on receiver.
+ if (invoke_type == kVirtual) {
+ called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
+ } else if (invoke_type == kInterface) {
+ called = receiver->GetClass()->FindVirtualMethodForInterface(called);
+ }
+ // Ensure that the called method's class is initialized.
+ mirror::Class* called_class = called->GetDeclaringClass();
+ linker->EnsureInitialized(called_class, true, true);
+ if (LIKELY(called_class->IsInitialized())) {
+ code = called->GetEntryPointFromCompiledCode();
+ } else if (called_class->IsInitializing()) {
+ if (invoke_type == kStatic) {
+ // 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);
+ } else {
+ // No trampoline for non-static methods.
+ code = called->GetEntryPointFromCompiledCode();
+ }
+ } else {
+ DCHECK(called_class->IsErroneous());
+ }
+ }
+ CHECK_EQ(code == NULL, thread->IsExceptionPending());
+#ifdef MOVING_GARBAGE_COLLECTOR
+ // TODO: locally saved objects may have moved during a GC during resolution. Need to update the
+ // registers so that the stale objects aren't passed to the method we've resolved.
+ UNIMPLEMENTED(WARNING);
+#endif
+ // Place called method in callee-save frame to be placed as first argument to quick method.
+ *sp = called;
+ return code;
+}
+
+} // namespace art
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index c0b85f4..c3b66b3 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -60,7 +60,7 @@ bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
const void* new_code;
if (uninstall) {
if (forced_interpret_only_ && !method->IsNative() && !method->IsProxyMethod()) {
- new_code = GetInterpreterEntryPoint();
+ new_code = GetCompiledCodeToInterpreterBridge();
} else if (is_initialized || !method->IsStatic() || method->IsConstructor()) {
new_code = class_linker->GetOatCodeFor(method);
} else {
@@ -68,9 +68,9 @@ bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
}
} else { // !uninstall
if (!interpreter_stubs_installed_ || method->IsNative()) {
- new_code = GetInstrumentationEntryPoint();
+ new_code = GetQuickInstrumentationEntryPoint();
} else {
- new_code = GetInterpreterEntryPoint();
+ new_code = GetCompiledCodeToInterpreterBridge();
}
}
method->SetEntryPointFromCompiledCode(new_code);
@@ -82,15 +82,15 @@ bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
const void* new_code;
if (uninstall) {
if (forced_interpret_only_ && !method->IsNative() && !method->IsProxyMethod()) {
- new_code = GetInterpreterEntryPoint();
+ new_code = GetCompiledCodeToInterpreterBridge();
} else {
new_code = class_linker->GetOatCodeFor(method);
}
} else { // !uninstall
if (!interpreter_stubs_installed_ || method->IsNative()) {
- new_code = GetInstrumentationEntryPoint();
+ new_code = GetQuickInstrumentationEntryPoint();
} else {
- new_code = GetInterpreterEntryPoint();
+ new_code = GetCompiledCodeToInterpreterBridge();
}
}
method->SetEntryPointFromCompiledCode(new_code);
@@ -159,7 +159,7 @@ static void InstrumentationInstallStack(Thread* thread, void* arg)
LOG(INFO) << "Installing exit stubs in " << thread_name;
}
UniquePtr<Context> context(Context::Create());
- uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
+ uintptr_t instrumentation_exit_pc = GetQuickInstrumentationExitPc();
InstallStackVisitor visitor(thread, context.get(), instrumentation_exit_pc);
visitor.WalkStack(true);
@@ -251,7 +251,7 @@ static void InstrumentationRestoreStack(Thread* thread, void* arg)
std::deque<instrumentation::InstrumentationStackFrame>* stack = thread->GetInstrumentationStack();
if (stack->size() > 0) {
Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
- uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
+ uintptr_t instrumentation_exit_pc = GetQuickInstrumentationExitPc();
RestoreStackVisitor visitor(thread, instrumentation_exit_pc, instrumentation);
visitor.WalkStack(true);
CHECK_EQ(visitor.frames_removed_, stack->size());
@@ -384,9 +384,9 @@ void Instrumentation::UpdateMethodsCode(mirror::AbstractMethod* method, const vo
method->SetEntryPointFromCompiledCode(code);
} else {
if (!interpreter_stubs_installed_ || method->IsNative()) {
- method->SetEntryPointFromCompiledCode(GetInstrumentationEntryPoint());
+ method->SetEntryPointFromCompiledCode(GetQuickInstrumentationEntryPoint());
} else {
- method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
+ method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
}
}
}
@@ -396,8 +396,8 @@ const void* Instrumentation::GetQuickCodeFor(const mirror::AbstractMethod* metho
if (LIKELY(!instrumentation_stubs_installed_)) {
const void* code = method->GetEntryPointFromCompiledCode();
DCHECK(code != NULL);
- if (LIKELY(code != GetResolutionTrampoline(runtime->GetClassLinker()) &&
- code != GetInterpreterEntryPoint())) {
+ if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker()) &&
+ code != GetQuickToInterpreterBridge())) {
return code;
}
}
@@ -548,7 +548,7 @@ uint64_t Instrumentation::PopInstrumentationStackFrame(Thread* self, uintptr_t*
<< " result is " << std::hex << return_value.GetJ();
}
self->SetDeoptimizationReturnValue(return_value);
- return static_cast<uint64_t>(GetDeoptimizationEntryPoint()) |
+ return static_cast<uint64_t>(GetQuickDeoptimizationEntryPoint()) |
(static_cast<uint64_t>(*return_pc) << 32);
} else {
if (kVerboseInstrumentation) {
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index ef4b95c..6e35d93 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -148,7 +148,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
}
} else {
// Not special, continue with regular interpreter execution.
- artInterpreterToInterpreterEntry(self, mh, code_item, shadow_frame, result);
+ artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result);
}
}
@@ -3039,6 +3039,10 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c
static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame, JValue result_register) {
+ DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
+ shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
+ DCHECK(!shadow_frame.GetMethod()->IsAbstract());
+ DCHECK(!shadow_frame.GetMethod()->IsNative());
if (shadow_frame.GetMethod()->IsPreverified()) {
// Enter the "without access check" interpreter.
return ExecuteImpl<false>(self, mh, code_item, shadow_frame, result_register);
@@ -3150,8 +3154,7 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa
}
JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
- ShadowFrame& shadow_frame)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ShadowFrame& shadow_frame) {
DCHECK_EQ(self, Thread::Current());
if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
ThrowStackOverflowError(self);
@@ -3161,10 +3164,9 @@ JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::C
return Execute(self, mh, code_item, shadow_frame, JValue());
}
-void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result) {
if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
ThrowStackOverflowError(self);
return;
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index 17884b9..af4a147 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -47,9 +47,9 @@ extern JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh,
ShadowFrame& shadow_frame)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result)
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
} // namespace interpreter
diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h
index ad66ada..fcac481 100644
--- a/runtime/jni_internal.h
+++ b/runtime/jni_internal.h
@@ -144,6 +144,10 @@ struct JNIEnvExt : public JNIEnv {
return Offset(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie));
}
+ static Offset SelfOffset() {
+ return Offset(OFFSETOF_MEMBER(JNIEnvExt, self));
+ }
+
Thread* const self;
JavaVMExt* vm;
diff --git a/runtime/mirror/abstract_method-inl.h b/runtime/mirror/abstract_method-inl.h
index d235e3e..8fde99b 100644
--- a/runtime/mirror/abstract_method-inl.h
+++ b/runtime/mirror/abstract_method-inl.h
@@ -114,11 +114,11 @@ inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const {
if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
return;
}
- if (pc == GetInstrumentationExitPc()) {
+ if (pc == GetQuickInstrumentationExitPc()) {
return;
}
const void* code = GetEntryPointFromCompiledCode();
- if (code == GetInterpreterEntryPoint() || code == GetInstrumentationEntryPoint()) {
+ if (code == GetCompiledCodeToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
return;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
index 4d7f99e..93065e7 100644
--- a/runtime/mirror/abstract_method.cc
+++ b/runtime/mirror/abstract_method.cc
@@ -321,6 +321,7 @@ bool AbstractMethod::IsRegistered() const {
return native_method != jni_stub;
}
+extern "C" void art_work_around_app_jni_bugs(JNIEnv*, jobject);
void AbstractMethod::RegisterNative(Thread* self, const void* native_method) {
DCHECK(Thread::Current() == self);
CHECK(IsNative()) << PrettyMethod(this);
@@ -332,10 +333,10 @@ void AbstractMethod::RegisterNative(Thread* self, const void* native_method) {
// around JNI bugs, that include not giving Object** SIRT references to native methods. Direct
// the native method to runtime support and store the target somewhere runtime support will
// find it.
-#if defined(__arm__) && !defined(ART_USE_PORTABLE_COMPILER)
- SetNativeMethod(native_method);
-#else
+#if defined(__i386__)
UNIMPLEMENTED(FATAL);
+#else
+ SetNativeMethod(reinterpret_cast<void*>(art_work_around_app_jni_bugs));
#endif
SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, gc_map_),
reinterpret_cast<const uint8_t*>(native_method), false);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index b352d08..32ab4f9 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -144,8 +144,6 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVe
if (targetSdkVersion > 0 && targetSdkVersion <= 13 /* honeycomb-mr2 */) {
Runtime* runtime = Runtime::Current();
JavaVMExt* vm = runtime->GetJavaVM();
-
-#if !defined(ART_USE_PORTABLE_COMPILER)
if (vm->check_jni) {
LOG(WARNING) << "Turning off CheckJNI so we can turn on JNI app bug workarounds...";
Thread* self = static_cast<JNIEnvExt*>(env)->self;
@@ -158,11 +156,6 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVe
<< targetSdkVersion << "...";
vm->work_around_app_jni_bugs = true;
-#else
- UNUSED(env);
- LOG(WARNING) << "LLVM does not work-around app jni bugs.";
- vm->work_around_app_jni_bugs = false;
-#endif
}
}
diff --git a/runtime/oat.cc b/runtime/oat.cc
index e606953..c01f77c 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -22,7 +22,7 @@
namespace art {
const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '0', '6', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '0', '7', '\0' };
OatHeader::OatHeader() {
memset(this, 0, sizeof(*this));
@@ -57,10 +57,13 @@ OatHeader::OatHeader(InstructionSet instruction_set,
UpdateChecksum(image_file_location.data(), image_file_location_size_);
executable_offset_ = 0;
- interpreter_to_interpreter_entry_offset_ = 0;
- interpreter_to_quick_entry_offset_ = 0;
+ interpreter_to_interpreter_bridge_offset_ = 0;
+ interpreter_to_compiled_code_bridge_offset_ = 0;
+ jni_dlsym_lookup_offset_ = 0;
portable_resolution_trampoline_offset_ = 0;
+ portable_to_interpreter_bridge_offset_ = 0;
quick_resolution_trampoline_offset_ = 0;
+ quick_to_interpreter_bridge_offset_ = 0;
}
bool OatHeader::IsValid() const {
@@ -111,42 +114,61 @@ void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
UpdateChecksum(&executable_offset_, sizeof(executable_offset));
}
-const void* OatHeader::GetInterpreterToInterpreterEntry() const {
- return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterEntryOffset();
+const void* OatHeader::GetInterpreterToInterpreterBridge() const {
+ return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
}
-uint32_t OatHeader::GetInterpreterToInterpreterEntryOffset() const {
+uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
DCHECK(IsValid());
- CHECK_GE(interpreter_to_interpreter_entry_offset_, executable_offset_);
- return interpreter_to_interpreter_entry_offset_;
+ CHECK_GE(interpreter_to_interpreter_bridge_offset_, executable_offset_);
+ return interpreter_to_interpreter_bridge_offset_;
}
-void OatHeader::SetInterpreterToInterpreterEntryOffset(uint32_t offset) {
+void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
CHECK(offset == 0 || offset >= executable_offset_);
DCHECK(IsValid());
- DCHECK_EQ(interpreter_to_interpreter_entry_offset_, 0U) << offset;
+ DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
- interpreter_to_interpreter_entry_offset_ = offset;
- UpdateChecksum(&interpreter_to_interpreter_entry_offset_, sizeof(offset));
+ interpreter_to_interpreter_bridge_offset_ = offset;
+ UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
}
-const void* OatHeader::GetInterpreterToQuickEntry() const {
- return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToQuickEntryOffset();
+const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
+ return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
}
-uint32_t OatHeader::GetInterpreterToQuickEntryOffset() const {
+uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
DCHECK(IsValid());
- CHECK_GE(interpreter_to_quick_entry_offset_, interpreter_to_interpreter_entry_offset_);
- return interpreter_to_quick_entry_offset_;
+ CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
+ return interpreter_to_compiled_code_bridge_offset_;
}
-void OatHeader::SetInterpreterToQuickEntryOffset(uint32_t offset) {
- CHECK(offset == 0 || offset >= interpreter_to_interpreter_entry_offset_);
+void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
+ CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
DCHECK(IsValid());
- DCHECK_EQ(interpreter_to_quick_entry_offset_, 0U) << offset;
+ DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
- interpreter_to_quick_entry_offset_ = offset;
- UpdateChecksum(&interpreter_to_quick_entry_offset_, sizeof(offset));
+ interpreter_to_compiled_code_bridge_offset_ = offset;
+ UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
+}
+
+const void* OatHeader::GetJniDlsymLookup() const {
+ return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
+}
+
+uint32_t OatHeader::GetJniDlsymLookupOffset() const {
+ DCHECK(IsValid());
+ CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
+ return jni_dlsym_lookup_offset_;
+}
+
+void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
+ CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
+ DCHECK(IsValid());
+ DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
+
+ jni_dlsym_lookup_offset_ = offset;
+ UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
}
const void* OatHeader::GetPortableResolutionTrampoline() const {
@@ -155,12 +177,12 @@ const void* OatHeader::GetPortableResolutionTrampoline() const {
uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
DCHECK(IsValid());
- CHECK_GE(portable_resolution_trampoline_offset_, interpreter_to_quick_entry_offset_);
+ CHECK_GE(portable_resolution_trampoline_offset_, jni_dlsym_lookup_offset_);
return portable_resolution_trampoline_offset_;
}
void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
- CHECK(offset == 0 || offset >= interpreter_to_quick_entry_offset_);
+ CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
DCHECK(IsValid());
DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
@@ -168,18 +190,37 @@ void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
}
+const void* OatHeader::GetPortableToInterpreterBridge() const {
+ return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
+}
+
+uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
+ DCHECK(IsValid());
+ CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
+ return portable_to_interpreter_bridge_offset_;
+}
+
+void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
+ CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
+ DCHECK(IsValid());
+ DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
+
+ portable_to_interpreter_bridge_offset_ = offset;
+ UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
+}
+
const void* OatHeader::GetQuickResolutionTrampoline() const {
return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
}
uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
DCHECK(IsValid());
- CHECK_GE(quick_resolution_trampoline_offset_, portable_resolution_trampoline_offset_);
+ CHECK_GE(quick_resolution_trampoline_offset_, portable_to_interpreter_bridge_offset_);
return quick_resolution_trampoline_offset_;
}
void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
- CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
+ CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
DCHECK(IsValid());
DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
@@ -187,6 +228,25 @@ void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
}
+const void* OatHeader::GetQuickToInterpreterBridge() const {
+ return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
+}
+
+uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
+ DCHECK(IsValid());
+ CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
+ return quick_to_interpreter_bridge_offset_;
+}
+
+void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
+ CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
+ DCHECK(IsValid());
+ DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
+
+ quick_to_interpreter_bridge_offset_ = offset;
+ UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
+}
+
uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
CHECK(IsValid());
return image_file_location_oat_checksum_;
diff --git a/runtime/oat.h b/runtime/oat.h
index 4bd1871..a5c6bed 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -44,18 +44,32 @@ class PACKED(4) OatHeader {
}
uint32_t GetExecutableOffset() const;
void SetExecutableOffset(uint32_t executable_offset);
- const void* GetInterpreterToInterpreterEntry() const;
- uint32_t GetInterpreterToInterpreterEntryOffset() const;
- void SetInterpreterToInterpreterEntryOffset(uint32_t offset);
- const void* GetInterpreterToQuickEntry() const;
- uint32_t GetInterpreterToQuickEntryOffset() const;
- void SetInterpreterToQuickEntryOffset(uint32_t offset);
+
+ const void* GetInterpreterToInterpreterBridge() const;
+ uint32_t GetInterpreterToInterpreterBridgeOffset() const;
+ void SetInterpreterToInterpreterBridgeOffset(uint32_t offset);
+ const void* GetInterpreterToCompiledCodeBridge() const;
+ uint32_t GetInterpreterToCompiledCodeBridgeOffset() const;
+ void SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset);
+
+ const void* GetJniDlsymLookup() const;
+ uint32_t GetJniDlsymLookupOffset() const;
+ void SetJniDlsymLookupOffset(uint32_t offset);
+
const void* GetPortableResolutionTrampoline() const;
uint32_t GetPortableResolutionTrampolineOffset() const;
void SetPortableResolutionTrampolineOffset(uint32_t offset);
+ const void* GetPortableToInterpreterBridge() const;
+ uint32_t GetPortableToInterpreterBridgeOffset() const;
+ void SetPortableToInterpreterBridgeOffset(uint32_t offset);
+
const void* GetQuickResolutionTrampoline() const;
uint32_t GetQuickResolutionTrampolineOffset() const;
void SetQuickResolutionTrampolineOffset(uint32_t offset);
+ const void* GetQuickToInterpreterBridge() const;
+ uint32_t GetQuickToInterpreterBridgeOffset() const;
+ void SetQuickToInterpreterBridgeOffset(uint32_t offset);
+
InstructionSet GetInstructionSet() const;
uint32_t GetImageFileLocationOatChecksum() const;
uint32_t GetImageFileLocationOatDataBegin() const;
@@ -74,10 +88,13 @@ class PACKED(4) OatHeader {
InstructionSet instruction_set_;
uint32_t dex_file_count_;
uint32_t executable_offset_;
- uint32_t interpreter_to_interpreter_entry_offset_;
- uint32_t interpreter_to_quick_entry_offset_;
+ uint32_t interpreter_to_interpreter_bridge_offset_;
+ uint32_t interpreter_to_compiled_code_bridge_offset_;
+ uint32_t jni_dlsym_lookup_offset_;
uint32_t portable_resolution_trampoline_offset_;
+ uint32_t portable_to_interpreter_bridge_offset_;
uint32_t quick_resolution_trampoline_offset_;
+ uint32_t quick_to_interpreter_bridge_offset_;
uint32_t image_file_location_oat_checksum_;
uint32_t image_file_location_oat_data_begin_;
diff --git a/runtime/oat_test.cc b/runtime/oat_test.cc
index 5d0dca9..68595c8 100644
--- a/runtime/oat_test.cc
+++ b/runtime/oat_test.cc
@@ -141,7 +141,7 @@ TEST_F(OatTest, WriteRead) {
TEST_F(OatTest, OatHeaderSizeCheck) {
// If this test is failing and you have to update these constants,
// it is time to update OatHeader::kOatVersion
- EXPECT_EQ(52U, sizeof(OatHeader));
+ EXPECT_EQ(64U, sizeof(OatHeader));
EXPECT_EQ(28U, sizeof(OatMethodOffsets));
}
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index fa7763e..3639a80 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -411,6 +411,10 @@ class MethodHelper {
shorty_ = NULL;
}
+ const mirror::AbstractMethod* GetMethod() const {
+ return method_;
+ }
+
const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
diff --git a/runtime/stack.cc b/runtime/stack.cc
index a74bcdb..7f3f40c 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -308,7 +308,7 @@ void StackVisitor::WalkStack(bool include_transitions) {
if (UNLIKELY(exit_stubs_installed)) {
// While profiling, the return pc is restored from the side stack, except when walking
// the stack for an exception where the side stack will be unwound in VisitFrame.
- if (GetInstrumentationExitPc() == return_pc) {
+ if (GetQuickInstrumentationExitPc() == return_pc) {
instrumentation::InstrumentationStackFrame instrumentation_frame =
GetInstrumentationStackFrame(instrumentation_stack_depth);
instrumentation_stack_depth++;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 97a1410..c79caa2 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -86,23 +86,25 @@ static void UnimplementedEntryPoint() {
}
#endif
-void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints);
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints);
-void Thread::InitFunctionPointers() {
+void Thread::InitTlsEntryPoints() {
#if !defined(__APPLE__) // The Mac GCC is too old to accept this code.
// Insert a placeholder so we can easily tell if we call an unimplemented entry point.
- uintptr_t* begin = reinterpret_cast<uintptr_t*>(&quick_entrypoints_);
+ uintptr_t* begin = reinterpret_cast<uintptr_t*>(&interpreter_entrypoints_);
uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(quick_entrypoints_));
for (uintptr_t* it = begin; it != end; ++it) {
*it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
}
- begin = reinterpret_cast<uintptr_t*>(&portable_entrypoints_);
+ begin = reinterpret_cast<uintptr_t*>(&interpreter_entrypoints_);
end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(portable_entrypoints_));
for (uintptr_t* it = begin; it != end; ++it) {
*it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
}
#endif
- InitEntryPoints(&quick_entrypoints_, &portable_entrypoints_);
+ InitEntryPoints(&interpreter_entrypoints_, &jni_entrypoints_, &portable_entrypoints_,
+ &quick_entrypoints_);
}
void Thread::SetDeoptimizationShadowFrame(ShadowFrame* sf) {
@@ -292,7 +294,7 @@ void Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) {
CHECK(Thread::Current() == NULL);
SetUpAlternateSignalStack();
InitCpu();
- InitFunctionPointers();
+ InitTlsEntryPoints();
InitCardTable();
InitTid();
// Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this
@@ -1589,22 +1591,29 @@ struct EntryPointInfo {
uint32_t offset;
const char* name;
};
-#define QUICK_ENTRY_POINT_INFO(x) { QUICK_ENTRYPOINT_OFFSET(x), #x }
-#define PORTABLE_ENTRY_POINT_INFO(x) { PORTABLE_ENTRYPOINT_OFFSET(x), #x }
+#define INTERPRETER_ENTRY_POINT_INFO(x) { INTERPRETER_ENTRYPOINT_OFFSET(x).Uint32Value(), #x }
+#define JNI_ENTRY_POINT_INFO(x) { JNI_ENTRYPOINT_OFFSET(x).Uint32Value(), #x }
+#define PORTABLE_ENTRY_POINT_INFO(x) { PORTABLE_ENTRYPOINT_OFFSET(x).Uint32Value(), #x }
+#define QUICK_ENTRY_POINT_INFO(x) { QUICK_ENTRYPOINT_OFFSET(x).Uint32Value(), #x }
static const EntryPointInfo gThreadEntryPointInfo[] = {
- QUICK_ENTRY_POINT_INFO(pAllocArrayFromCode),
- QUICK_ENTRY_POINT_INFO(pAllocArrayFromCodeWithAccessCheck),
- QUICK_ENTRY_POINT_INFO(pAllocObjectFromCode),
- QUICK_ENTRY_POINT_INFO(pAllocObjectFromCodeWithAccessCheck),
- QUICK_ENTRY_POINT_INFO(pCheckAndAllocArrayFromCode),
- QUICK_ENTRY_POINT_INFO(pCheckAndAllocArrayFromCodeWithAccessCheck),
- QUICK_ENTRY_POINT_INFO(pInstanceofNonTrivialFromCode),
- QUICK_ENTRY_POINT_INFO(pCanPutArrayElementFromCode),
- QUICK_ENTRY_POINT_INFO(pCheckCastFromCode),
+ INTERPRETER_ENTRY_POINT_INFO(pInterpreterToInterpreterBridge),
+ INTERPRETER_ENTRY_POINT_INFO(pInterpreterToCompiledCodeBridge),
+ JNI_ENTRY_POINT_INFO(pDlsymLookup),
+ PORTABLE_ENTRY_POINT_INFO(pPortableResolutionTrampoline),
+ PORTABLE_ENTRY_POINT_INFO(pPortableToInterpreterBridge),
+ QUICK_ENTRY_POINT_INFO(pAllocArray),
+ QUICK_ENTRY_POINT_INFO(pAllocArrayWithAccessCheck),
+ QUICK_ENTRY_POINT_INFO(pAllocObject),
+ QUICK_ENTRY_POINT_INFO(pAllocObjectWithAccessCheck),
+ QUICK_ENTRY_POINT_INFO(pCheckAndAllocArray),
+ QUICK_ENTRY_POINT_INFO(pCheckAndAllocArrayWithAccessCheck),
+ QUICK_ENTRY_POINT_INFO(pInstanceofNonTrivial),
+ QUICK_ENTRY_POINT_INFO(pCanPutArrayElement),
+ QUICK_ENTRY_POINT_INFO(pCheckCast),
QUICK_ENTRY_POINT_INFO(pInitializeStaticStorage),
- QUICK_ENTRY_POINT_INFO(pInitializeTypeAndVerifyAccessFromCode),
- QUICK_ENTRY_POINT_INFO(pInitializeTypeFromCode),
- QUICK_ENTRY_POINT_INFO(pResolveStringFromCode),
+ QUICK_ENTRY_POINT_INFO(pInitializeTypeAndVerifyAccess),
+ QUICK_ENTRY_POINT_INFO(pInitializeType),
+ QUICK_ENTRY_POINT_INFO(pResolveString),
QUICK_ENTRY_POINT_INFO(pSet32Instance),
QUICK_ENTRY_POINT_INFO(pSet32Static),
QUICK_ENTRY_POINT_INFO(pSet64Instance),
@@ -1617,15 +1626,15 @@ static const EntryPointInfo gThreadEntryPointInfo[] = {
QUICK_ENTRY_POINT_INFO(pGet64Static),
QUICK_ENTRY_POINT_INFO(pGetObjInstance),
QUICK_ENTRY_POINT_INFO(pGetObjStatic),
- QUICK_ENTRY_POINT_INFO(pHandleFillArrayDataFromCode),
+ QUICK_ENTRY_POINT_INFO(pHandleFillArrayData),
QUICK_ENTRY_POINT_INFO(pJniMethodStart),
QUICK_ENTRY_POINT_INFO(pJniMethodStartSynchronized),
QUICK_ENTRY_POINT_INFO(pJniMethodEnd),
QUICK_ENTRY_POINT_INFO(pJniMethodEndSynchronized),
QUICK_ENTRY_POINT_INFO(pJniMethodEndWithReference),
QUICK_ENTRY_POINT_INFO(pJniMethodEndWithReferenceSynchronized),
- QUICK_ENTRY_POINT_INFO(pLockObjectFromCode),
- QUICK_ENTRY_POINT_INFO(pUnlockObjectFromCode),
+ QUICK_ENTRY_POINT_INFO(pLockObject),
+ QUICK_ENTRY_POINT_INFO(pUnlockObject),
QUICK_ENTRY_POINT_INFO(pCmpgDouble),
QUICK_ENTRY_POINT_INFO(pCmpgFloat),
QUICK_ENTRY_POINT_INFO(pCmplDouble),
@@ -1646,28 +1655,26 @@ static const EntryPointInfo gThreadEntryPointInfo[] = {
QUICK_ENTRY_POINT_INFO(pShlLong),
QUICK_ENTRY_POINT_INFO(pShrLong),
QUICK_ENTRY_POINT_INFO(pUshrLong),
- QUICK_ENTRY_POINT_INFO(pInterpreterToInterpreterEntry),
- QUICK_ENTRY_POINT_INFO(pInterpreterToQuickEntry),
QUICK_ENTRY_POINT_INFO(pIndexOf),
QUICK_ENTRY_POINT_INFO(pMemcmp16),
QUICK_ENTRY_POINT_INFO(pStringCompareTo),
QUICK_ENTRY_POINT_INFO(pMemcpy),
- QUICK_ENTRY_POINT_INFO(pQuickResolutionTrampolineFromCode),
+ QUICK_ENTRY_POINT_INFO(pQuickResolutionTrampoline),
+ QUICK_ENTRY_POINT_INFO(pQuickToInterpreterBridge),
QUICK_ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck),
QUICK_ENTRY_POINT_INFO(pInvokeInterfaceTrampoline),
QUICK_ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck),
QUICK_ENTRY_POINT_INFO(pInvokeStaticTrampolineWithAccessCheck),
QUICK_ENTRY_POINT_INFO(pInvokeSuperTrampolineWithAccessCheck),
QUICK_ENTRY_POINT_INFO(pInvokeVirtualTrampolineWithAccessCheck),
- QUICK_ENTRY_POINT_INFO(pCheckSuspendFromCode),
- QUICK_ENTRY_POINT_INFO(pTestSuspendFromCode),
+ QUICK_ENTRY_POINT_INFO(pCheckSuspend),
+ QUICK_ENTRY_POINT_INFO(pTestSuspend),
QUICK_ENTRY_POINT_INFO(pDeliverException),
- QUICK_ENTRY_POINT_INFO(pThrowArrayBoundsFromCode),
- QUICK_ENTRY_POINT_INFO(pThrowDivZeroFromCode),
- QUICK_ENTRY_POINT_INFO(pThrowNoSuchMethodFromCode),
- QUICK_ENTRY_POINT_INFO(pThrowNullPointerFromCode),
- QUICK_ENTRY_POINT_INFO(pThrowStackOverflowFromCode),
- PORTABLE_ENTRY_POINT_INFO(pPortableResolutionTrampolineFromCode),
+ QUICK_ENTRY_POINT_INFO(pThrowArrayBounds),
+ QUICK_ENTRY_POINT_INFO(pThrowDivZero),
+ QUICK_ENTRY_POINT_INFO(pThrowNoSuchMethod),
+ QUICK_ENTRY_POINT_INFO(pThrowNullPointer),
+ QUICK_ENTRY_POINT_INFO(pThrowStackOverflow),
};
#undef QUICK_ENTRY_POINT_INFO
@@ -1695,8 +1702,9 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset, size_t size_of_
size_t entry_point_count = arraysize(gThreadEntryPointInfo);
CHECK_EQ(entry_point_count * size_of_pointers,
- sizeof(QuickEntryPoints) + sizeof(PortableEntryPoints));
- uint32_t expected_offset = OFFSETOF_MEMBER(Thread, quick_entrypoints_);
+ sizeof(InterpreterEntryPoints) + sizeof(JniEntryPoints) + sizeof(PortableEntryPoints) +
+ sizeof(QuickEntryPoints));
+ uint32_t expected_offset = OFFSETOF_MEMBER(Thread, interpreter_entrypoints_);
for (size_t i = 0; i < entry_point_count; ++i) {
CHECK_EQ(gThreadEntryPointInfo[i].offset, expected_offset) << gThreadEntryPointInfo[i].name;
expected_offset += size_of_pointers;
@@ -1739,7 +1747,7 @@ class CatchBlockStackVisitor : public StackVisitor {
return false; // End stack walk.
} else {
if (UNLIKELY(method_tracing_active_ &&
- GetInstrumentationExitPc() == GetReturnPc())) {
+ GetQuickInstrumentationExitPc() == GetReturnPc())) {
// Keep count of the number of unwinds during instrumentation.
instrumentation_frames_to_pop_++;
}
diff --git a/runtime/thread.h b/runtime/thread.h
index ff0fe22..8b6771e 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -26,6 +26,8 @@
#include <string>
#include "base/macros.h"
+#include "entrypoints/interpreter/interpreter_entrypoints.h"
+#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "globals.h"
@@ -43,17 +45,17 @@
namespace art {
namespace mirror {
-class AbstractMethod;
-class Array;
-class Class;
-class ClassLoader;
-class Object;
-template<class T> class ObjectArray;
-template<class T> class PrimitiveArray;
-typedef PrimitiveArray<int32_t> IntArray;
-class StackTraceElement;
-class StaticStorageBase;
-class Throwable;
+ class AbstractMethod;
+ class Array;
+ class Class;
+ class ClassLoader;
+ class Object;
+ template<class T> class ObjectArray;
+ template<class T> class PrimitiveArray;
+ typedef PrimitiveArray<int32_t> IntArray;
+ class StackTraceElement;
+ class StaticStorageBase;
+ class Throwable;
} // namespace mirror
class BaseMutex;
class ClassLinker;
@@ -614,7 +616,7 @@ class PACKED(4) Thread {
void Init(ThreadList*, JavaVMExt*) EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
void InitCardTable();
void InitCpu();
- void InitFunctionPointers();
+ void InitTlsEntryPoints();
void InitTid();
void InitPthreadKeySelf();
void InitStackHwm();
@@ -776,8 +778,10 @@ class PACKED(4) Thread {
public:
// Entrypoint function pointers
// TODO: move this near the top, since changing its offset requires all oats to be recompiled!
- QuickEntryPoints quick_entrypoints_;
+ InterpreterEntryPoints interpreter_entrypoints_;
+ JniEntryPoints jni_entrypoints_;
PortableEntryPoints portable_entrypoints_;
+ QuickEntryPoints quick_entrypoints_;
private:
// How many times has our pthread key's destructor been called?