Don't hardcode the location of the caller.
This is to avoid shooting ourselves in the foot when
dealing with inlined frames. Instead, use common methods
for fetching the caller and its dex pc.
Change-Id: I3467a7b50cf163022d332e80356f0aab747de252
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 46629f5..9148878 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -25,8 +25,7 @@
namespace art {
-extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
- Thread* self)
+extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Called to ensure static storage base is initialized for direct static field reads and writes.
// A class may be accessing another class' fields when it doesn't have access, as access has been
@@ -36,8 +35,7 @@
return ResolveVerifyAndClinit(type_idx, caller, self, true, false);
}
-extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
- Thread* self)
+extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Called when method->dex_cache_resolved_types_[] misses.
ScopedQuickEntrypointChecks sqec(self);
@@ -45,8 +43,7 @@
return ResolveVerifyAndClinit(type_idx, caller, self, false, false);
}
-extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
- Thread* self)
+extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Called when caller isn't guaranteed to have access to a type and the dex cache may be
// unpopulated.
@@ -55,8 +52,7 @@
return ResolveVerifyAndClinit(type_idx, caller, self, false, true);
}
-extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx,
- Thread* self)
+extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly);
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2e7e2df..345b0ad 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -294,8 +294,13 @@
static mirror::ArtMethod* GetCallingMethod(StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
- uint8_t* previous_sp = reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize;
- return reinterpret_cast<StackReference<mirror::ArtMethod>*>(previous_sp)->AsMirrorPtr();
+ return GetCalleeSaveMethodCaller(sp, Runtime::kRefsAndArgs);
+ }
+
+ static uint32_t GetCallingDexPc(StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+ return GetCallingMethod(sp)->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
}
// For the given quick ref and args quick frame, return the caller's PC.
@@ -827,12 +832,13 @@
// Compute details about the called method (avoid GCs)
ClassLinker* linker = Runtime::Current()->GetClassLinker();
- mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
InvokeType invoke_type;
MethodReference called_method(nullptr, 0);
const bool called_method_known_on_entry = !called->IsRuntimeMethod();
+ mirror::ArtMethod* caller = nullptr;
if (!called_method_known_on_entry) {
- uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
+ caller = QuickArgumentVisitor::GetCallingMethod(sp);
+ uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
const DexFile::CodeItem* code;
called_method.dex_file = caller->GetDexFile();
code = caller->GetCodeItem();
@@ -1946,16 +1952,13 @@
// to hold the mutator lock (see SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) annotations).
template<InvokeType type, bool access_check>
-static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self, StackReference<mirror::ArtMethod>* sp);
-
-template<InvokeType type, bool access_check>
-static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self, StackReference<mirror::ArtMethod>* sp) {
+static TwoWordReturn artInvokeCommon(uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
+ StackReference<mirror::ArtMethod>* sp) {
ScopedQuickEntrypointChecks sqec(self);
DCHECK_EQ(sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
+ mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check,
type);
if (UNLIKELY(method == nullptr)) {
@@ -1994,7 +1997,6 @@
template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \
TwoWordReturn artInvokeCommon<type, access_check>(uint32_t method_idx, \
mirror::Object* this_object, \
- mirror::ArtMethod* caller_method, \
Thread* self, \
StackReference<mirror::ArtMethod>* sp) \
@@ -2012,58 +2014,58 @@
// See comments in runtime_support_asm.S
extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(
- uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method, Thread* self,
+ uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kInterface, true>(method_idx, this_object,
- caller_method, self, sp);
+ return artInvokeCommon<kInterface, true>(method_idx, this_object, self, sp);
}
extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(
- uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method, Thread* self,
+ uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kDirect, true>(method_idx, this_object, caller_method,
- self, sp);
+ return artInvokeCommon<kDirect, true>(method_idx, this_object, self, sp);
}
extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(
- uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method, Thread* self,
+ uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kStatic, true>(method_idx, this_object, caller_method,
- self, sp);
+ return artInvokeCommon<kStatic, true>(method_idx, this_object, self, sp);
}
extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(
- uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method, Thread* self,
+ uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kSuper, true>(method_idx, this_object, caller_method,
- self, sp);
+ return artInvokeCommon<kSuper, true>(method_idx, this_object, self, sp);
}
extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(
- uint32_t method_idx, mirror::Object* this_object,
- mirror::ArtMethod* caller_method, Thread* self,
+ uint32_t method_idx,
+ mirror::Object* this_object,
+ Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kVirtual, true>(method_idx, this_object, caller_method,
- self, sp);
+ return artInvokeCommon<kVirtual, true>(method_idx, this_object, self, sp);
}
// Determine target of interface dispatch. This object is known non-null.
extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interface_method,
mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
+ mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
mirror::ArtMethod* method;
if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
@@ -2075,12 +2077,7 @@
} else {
DCHECK(interface_method == Runtime::Current()->GetResolutionMethod());
- // Find the caller PC.
- constexpr size_t pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsAndArgs);
- uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) + pc_offset);
-
- // Map the caller PC to a dex PC.
- uint32_t dex_pc = caller_method->ToDexPc(caller_pc);
+ uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
const DexFile::CodeItem* code = caller_method->GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);