diff options
Diffstat (limited to 'runtime/instrumentation.cc')
| -rw-r--r-- | runtime/instrumentation.cc | 121 |
1 files changed, 60 insertions, 61 deletions
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 12f1522386..cbcaaef260 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -18,8 +18,6 @@ #include <sstream> -#include <android-base/logging.h> - #include "arch/context.h" #include "art_field-inl.h" #include "art_method-inl.h" @@ -1357,66 +1355,65 @@ DeoptimizationMethodType Instrumentation::GetDeoptimizationMethodType(ArtMethod* } // Try to get the shorty of a runtime method if it's an invocation stub. -static char GetRuntimeMethodShorty(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) { - char shorty = 'V'; - StackVisitor::WalkStack( - [&shorty](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) { - ArtMethod* m = stack_visitor->GetMethod(); - if (m == nullptr || m->IsRuntimeMethod()) { - return true; - } - // The first Java method. - if (m->IsNative()) { - // Use JNI method's shorty for the jni stub. - shorty = m->GetShorty()[0]; - } else if (m->IsProxyMethod()) { - // Proxy method just invokes its proxied method via - // art_quick_proxy_invoke_handler. - shorty = m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty()[0]; - } else { - const Instruction& instr = m->DexInstructions().InstructionAt(stack_visitor->GetDexPc()); - if (instr.IsInvoke()) { - auto get_method_index_fn = [](ArtMethod* caller, - const Instruction& inst, - uint32_t dex_pc) - REQUIRES_SHARED(Locks::mutator_lock_) { - switch (inst.Opcode()) { - case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: - case Instruction::INVOKE_VIRTUAL_QUICK: { - uint16_t method_idx = caller->GetIndexFromQuickening(dex_pc); - CHECK_NE(method_idx, DexFile::kDexNoIndex16); - return method_idx; - } - default: { - return static_cast<uint16_t>(inst.VRegB()); - } - } - }; - - uint16_t method_index = get_method_index_fn(m, instr, stack_visitor->GetDexPc()); - const DexFile* dex_file = m->GetDexFile(); - if (interpreter::IsStringInit(dex_file, method_index)) { - // Invoking string init constructor is turned into invoking - // StringFactory.newStringFromChars() which returns a string. - shorty = 'L'; - } else { - shorty = dex_file->GetMethodShorty(method_index)[0]; - } +struct RuntimeMethodShortyVisitor : public StackVisitor { + explicit RuntimeMethodShortyVisitor(Thread* thread) + : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), + shorty('V') {} + + static uint16_t GetMethodIndexOfInvoke(ArtMethod* caller, + const Instruction& inst, + uint32_t dex_pc) + REQUIRES_SHARED(Locks::mutator_lock_) { + switch (inst.Opcode()) { + case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: + case Instruction::INVOKE_VIRTUAL_QUICK: { + uint16_t method_idx = caller->GetIndexFromQuickening(dex_pc); + CHECK_NE(method_idx, DexFile::kDexNoIndex16); + return method_idx; + } + default: { + return inst.VRegB(); + } + } + } - } else { - // It could be that a non-invoke opcode invokes a stub, which in turn - // invokes Java code. In such cases, we should never expect a return - // value from the stub. - } + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { + ArtMethod* m = GetMethod(); + if (m == nullptr || m->IsRuntimeMethod()) { + return true; + } + // The first Java method. + if (m->IsNative()) { + // Use JNI method's shorty for the jni stub. + shorty = m->GetShorty()[0]; + } else if (m->IsProxyMethod()) { + // Proxy method just invokes its proxied method via + // art_quick_proxy_invoke_handler. + shorty = m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty()[0]; + } else { + const Instruction& instr = m->DexInstructions().InstructionAt(GetDexPc()); + if (instr.IsInvoke()) { + uint16_t method_index = GetMethodIndexOfInvoke(m, instr, GetDexPc()); + const DexFile* dex_file = m->GetDexFile(); + if (interpreter::IsStringInit(dex_file, method_index)) { + // Invoking string init constructor is turned into invoking + // StringFactory.newStringFromChars() which returns a string. + shorty = 'L'; + } else { + shorty = dex_file->GetMethodShorty(method_index)[0]; } - // Stop stack walking since we've seen a Java frame. - return false; - }, - thread, - /* context= */ nullptr, - art::StackVisitor::StackWalkKind::kIncludeInlinedFrames); - return shorty; -} + } else { + // It could be that a non-invoke opcode invokes a stub, which in turn + // invokes Java code. In such cases, we should never expect a return + // value from the stub. + } + } + // Stop stack walking since we've seen a Java frame. + return false; + } + + char shorty; +}; TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc, @@ -1450,7 +1447,9 @@ TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self, // for clinit, we need to pass return results to the caller. // We need the correct shorty to decide whether we need to pass the return // result for deoptimization below. - return_shorty = GetRuntimeMethodShorty(self); + RuntimeMethodShortyVisitor visitor(self); + visitor.WalkStack(); + return_shorty = visitor.shorty; } else { // Some runtime methods such as allocations, unresolved field getters, etc. // have return value. We don't need to set return_value since MethodExitEvent() |