summaryrefslogtreecommitdiff
path: root/runtime/instrumentation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/instrumentation.cc')
-rw-r--r--runtime/instrumentation.cc121
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()