diff options
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? |