summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2015-04-10 12:12:33 +0200
committerSebastien Hertz <shertz@google.com>2015-04-29 16:59:58 +0200
commit9d6bf69ad3012a9d843268fdd5325b6719b6d5f2 (patch)
treea41fc22d2c89e41c86feb5ef07ebda89b1b83d90 /runtime/interpreter
parentb6829c2ee05124d64a19c7a52ada4a23f624fb91 (diff)
downloadart-9d6bf69ad3012a9d843268fdd5325b6719b6d5f2.zip
art-9d6bf69ad3012a9d843268fdd5325b6719b6d5f2.tar.gz
art-9d6bf69ad3012a9d843268fdd5325b6719b6d5f2.tar.bz2
JDWP: properly combine location events
This CL properly groups JDWP events at the same location: Breakpoint, Single-step, Method Entry and Method Exit. This is necessary if the debugger is not the only instrumentation listener. This matches the behavior of Dalvik, especially for methods with a single return instruction. The interpreter was tuned so the instrumentation callbacks were called to satisfy the debugger with the idea the debugger was the only instrumentation listener. This is not true when method tracing is enabled at the same time. When tracing is enabled, there is always a listener for MethodEntry and MethodExit events (art::Trace class). However, if the debugger is only listening to DexPcMoved event (to manage JDWP Breakpoint event), it will not be notified of this event. We now properly call all the instrumentation callbacks in the interpreter and move the logic specific to debugging into the class DebugInstrumentationListener. This allows to properly group JDWP location events together depending on the sequence of instrumentation callbacks. We add Thread::tls_32bit_sized_values::debug_method_entry_ flag to remember we just entered a method. It replaces the local variable notified_method_entry_event in the interpreter and simplifies the code. Bump oat version to force recompilation because the layout of the Thread class is modified. Bug: 19829329 Change-Id: I204af9112e37d2eebc86661fb7c961a41c74e598
Diffstat (limited to 'runtime/interpreter')
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc47
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc27
2 files changed, 16 insertions, 58 deletions
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 878efba..dd1f55e 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -156,7 +156,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
uint16_t inst_data;
const void* const* currentHandlersTable;
- bool notified_method_entry_event = false;
UPDATE_HANDLER_TABLE();
if (LIKELY(dex_pc == 0)) { // We are entering the method as opposed to deoptimizing.
if (kIsDebugBuild) {
@@ -166,7 +165,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), 0);
- notified_method_entry_event = true;
}
}
@@ -264,9 +262,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
@@ -281,9 +276,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
@@ -299,9 +291,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
@@ -316,9 +305,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
@@ -352,9 +338,6 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
@@ -2510,26 +2493,16 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
// Note: we do not use the kReturn instruction flag here (to test the instruction is a return). The
// compiler seems to not evaluate "(Instruction::FlagsOf(Instruction::code) & kReturn) != 0" to
// a constant condition that would remove the "if" statement so the test is free.
-#define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) \
- alt_op_##code: { \
- if (Instruction::code != Instruction::RETURN_VOID && \
- Instruction::code != Instruction::RETURN_VOID_NO_BARRIER && \
- Instruction::code != Instruction::RETURN && \
- Instruction::code != Instruction::RETURN_WIDE && \
- Instruction::code != Instruction::RETURN_OBJECT) { \
- if (LIKELY(!notified_method_entry_event)) { \
- Runtime* runtime = Runtime::Current(); \
- const instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation(); \
- if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
- Object* this_object = shadow_frame.GetThisObject(code_item->ins_size_); \
- instrumentation->DexPcMovedEvent(self, this_object, shadow_frame.GetMethod(), dex_pc); \
- } \
- } else { \
- notified_method_entry_event = false; \
- } \
- } \
- UPDATE_HANDLER_TABLE(); \
- goto *handlersTable[instrumentation::kMainHandlerTable][Instruction::code]; \
+#define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) \
+ alt_op_##code: { \
+ Runtime* const runtime = Runtime::Current(); \
+ const instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation(); \
+ if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
+ Object* this_object = shadow_frame.GetThisObject(code_item->ins_size_); \
+ instrumentation->DexPcMovedEvent(self, this_object, shadow_frame.GetMethod(), dex_pc); \
+ } \
+ UPDATE_HANDLER_TABLE(); \
+ goto *handlersTable[instrumentation::kMainHandlerTable][Instruction::code]; \
}
#include "dex_instruction_list.h"
DEX_INSTRUCTION_LIST(INSTRUMENTATION_INSTRUCTION_HANDLER)
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index a5e5299..0e3420f 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -47,10 +47,7 @@ namespace interpreter {
// Code to run before each dex instruction.
#define PREAMBLE() \
do { \
- DCHECK(!inst->IsReturn()); \
- if (UNLIKELY(notified_method_entry_event)) { \
- notified_method_entry_event = false; \
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
+ if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), \
shadow_frame.GetMethod(), dex_pc); \
} \
@@ -67,7 +64,6 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
self->VerifyStack();
uint32_t dex_pc = shadow_frame.GetDexPC();
- bool notified_method_entry_event = false;
const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
if (LIKELY(dex_pc == 0)) { // We are entering the method as opposed to deoptimizing.
if (kIsDebugBuild) {
@@ -76,7 +72,6 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), 0);
- notified_method_entry_event = true;
}
}
const uint16_t* const insns = code_item->insns_;
@@ -171,19 +166,18 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
break;
}
case Instruction::RETURN_VOID_NO_BARRIER: {
+ PREAMBLE();
JValue result;
self->AllowThreadSuspension();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), inst->GetDexPc(insns),
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
case Instruction::RETURN_VOID: {
+ PREAMBLE();
QuasiAtomic::ThreadFenceForConstructor();
JValue result;
self->AllowThreadSuspension();
@@ -191,13 +185,11 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), inst->GetDexPc(insns),
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
case Instruction::RETURN: {
+ PREAMBLE();
JValue result;
result.SetJ(0);
result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
@@ -206,13 +198,11 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), inst->GetDexPc(insns),
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
case Instruction::RETURN_WIDE: {
+ PREAMBLE();
JValue result;
result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
self->AllowThreadSuspension();
@@ -220,13 +210,11 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), inst->GetDexPc(insns),
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}
case Instruction::RETURN_OBJECT: {
+ PREAMBLE();
JValue result;
self->AllowThreadSuspension();
const size_t ref_idx = inst->VRegA_11x(inst_data);
@@ -254,9 +242,6 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), inst->GetDexPc(insns),
result);
- } else if (UNLIKELY(instrumentation->HasDexPcListeners())) {
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- shadow_frame.GetMethod(), dex_pc);
}
return result;
}