summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2023-05-04 14:24:19 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2023-05-04 15:34:48 +0000
commit88411fb64e4644874d11649e14c4404e7a6777d9 (patch)
treea739084266c4b3c196c924710ff4213fc149fc09
parentbe726b5fb9fa19e9731faa6cacd747efbde9d5b9 (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.cc84
-rw-r--r--runtime/entrypoints/entrypoint_utils.h7
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc55
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);