diff options
author | 2019-07-04 10:00:12 +0000 | |
---|---|---|
committer | 2019-07-05 00:20:19 +0000 | |
commit | e81f10a3f672a8bcc421cab812e6435749181566 (patch) | |
tree | 076df5318e4bfdb6148fd6bb0faf5ea8de1d3336 | |
parent | 9690542a9ed7740110459d3167708e6edc1a2686 (diff) |
Revert "Remove ShadowFrame::dex_pc_ (but keep dex_pc_ptr_)"
This reverts commit 50bc8fb89c79874e731f245abda3b9e48a541cfe.
Reason for revert: Performance regression
Change-Id: Ib39ceb9e1f2753c518dd24fd193a824211fd5795
-rw-r--r-- | oatdump/oatdump_app_test.cc | 16 | ||||
-rw-r--r-- | oatdump/oatdump_image_test.cc | 8 | ||||
-rw-r--r-- | oatdump/oatdump_test.cc | 28 | ||||
-rw-r--r-- | oatdump/oatdump_test.h | 6 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl-inl.h | 1 | ||||
-rw-r--r-- | runtime/interpreter/mterp/arm/main.S | 31 | ||||
-rw-r--r-- | runtime/interpreter/mterp/arm64/main.S | 23 | ||||
-rw-r--r-- | runtime/interpreter/mterp/mterp.cc | 10 | ||||
-rw-r--r-- | runtime/interpreter/mterp/mterp.h | 4 | ||||
-rw-r--r-- | runtime/interpreter/mterp/x86/main.S | 21 | ||||
-rw-r--r-- | runtime/interpreter/mterp/x86_64/main.S | 20 | ||||
-rw-r--r-- | runtime/interpreter/shadow_frame.h | 24 | ||||
-rw-r--r-- | tools/cpp-define-generator/shadow_frame.def | 4 |
13 files changed, 142 insertions, 54 deletions
diff --git a/oatdump/oatdump_app_test.cc b/oatdump/oatdump_app_test.cc index bbd0e3d34c..4490647d2c 100644 --- a/oatdump/oatdump_app_test.cc +++ b/oatdump/oatdump_app_test.cc @@ -19,27 +19,27 @@ namespace art { TEST_F(OatDumpTest, TestAppWithBootImage) { - ASSERT_TRUE(GenerateAppOdexFile(kDynamicLinking, {"--runtime-arg", "-Xmx64M"})); - ASSERT_TRUE(Exec(kDynamicLinking, kModeOatWithBootImage, {}, kListAndCode)); + ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M"})); + ASSERT_TRUE(Exec(kDynamic, kModeOatWithBootImage, {}, kListAndCode)); } TEST_F(OatDumpTest, TestAppWithBootImageStatic) { TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); - ASSERT_TRUE(GenerateAppOdexFile(kStaticLinking, {"--runtime-arg", "-Xmx64M"})); - ASSERT_TRUE(Exec(kStaticLinking, kModeOatWithBootImage, {}, kListAndCode)); + ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M"})); + ASSERT_TRUE(Exec(kStatic, kModeOatWithBootImage, {}, kListAndCode)); } TEST_F(OatDumpTest, TestAppImageWithBootImage) { TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS(); // GC bug, b/126305867 const std::string app_image_arg = "--app-image-file=" + GetAppImageName(); - ASSERT_TRUE(GenerateAppOdexFile(kDynamicLinking, {"--runtime-arg", "-Xmx64M", app_image_arg})); - ASSERT_TRUE(Exec(kDynamicLinking, kModeAppImage, {}, kListAndCode)); + ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M", app_image_arg})); + ASSERT_TRUE(Exec(kDynamic, kModeAppImage, {}, kListAndCode)); } TEST_F(OatDumpTest, TestAppImageWithBootImageStatic) { TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS(); // GC bug, b/126305867 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); const std::string app_image_arg = "--app-image-file=" + GetAppImageName(); - ASSERT_TRUE(GenerateAppOdexFile(kStaticLinking, {"--runtime-arg", "-Xmx64M", app_image_arg})); - ASSERT_TRUE(Exec(kStaticLinking, kModeAppImage, {}, kListAndCode)); + ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M", app_image_arg})); + ASSERT_TRUE(Exec(kStatic, kModeAppImage, {}, kListAndCode)); } } // namespace art diff --git a/oatdump/oatdump_image_test.cc b/oatdump/oatdump_image_test.cc index 6f6b83bc53..0a076f065e 100644 --- a/oatdump/oatdump_image_test.cc +++ b/oatdump/oatdump_image_test.cc @@ -28,25 +28,25 @@ namespace art { TEST_F(OatDumpTest, TestImage) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeArt, {}, kListAndCode)); + ASSERT_TRUE(Exec(kDynamic, kModeArt, {}, kListAndCode)); } TEST_F(OatDumpTest, TestImageStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeArt, {}, kListAndCode)); + ASSERT_TRUE(Exec(kStatic, kModeArt, {}, kListAndCode)); } TEST_F(OatDumpTest, TestOatImage) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeCoreOat, {}, kListAndCode)); + ASSERT_TRUE(Exec(kDynamic, kModeCoreOat, {}, kListAndCode)); } TEST_F(OatDumpTest, TestOatImageStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeCoreOat, {}, kListAndCode)); + ASSERT_TRUE(Exec(kStatic, kModeCoreOat, {}, kListAndCode)); } } // namespace art diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc index 87f9ac69ca..506fde776b 100644 --- a/oatdump/oatdump_test.cc +++ b/oatdump/oatdump_test.cc @@ -30,61 +30,61 @@ namespace art { TEST_F(OatDumpTest, TestNoDumpVmap) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeArt, {"--no-dump:vmap"}, kListAndCode)); + ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-dump:vmap"}, kListAndCode)); } TEST_F(OatDumpTest, TestNoDumpVmapStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeArt, {"--no-dump:vmap"}, kListAndCode)); + ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-dump:vmap"}, kListAndCode)); } TEST_F(OatDumpTest, TestNoDisassemble) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeArt, {"--no-disassemble"}, kListAndCode)); + ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-disassemble"}, kListAndCode)); } TEST_F(OatDumpTest, TestNoDisassembleStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeArt, {"--no-disassemble"}, kListAndCode)); + ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-disassemble"}, kListAndCode)); } TEST_F(OatDumpTest, TestListClasses) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeArt, {"--list-classes"}, kListOnly)); + ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-classes"}, kListOnly)); } TEST_F(OatDumpTest, TestListClassesStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeArt, {"--list-classes"}, kListOnly)); + ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-classes"}, kListOnly)); } TEST_F(OatDumpTest, TestListMethods) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeArt, {"--list-methods"}, kListOnly)); + ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-methods"}, kListOnly)); } TEST_F(OatDumpTest, TestListMethodsStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeArt, {"--list-methods"}, kListOnly)); + ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-methods"}, kListOnly)); } TEST_F(OatDumpTest, TestSymbolize) { TEST_DISABLED_FOR_ARM_AND_MIPS(); std::string error_msg; - ASSERT_TRUE(Exec(kDynamicLinking, kModeSymbolize, {}, kListOnly)); + ASSERT_TRUE(Exec(kDynamic, kModeSymbolize, {}, kListOnly)); } TEST_F(OatDumpTest, TestSymbolizeStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(Exec(kStaticLinking, kModeSymbolize, {}, kListOnly)); + ASSERT_TRUE(Exec(kStatic, kModeSymbolize, {}, kListOnly)); } TEST_F(OatDumpTest, TestExportDex) { @@ -92,8 +92,8 @@ TEST_F(OatDumpTest, TestExportDex) { // Test is failing on target, b/77469384. TEST_DISABLED_FOR_TARGET(); std::string error_msg; - ASSERT_TRUE(GenerateAppOdexFile(kDynamicLinking, {"--runtime-arg", "-Xmx64M"})); - ASSERT_TRUE(Exec(kDynamicLinking, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly)); + ASSERT_TRUE(GenerateAppOdexFile(kDynamic, {"--runtime-arg", "-Xmx64M"})); + ASSERT_TRUE(Exec(kDynamic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly)); const std::string dex_location = tmp_dir_+ "/" + android::base::Basename(GetTestDexFileName(GetAppBaseName().c_str())) + "_export.dex"; @@ -109,8 +109,8 @@ TEST_F(OatDumpTest, TestExportDexStatic) { TEST_DISABLED_FOR_ARM_AND_MIPS(); TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); std::string error_msg; - ASSERT_TRUE(GenerateAppOdexFile(kStaticLinking, {"--runtime-arg", "-Xmx64M"})); - ASSERT_TRUE(Exec(kStaticLinking, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly)); + ASSERT_TRUE(GenerateAppOdexFile(kStatic, {"--runtime-arg", "-Xmx64M"})); + ASSERT_TRUE(Exec(kStatic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly)); } } // namespace art diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h index 997321f1b3..359b060f1f 100644 --- a/oatdump/oatdump_test.h +++ b/oatdump/oatdump_test.h @@ -66,8 +66,8 @@ class OatDumpTest : public CommonRuntimeTest { // Linking flavor. enum Flavor { - kDynamicLinking, // oatdump(d), dex2oat(d) - kStaticLinking, // oatdump(d)s, dex2oat(d)s + kDynamic, // oatdump(d), dex2oat(d) + kStatic, // oatdump(d)s, dex2oat(d)s }; // Returns path to the oatdump/dex2oat/dexdump binary. @@ -83,7 +83,7 @@ class OatDumpTest : public CommonRuntimeTest { } std::string GetExecutableFilePath(Flavor flavor, const char* name) { - return GetExecutableFilePath(name, kIsDebugBuild, flavor == kStaticLinking); + return GetExecutableFilePath(name, kIsDebugBuild, flavor == kStatic); } enum Mode { diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h index d22771dea8..fc3005d72c 100644 --- a/runtime/interpreter/interpreter_switch_impl-inl.h +++ b/runtime/interpreter/interpreter_switch_impl-inl.h @@ -1917,7 +1917,6 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) self->VerifyStack(); uint32_t dex_pc = shadow_frame.GetDexPC(); - DCHECK_LT(dex_pc, shadow_frame.GetMethod()->DexInstructionData().InsnsSizeInCodeUnits()); const auto* const instrumentation = Runtime::Current()->GetInstrumentation(); const uint16_t* const insns = accessor.Insns(); const Instruction* next = Instruction::At(insns + dex_pc); diff --git a/runtime/interpreter/mterp/arm/main.S b/runtime/interpreter/mterp/arm/main.S index 95bc864ad9..12b3dab003 100644 --- a/runtime/interpreter/mterp/arm/main.S +++ b/runtime/interpreter/mterp/arm/main.S @@ -109,10 +109,12 @@ unspecified registers or condition codes. */ #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_DEX_INSTRUCTIONS OFF_FP(SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET) #define OFF_FP_SHADOWFRAME OFF_FP(0) /* @@ -120,11 +122,25 @@ unspecified registers or condition codes. * be done *before* something throws. * * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. */ .macro EXPORT_PC str rPC, [rFP, #OFF_FP_DEX_PC_PTR] .endm +.macro EXPORT_DEX_PC tmp + ldr \tmp, [rFP, #OFF_FP_DEX_INSTRUCTIONS] + str rPC, [rFP, #OFF_FP_DEX_PC_PTR] + sub \tmp, rPC, \tmp + asr \tmp, #1 + str \tmp, [rFP, #OFF_FP_DEX_PC] +.endm + /* * Fetch the next instruction from rPC into rINST. Does not advance rPC. */ @@ -382,13 +398,18 @@ ENTRY ExecuteMterpImpl /* Remember the return register */ str r3, [r2, #SHADOWFRAME_RESULT_REGISTER_OFFSET] + /* Remember the dex instruction pointer */ + str r1, [r2, #SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET] + /* set up "named" registers */ mov rSELF, r0 ldr r0, [r2, #SHADOWFRAME_NUMBER_OF_VREGS_OFFSET] - add rFP, r2, #SHADOWFRAME_VREGS_OFFSET @ pointer to vregs. - VREG_INDEX_TO_ADDR rREFS, r0 @ pointer to reference array in shadow frame - ldr rPC, [r2, #SHADOWFRAME_DEX_PC_PTR_OFFSET] @ pointer to current dex instruction. + add rFP, r2, #SHADOWFRAME_VREGS_OFFSET @ point to vregs. + VREG_INDEX_TO_ADDR rREFS, r0 @ point to reference array in shadow frame + ldr r0, [r2, #SHADOWFRAME_DEX_PC_OFFSET] @ Get starting dex_pc. + add rPC, r1, r0, lsl #1 @ Create direct pointer to 1st dex opcode CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) + EXPORT_PC /* Starting ibase */ ldr rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET] @@ -530,8 +551,10 @@ MterpException: bl MterpHandleException @ (self, shadow_frame) cmp r0, #0 beq MterpExceptionReturn @ no local catch, back to caller. + ldr r0, [rFP, #OFF_FP_DEX_INSTRUCTIONS] + ldr r1, [rFP, #OFF_FP_DEX_PC] ldr rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET] - ldr rPC, [rFP, #OFF_FP_DEX_PC_PTR] @ reload dex pc pointer. + add rPC, r0, r1, lsl #1 @ generate new dex_pc_ptr /* Do we need to switch interpreters? */ ldr r0, [rSELF, #THREAD_USE_MTERP_OFFSET] cmp r0, #0 diff --git a/runtime/interpreter/mterp/arm64/main.S b/runtime/interpreter/mterp/arm64/main.S index e16b51cb08..fd745f1bd1 100644 --- a/runtime/interpreter/mterp/arm64/main.S +++ b/runtime/interpreter/mterp/arm64/main.S @@ -115,10 +115,12 @@ codes. */ #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_DEX_INSTRUCTIONS OFF_FP(SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET) #define OFF_FP_SHADOWFRAME OFF_FP(0) /* @@ -126,6 +128,12 @@ codes. * be done *before* something throws. * * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. */ .macro EXPORT_PC str xPC, [xFP, #OFF_FP_DEX_PC_PTR] @@ -403,13 +411,18 @@ ENTRY ExecuteMterpImpl /* Remember the return register */ str x3, [x2, #SHADOWFRAME_RESULT_REGISTER_OFFSET] + /* Remember the dex instruction pointer */ + str x1, [x2, #SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET] + /* set up "named" registers */ mov xSELF, x0 ldr w0, [x2, #SHADOWFRAME_NUMBER_OF_VREGS_OFFSET] - add xFP, x2, #SHADOWFRAME_VREGS_OFFSET // pointer to vregs. - add xREFS, xFP, w0, uxtw #2 // pointer to reference array in shadow frame - ldr xPC, [x2, #SHADOWFRAME_DEX_PC_PTR_OFFSET] // pointer to current dex instruction. + add xFP, x2, #SHADOWFRAME_VREGS_OFFSET // point to vregs. + add xREFS, xFP, w0, uxtw #2 // point to reference array in shadow frame + ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc. + add xPC, x1, w0, uxtw #1 // Create direct pointer to 1st dex opcode CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) + EXPORT_PC /* Starting ibase */ ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] @@ -548,8 +561,10 @@ MterpException: add x1, xFP, #OFF_FP_SHADOWFRAME bl MterpHandleException // (self, shadow_frame) cbz w0, MterpExceptionReturn // no local catch, back to caller. + ldr x0, [xFP, #OFF_FP_DEX_INSTRUCTIONS] + ldr w1, [xFP, #OFF_FP_DEX_PC] ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] - ldr xPC, [xFP, #OFF_FP_DEX_PC_PTR] // reload dex pc pointer. + add xPC, x0, x1, lsl #1 // generate new dex_pc_ptr /* Do we need to switch interpreters? */ ldr w0, [xSELF, #THREAD_USE_MTERP_OFFSET] cbz w0, MterpFallback diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc index 57ebface31..80ebf21b40 100644 --- a/runtime/interpreter/mterp/mterp.cc +++ b/runtime/interpreter/mterp/mterp.cc @@ -554,10 +554,14 @@ extern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame, uint16 } DCHECK(!Runtime::Current()->IsActiveTransaction()); const Instruction* inst = Instruction::At(dex_pc_ptr); - DCHECK_EQ(self->IsExceptionPending(), inst->Opcode() == Instruction::MOVE_EXCEPTION); - uint32_t dex_pc = dex_pc_ptr - shadow_frame->GetDexInstructions(); - DCHECK_LT(dex_pc, shadow_frame->GetMethod()->DexInstructionData().InsnsSizeInCodeUnits()); + uint16_t inst_data = inst->Fetch16(0); + if (inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION) { + self->AssertPendingException(); + } else { + self->AssertNoPendingException(); + } if (kTraceExecutionEnabled) { + uint32_t dex_pc = dex_pc_ptr - shadow_frame->GetDexInstructions(); TraceExecution(*shadow_frame, inst, dex_pc); } if (kTestExportPC) { diff --git a/runtime/interpreter/mterp/mterp.h b/runtime/interpreter/mterp/mterp.h index d8fe358885..af52758bbc 100644 --- a/runtime/interpreter/mterp/mterp.h +++ b/runtime/interpreter/mterp/mterp.h @@ -40,8 +40,8 @@ bool CanUseMterp(); // handler for a recent opcode failed to export the Dalvik PC prior to a possible exit from // the mterp environment. constexpr uintptr_t kExportPCPoison = 0xdead00ff; -// Set true to enable poison testing of ExportPC. -constexpr bool kTestExportPC = true; +// Set true to enable poison testing of ExportPC. Uses Alt interpreter. +constexpr bool kTestExportPC = false; constexpr size_t kMterpHandlerSize = 128; diff --git a/runtime/interpreter/mterp/x86/main.S b/runtime/interpreter/mterp/x86/main.S index 03cbf49a06..8df75d2f66 100644 --- a/runtime/interpreter/mterp/x86/main.S +++ b/runtime/interpreter/mterp/x86/main.S @@ -131,10 +131,12 @@ unspecified registers or condition codes. */ #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_DEX_INSTRUCTIONS OFF_FP(SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET) #define OFF_FP_COUNTDOWN_OFFSET OFF_FP(SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET) #define OFF_FP_SHADOWFRAME OFF_FP(0) @@ -180,6 +182,12 @@ unspecified registers or condition codes. * be done *before* something throws. * * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. */ .macro EXPORT_PC movl rPC, OFF_FP_DEX_PC_PTR(rFP) @@ -385,12 +393,18 @@ ENTRY ExecuteMterpImpl movl IN_ARG3(%esp), %eax movl %eax, SHADOWFRAME_RESULT_REGISTER_OFFSET(%edx) + /* Remember the code_item */ + movl IN_ARG1(%esp), %ecx + movl %ecx, SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET(%edx) + /* set up "named" registers */ movl SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(%edx), %eax leal SHADOWFRAME_VREGS_OFFSET(%edx), rFP leal (rFP, %eax, 4), rREFS - movl SHADOWFRAME_DEX_PC_PTR_OFFSET(%edx), rPC + movl SHADOWFRAME_DEX_PC_OFFSET(%edx), %eax + lea (%ecx, %eax, 2), rPC CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) + EXPORT_PC /* Set up for backwards branches & osr profiling */ movl OFF_FP_METHOD(rFP), %eax @@ -556,7 +570,10 @@ MterpException: call SYMBOL(MterpHandleException) testb %al, %al jz MterpExceptionReturn - movl OFF_FP_DEX_PC_PTR(rFP), rPC + movl OFF_FP_DEX_INSTRUCTIONS(rFP), %eax + movl OFF_FP_DEX_PC(rFP), %ecx + lea (%eax, %ecx, 2), rPC + movl rPC, OFF_FP_DEX_PC_PTR(rFP) /* Do we need to switch interpreters? */ movl rSELF, %eax cmpb LITERAL(0), THREAD_USE_MTERP_OFFSET(%eax) diff --git a/runtime/interpreter/mterp/x86_64/main.S b/runtime/interpreter/mterp/x86_64/main.S index 11e4d616d6..5f1fd2dfbe 100644 --- a/runtime/interpreter/mterp/x86_64/main.S +++ b/runtime/interpreter/mterp/x86_64/main.S @@ -127,10 +127,12 @@ unspecified registers or condition codes. */ #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_DEX_INSTRUCTIONS OFF_FP(SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET) #define OFF_FP_COUNTDOWN_OFFSET OFF_FP(SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET) #define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET) @@ -181,6 +183,12 @@ unspecified registers or condition codes. * be done *before* something throws. * * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. */ .macro EXPORT_PC movq rPC, OFF_FP_DEX_PC_PTR(rFP) @@ -372,12 +380,17 @@ ENTRY ExecuteMterpImpl /* Remember the return register */ movq IN_ARG3, SHADOWFRAME_RESULT_REGISTER_OFFSET(IN_ARG2) + /* Remember the code_item */ + movq IN_ARG1, SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET(IN_ARG2) + /* set up "named" registers */ movl SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(IN_ARG2), %eax leaq SHADOWFRAME_VREGS_OFFSET(IN_ARG2), rFP leaq (rFP, %rax, 4), rREFS - movq SHADOWFRAME_DEX_PC_PTR_OFFSET(IN_ARG2), rPC + movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax + leaq (IN_ARG1, %rax, 2), rPC CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) + EXPORT_PC /* Starting ibase */ movq IN_ARG0, rSELF @@ -523,7 +536,10 @@ MterpException: call SYMBOL(MterpHandleException) testb %al, %al jz MterpExceptionReturn - movq OFF_FP_DEX_PC_PTR(rFP), rPC + movq OFF_FP_DEX_INSTRUCTIONS(rFP), %rax + mov OFF_FP_DEX_PC(rFP), %ecx + leaq (%rax, %rcx, 2), rPC + movq rPC, OFF_FP_DEX_PC_PTR(rFP) /* Do we need to switch interpreters? */ movq rSELF, %rax cmpb LITERAL(0), THREAD_USE_MTERP_OFFSET(%rax) diff --git a/runtime/interpreter/shadow_frame.h b/runtime/interpreter/shadow_frame.h index b0fa4a3be1..8cb2b33a07 100644 --- a/runtime/interpreter/shadow_frame.h +++ b/runtime/interpreter/shadow_frame.h @@ -21,10 +21,8 @@ #include <cstring> #include <string> -#include "art_method.h" #include "base/locks.h" #include "base/macros.h" -#include "dex/code_item_accessors-inl.h" #include "lock_count_data.h" #include "read_barrier.h" #include "stack_reference.h" @@ -104,7 +102,7 @@ class ShadowFrame { } uint32_t GetDexPC() const { - return (dex_pc_ptr_ == nullptr) ? dex::kDexNoIndex : (dex_pc_ptr_ - dex_instructions_); + return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_; } int16_t GetCachedHotnessCountdown() const { @@ -124,7 +122,8 @@ class ShadowFrame { } void SetDexPC(uint32_t dex_pc) { - dex_pc_ptr_ = (dex_pc == dex::kDexNoIndex) ? nullptr : (dex_instructions_ + dex_pc); + dex_pc_ = dex_pc; + dex_pc_ptr_ = nullptr; } ShadowFrame* GetLink() const { @@ -281,6 +280,10 @@ class ShadowFrame { return OFFSETOF_MEMBER(ShadowFrame, method_); } + static constexpr size_t DexPCOffset() { + return OFFSETOF_MEMBER(ShadowFrame, dex_pc_); + } + static constexpr size_t NumberOfVRegsOffset() { return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_); } @@ -297,6 +300,10 @@ class ShadowFrame { return OFFSETOF_MEMBER(ShadowFrame, dex_pc_ptr_); } + static constexpr size_t DexInstructionsOffset() { + return OFFSETOF_MEMBER(ShadowFrame, dex_instructions_); + } + static constexpr size_t CachedHotnessCountdownOffset() { return OFFSETOF_MEMBER(ShadowFrame, cached_hotness_countdown_); } @@ -382,9 +389,10 @@ class ShadowFrame { : link_(link), method_(method), result_register_(nullptr), - dex_instructions_(method == nullptr ? nullptr : method->DexInstructionData().Insns()), - dex_pc_ptr_(dex_instructions_ + dex_pc), + dex_pc_ptr_(nullptr), + dex_instructions_(nullptr), number_of_vregs_(num_vregs), + dex_pc_(dex_pc), cached_hotness_countdown_(0), hotness_countdown_(0), frame_flags_(0) { @@ -417,10 +425,12 @@ class ShadowFrame { ShadowFrame* link_; ArtMethod* method_; JValue* result_register_; - const uint16_t* dex_instructions_; // Dex instruction base of the code item. const uint16_t* dex_pc_ptr_; + // Dex instruction base of the code item. + const uint16_t* dex_instructions_; LockCountData lock_count_data_; // This may contain GC roots when lock counting is active. const uint32_t number_of_vregs_; + uint32_t dex_pc_; int16_t cached_hotness_countdown_; int16_t hotness_countdown_; diff --git a/tools/cpp-define-generator/shadow_frame.def b/tools/cpp-define-generator/shadow_frame.def index 5bf3befea0..10a309cbdb 100644 --- a/tools/cpp-define-generator/shadow_frame.def +++ b/tools/cpp-define-generator/shadow_frame.def @@ -20,6 +20,10 @@ ASM_DEFINE(SHADOWFRAME_CACHED_HOTNESS_COUNTDOWN_OFFSET, art::ShadowFrame::CachedHotnessCountdownOffset()) +ASM_DEFINE(SHADOWFRAME_DEX_INSTRUCTIONS_OFFSET, + art::ShadowFrame::DexInstructionsOffset()) +ASM_DEFINE(SHADOWFRAME_DEX_PC_OFFSET, + art::ShadowFrame::DexPCOffset()) ASM_DEFINE(SHADOWFRAME_DEX_PC_PTR_OFFSET, art::ShadowFrame::DexPCPtrOffset()) ASM_DEFINE(SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET, |