diff options
author | 2023-05-04 14:24:19 +0100 | |
---|---|---|
committer | 2023-05-04 15:34:48 +0000 | |
commit | 88411fb64e4644874d11649e14c4404e7a6777d9 (patch) | |
tree | a739084266c4b3c196c924710ff4213fc149fc09 | |
parent | be726b5fb9fa19e9731faa6cacd747efbde9d5b9 (diff) |
When fetching the caller of a runtime method, also fetch dex_pc.
This avoids doing twice an expensive stack map decoding when looking for
the dex pc.
Test: test.py
Bug: 280355026
Change-Id: I9c3632d9a2544f5c5dfe2a8fb75d348c6504eb47
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 84 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 7 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 55 |
3 files changed, 76 insertions, 70 deletions
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index e6d0adb1be..aa27df4dc5 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -208,43 +208,62 @@ static inline std::pair<ArtMethod*, uintptr_t> DoGetCalleeSaveMethodOuterCallerA return std::make_pair(outer_method, caller_pc); } -static inline ArtMethod* DoGetCalleeSaveMethodCaller(ArtMethod* outer_method, - uintptr_t caller_pc, - bool do_caller_check) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtMethod* caller = outer_method; - if (outer_method != nullptr) { - const OatQuickMethodHeader* current_code = outer_method->GetOatQuickMethodHeader(caller_pc); - DCHECK(current_code != nullptr); - if (current_code->IsOptimized() && - CodeInfo::HasInlineInfo(current_code->GetOptimizedCodeInfoPtr())) { - uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc); - CodeInfo code_info = CodeInfo::DecodeInlineInfoOnly(current_code); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); - DCHECK(stack_map.IsValid()); - BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); - if (!inline_infos.empty()) { - caller = GetResolvedMethod(outer_method, code_info, inline_infos); - } +static inline ArtMethod* DoGetCalleeSaveMethodCallerAndDexPc(ArtMethod** sp, + CalleeSaveType type, + ArtMethod* outer_method, + uintptr_t caller_pc, + uint32_t* dex_pc, + bool do_caller_check) + REQUIRES_SHARED(Locks::mutator_lock_) { + ArtMethod* caller = outer_method; + if (outer_method != nullptr) { + const OatQuickMethodHeader* current_code = outer_method->GetOatQuickMethodHeader(caller_pc); + DCHECK(current_code != nullptr); + if (current_code->IsOptimized() && + CodeInfo::HasInlineInfo(current_code->GetOptimizedCodeInfoPtr())) { + uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc); + CodeInfo code_info = CodeInfo::DecodeInlineInfoOnly(current_code); + StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); + DCHECK(stack_map.IsValid()); + BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); + if (!inline_infos.empty()) { + caller = GetResolvedMethod(outer_method, code_info, inline_infos); + *dex_pc = inline_infos.back().GetDexPc(); + } else { + *dex_pc = stack_map.GetDexPc(); } + } else { + size_t callee_frame_size = RuntimeCalleeSaveFrame::GetFrameSize(type); + ArtMethod** caller_sp = reinterpret_cast<ArtMethod**>( + reinterpret_cast<uintptr_t>(sp) + callee_frame_size); + *dex_pc = current_code->ToDexPc(caller_sp, caller_pc); } - if (kIsDebugBuild && do_caller_check) { - // Note that do_caller_check is optional, as this method can be called by - // stubs, and tests without a proper call stack. - NthCallerVisitor visitor(Thread::Current(), 1, true); - visitor.WalkStack(); - CHECK_EQ(caller, visitor.caller); - } - return caller; + } + if (kIsDebugBuild && do_caller_check) { + // Note that do_caller_check is optional, as this method can be called by + // stubs, and tests without a proper call stack. + NthCallerVisitor visitor(Thread::Current(), 1, true); + visitor.WalkStack(); + CHECK_EQ(caller, visitor.caller); + } + return caller; } -ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp, CalleeSaveType type, bool do_caller_check) +ArtMethod* GetCalleeSaveMethodCallerAndDexPc(ArtMethod** sp, + CalleeSaveType type, + uint32_t* dex_pc, + bool do_caller_check) REQUIRES_SHARED(Locks::mutator_lock_) { ScopedAssertNoThreadSuspension ants(__FUNCTION__); auto outer_caller_and_pc = DoGetCalleeSaveMethodOuterCallerAndPc(sp, type); ArtMethod* outer_method = outer_caller_and_pc.first; uintptr_t caller_pc = outer_caller_and_pc.second; - ArtMethod* caller = DoGetCalleeSaveMethodCaller(outer_method, caller_pc, do_caller_check); + ArtMethod* caller = DoGetCalleeSaveMethodCallerAndDexPc(sp, + type, + outer_method, + caller_pc, + dex_pc, + do_caller_check); return caller; } @@ -255,8 +274,13 @@ CallerAndOuterMethod GetCalleeSaveMethodCallerAndOuterMethod(Thread* self, Calle auto outer_caller_and_pc = DoGetCalleeSaveMethodOuterCallerAndPc(sp, type); result.outer_method = outer_caller_and_pc.first; uintptr_t caller_pc = outer_caller_and_pc.second; - result.caller = - DoGetCalleeSaveMethodCaller(result.outer_method, caller_pc, /* do_caller_check= */ true); + uint32_t dex_pc; + result.caller = DoGetCalleeSaveMethodCallerAndDexPc(sp, + type, + result.outer_method, + caller_pc, + &dex_pc, + /* do_caller_check= */ true); return result; } diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index ae80352f72..cfa744d278 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -188,9 +188,10 @@ bool FillArrayData(ObjPtr<mirror::Object> obj, const Instruction::ArrayDataPaylo template <typename INT_TYPE, typename FLOAT_TYPE> inline INT_TYPE art_float_to_integral(FLOAT_TYPE f); -ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp, - CalleeSaveType type, - bool do_caller_check = false) +ArtMethod* GetCalleeSaveMethodCallerAndDexPc(ArtMethod** sp, + CalleeSaveType type, + /* out */ uint32_t* dex_pc, + bool do_caller_check = false) REQUIRES_SHARED(Locks::mutator_lock_); struct CallerAndOuterMethod { diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index a405ab3bf2..7e96f2947c 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -279,9 +279,15 @@ class QuickArgumentVisitor { return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address); } - static ArtMethod* GetCallingMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { + static ArtMethod* GetCallingMethodAndDexPc(ArtMethod** sp, uint32_t* dex_pc) + REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK((*sp)->IsCalleeSaveMethod()); - return GetCalleeSaveMethodCaller(sp, CalleeSaveType::kSaveRefsAndArgs); + return GetCalleeSaveMethodCallerAndDexPc(sp, CalleeSaveType::kSaveRefsAndArgs, dex_pc); + } + + static ArtMethod* GetCallingMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { + uint32_t dex_pc; + return GetCallingMethodAndDexPc(sp, &dex_pc); } static ArtMethod* GetOuterMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -291,31 +297,6 @@ class QuickArgumentVisitor { return *reinterpret_cast<ArtMethod**>(previous_sp); } - static uint32_t GetCallingDexPc(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK((*sp)->IsCalleeSaveMethod()); - constexpr size_t callee_frame_size = - RuntimeCalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs); - ArtMethod** caller_sp = reinterpret_cast<ArtMethod**>( - reinterpret_cast<uintptr_t>(sp) + callee_frame_size); - uintptr_t outer_pc = QuickArgumentVisitor::GetCallingPc(sp); - const OatQuickMethodHeader* current_code = (*caller_sp)->GetOatQuickMethodHeader(outer_pc); - uintptr_t outer_pc_offset = current_code->NativeQuickPcOffset(outer_pc); - - if (current_code->IsOptimized()) { - CodeInfo code_info = CodeInfo::DecodeInlineInfoOnly(current_code); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset); - DCHECK(stack_map.IsValid()); - BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); - if (!inline_infos.empty()) { - return inline_infos.back().GetDexPc(); - } else { - return stack_map.GetDexPc(); - } - } else { - return current_code->ToDexPc(caller_sp, outer_pc); - } - } - static uint8_t* GetCallingPcAddr(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK((*sp)->IsCalleeSaveMethod()); uint8_t* return_adress_spill = @@ -1154,11 +1135,11 @@ extern "C" const void* artQuickResolutionTrampoline( const bool called_method_known_on_entry = !called->IsRuntimeMethod(); ArtMethod* caller = nullptr; if (!called_method_known_on_entry) { - caller = QuickArgumentVisitor::GetCallingMethod(sp); + uint32_t dex_pc; + caller = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc); called_method.dex_file = caller->GetDexFile(); { - uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); CodeItemInstructionAccessor accessor(caller->DexInstructions()); CHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits()); const Instruction& instr = accessor.InstructionAt(dex_pc); @@ -2116,8 +2097,8 @@ static TwoWordReturn artInvokeCommon(uint32_t method_idx, ArtMethod** sp) { ScopedQuickEntrypointChecks sqec(self); DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs)); - ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); - uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); + uint32_t dex_pc; + ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc); CodeItemInstructionAccessor accessor(caller_method->DexInstructions()); DCHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits()); const Instruction& instr = accessor.InstructionAt(dex_pc); @@ -2230,9 +2211,9 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_metho // Fetch the dex_method_idx of the target interface method from the caller. StackHandleScope<1> hs(self); Handle<mirror::Object> this_object = hs.NewHandle(raw_this_object); - ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); + uint32_t dex_pc; + ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc); uint32_t dex_method_idx; - uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); const Instruction& instr = caller_method->DexInstructions().InstructionAt(dex_pc); Instruction::Code instr_code = instr.Opcode(); DCHECK(instr_code == Instruction::INVOKE_INTERFACE || @@ -2351,8 +2332,8 @@ extern "C" uint64_t artInvokePolymorphic(mirror::Object* raw_receiver, Thread* s const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe."); // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC. - ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); - uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); + uint32_t dex_pc; + ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc); const Instruction& inst = caller_method->DexInstructions().InstructionAt(dex_pc); DCHECK(inst.Opcode() == Instruction::INVOKE_POLYMORPHIC || inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE); @@ -2478,8 +2459,8 @@ extern "C" uint64_t artInvokeCustom(uint32_t call_site_idx, Thread* self, ArtMet const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe."); // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC. - ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); - uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); + uint32_t dex_pc; + ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc); const DexFile* dex_file = caller_method->GetDexFile(); const dex::ProtoIndex proto_idx(dex_file->GetProtoIndexForCallSite(call_site_idx)); const char* shorty = caller_method->GetDexFile()->GetShorty(proto_idx); |