summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_goto_table_impl.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2013-10-17 15:10:52 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-10-17 15:10:53 +0000
commitf6e4a59cf58471ba69b0eafb34b3a43b2b95caa1 (patch)
treeca1f63c18fd92a085c1456174494b01bf7dc5787 /runtime/interpreter/interpreter_goto_table_impl.cc
parent6cddafbdd4b092565664195a25256b907f5d2ccd (diff)
parentee1997a3b83334985e757f369c09e111b121661b (diff)
downloadart-f6e4a59cf58471ba69b0eafb34b3a43b2b95caa1.zip
art-f6e4a59cf58471ba69b0eafb34b3a43b2b95caa1.tar.gz
art-f6e4a59cf58471ba69b0eafb34b3a43b2b95caa1.tar.bz2
Merge "Improve interpreter handler table management." into dalvik-dev
Diffstat (limited to 'runtime/interpreter/interpreter_goto_table_impl.cc')
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc162
1 files changed, 108 insertions, 54 deletions
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 3a91b8c..aa6bcd6 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -51,14 +51,8 @@ namespace interpreter {
} \
} while (false)
-#define UPDATE_HANDLER_TABLE() \
- do { \
- if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
- currentHandlersTable = instrumentationHandlersTable; \
- } else { \
- currentHandlersTable = handlersTable; \
- } \
- } while (false);
+#define UPDATE_HANDLER_TABLE() \
+ currentHandlersTable = handlersTable[Runtime::Current()->GetInstrumentation()->GetInterpreterHandlerTable()]
#define UNREACHABLE_CODE_CHECK() \
do { \
@@ -70,10 +64,77 @@ namespace interpreter {
#define HANDLE_INSTRUCTION_START(opcode) op_##opcode: // NOLINT(whitespace/labels)
#define HANDLE_INSTRUCTION_END() UNREACHABLE_CODE_CHECK()
+/**
+ * Interpreter based on computed goto tables.
+ *
+ * Each instruction is associated to a handler. This handler is responsible for executing the
+ * instruction and jump to the next instruction's handler.
+ * In order to limit the cost of instrumentation, we have two handler tables:
+ * - the "main" handler table: it contains handlers for normal execution of each instruction without
+ * handling of instrumentation.
+ * - the "alternative" handler table: it contains alternative handlers which first handle
+ * instrumentation before jumping to the corresponding "normal" instruction's handler.
+ *
+ * When instrumentation is active, the interpreter uses the "alternative" handler table. Otherwise
+ * it uses the "main" handler table.
+ *
+ * The current handler table is the handler table being used by the interpreter. It is updated:
+ * - on backward branch (goto, if and switch instructions)
+ * - after invoke
+ * - when an exception is thrown.
+ * This allows to support an attaching debugger to an already running application for instance.
+ *
+ * For a fast handler table update, handler tables are stored in an array of handler tables. Each
+ * handler table is represented by the InterpreterHandlerTable enum which allows to associate it
+ * to an index in this array of handler tables ((see Instrumentation::GetInterpreterHandlerTable).
+ *
+ * Here's the current layout of this array of handler tables:
+ *
+ * ---------------------+---------------+
+ * | NOP | (handler for NOP instruction)
+ * +---------------+
+ * "main" | MOVE | (handler for MOVE instruction)
+ * handler table +---------------+
+ * | ... |
+ * +---------------+
+ * | UNUSED_FF | (handler for UNUSED_FF instruction)
+ * ---------------------+---------------+
+ * | NOP | (alternative handler for NOP instruction)
+ * +---------------+
+ * "alternative" | MOVE | (alternative handler for MOVE instruction)
+ * handler table +---------------+
+ * | ... |
+ * +---------------+
+ * | UNUSED_FF | (alternative handler for UNUSED_FF instruction)
+ * ---------------------+---------------+
+ *
+ */
template<bool do_access_check>
JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame, JValue result_register) {
- bool do_assignability_check = do_access_check;
+ // Define handler tables:
+ // - The main handler table contains execution handlers for each instruction.
+ // - The alternative handler table contains prelude handlers which check for thread suspend and
+ // manage instrumentation before jumping to the execution handler.
+ static const void* const handlersTable[instrumentation::kNumHandlerTables][kNumPackedOpcodes] = {
+ {
+ // Main handler table.
+#define INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) &&op_##code,
+#include "dex_instruction_list.h"
+ DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
+#undef DEX_INSTRUCTION_LIST
+#undef INSTRUCTION_HANDLER
+ }, {
+ // Alternative handler table.
+#define INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) &&alt_op_##code,
+#include "dex_instruction_list.h"
+ DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
+#undef DEX_INSTRUCTION_LIST
+#undef INSTRUCTION_HANDLER
+ }
+ };
+
+ const bool do_assignability_check = do_access_check;
if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
LOG(FATAL) << "Invalid shadow frame for interpreter use";
return JValue();
@@ -81,35 +142,17 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
self->VerifyStack();
uint32_t dex_pc = shadow_frame.GetDexPC();
- const instrumentation::Instrumentation* const instrumentation = Runtime::Current()->GetInstrumentation();
+ const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
+ uint16_t inst_data;
+ const void* const* currentHandlersTable;
+ UPDATE_HANDLER_TABLE();
if (LIKELY(dex_pc == 0)) { // We are entering the method as opposed to deoptimizing..
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), 0);
}
}
- const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
- uint16_t inst_data;
-
- // Define handlers table.
- static const void* handlersTable[kNumPackedOpcodes] = {
-#define INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) &&op_##code,
-#include "dex_instruction_list.h"
- DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
-#undef DEX_INSTRUCTION_LIST
-#undef INSTRUCTION_HANDLER
- };
-
- static const void* instrumentationHandlersTable[kNumPackedOpcodes] = {
-#define INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) &&instrumentation_op_##code,
-#include "dex_instruction_list.h"
- DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
-#undef DEX_INSTRUCTION_LIST
-#undef INSTRUCTION_HANDLER
- };
-
- const void** currentHandlersTable;
- UPDATE_HANDLER_TABLE();
// Jump to first instruction.
ADVANCE(0);
@@ -207,6 +250,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
}
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
@@ -222,6 +266,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
}
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
@@ -238,6 +283,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
}
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
@@ -253,6 +299,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
}
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
@@ -286,6 +333,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_PENDING_EXCEPTION();
}
}
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
shadow_frame.GetMethod(), dex_pc,
@@ -547,8 +595,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
}
@@ -559,8 +607,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
}
@@ -571,8 +619,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
}
@@ -583,8 +631,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
}
@@ -595,8 +643,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
}
@@ -688,8 +736,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -704,8 +752,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -720,8 +768,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -736,8 +784,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -752,8 +800,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -768,8 +816,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -784,8 +832,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -800,8 +848,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -816,8 +864,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -832,8 +880,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -848,8 +896,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -864,8 +912,8 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
if (IsBackwardBranch(offset)) {
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
- UPDATE_HANDLER_TABLE();
}
ADVANCE(offset);
} else {
@@ -2306,8 +2354,10 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
CHECK(self->IsExceptionPending());
if (UNLIKELY(self->TestAllFlags())) {
CheckSuspend(self);
+ UPDATE_HANDLER_TABLE();
}
Object* this_object = shadow_frame.GetThisObject(code_item->ins_size_);
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
uint32_t found_dex_pc = FindNextInstructionFollowingException(self, shadow_frame, dex_pc,
this_object,
instrumentation);
@@ -2320,11 +2370,15 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
}
// Create alternative instruction handlers dedicated to instrumentation.
-#define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) \
- instrumentation_op_##code: { \
- instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), \
- shadow_frame.GetMethod(), dex_pc); \
- goto *handlersTable[Instruction::code]; \
+#define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v) \
+ alt_op_##code: { \
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); \
+ if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
+ instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), \
+ 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)