Interpreter restructuring
This is a restructuring of the Dalvik ARM and x86 interpreters:
o Combine the old portstd and portdbg interpreters into a single
portable interpreter.
o Add debug/profiling support to the fast (mterp) interpreters.
o Delete old mechansim of switching between interpreters. Now, once
you choose an interpreter at startup, you stick with it.
o Allow JIT to co-exist with profiling & debugging (necessary for
first-class support of debugging with the JIT active).
o Adds single-step capability to the fast assembly interpreters without
slowing them down (and, in fact, measurably improves their performance).
o Remove old "polling for safe point" mechanism. Breakouts now achieved
via modifying base of interpreter handler table.
o Simplify interpeter control mechanism.
o Allow thread-granularity control for profiling & debugging
The primary motivation behind this change was to improve the responsiveness
of debugging and profiling and to make it easier to add new debugging and
profiling capabilities in the future. Instead of always bailing out to the
slow debug portable interpreter, we can now stay in the fast interpreter.
A nice side effect of the change is that the fast interpreters
got a healthy speed boost because we were able to replace the
polling safepoint check that involved a dozen or so instructions
with a single table-base reload. When combined with the two earlier CLs
related to this restructuring, we show a 5.6% performance improvement
using libdvm_interp.so on the Checkers benchmark relative to Honeycomb.
Change-Id: I8d37e866b3618def4e582fc73f1cf69ffe428f3c
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 817b7e6..a485ca5 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -146,7 +146,7 @@
dvmLockMutex(&gDvmJit.compilerLock);
while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
- self->suspendCount == 0) {
+ self->interpBreak.ctl.suspendCount == 0) {
/*
* Use timed wait here - more than one mutator threads may be blocked
* but the compiler thread will only signal once when the queue is
@@ -420,7 +420,7 @@
* NOTE: the profile table must only be allocated once, globally.
* Profiling is turned on and off by nulling out gDvm.pJitProfTable
* and then restoring its original value. However, this action
- * is not syncronized for speed so threads may continue to hold
+ * is not synchronized for speed so threads may continue to hold
* and update the profile table after profiling has been turned
* off by null'ng the global pointer. Be aware.
*/
@@ -458,6 +458,7 @@
gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable;
gDvmJit.pProfTableCopy = pJitProfTable;
gDvmJit.pJitTraceProfCounters = pJitTraceProfCounters;
+ dvmJitUpdateState();
dvmUnlockMutex(&gDvmJit.tableLock);
/* Signal running threads to refresh their cached pJitTable pointers */
@@ -738,6 +739,7 @@
/* Disable new translation requests */
gDvmJit.pProfTable = NULL;
gDvmJit.pProfTableCopy = NULL;
+ dvmJitUpdateState();
if (gDvm.verboseShutdown ||
gDvmJit.profileMode == kTraceProfilingContinuous) {
@@ -796,7 +798,7 @@
* may be executed before the compiler thread has finished
* initialization.
*/
- if ((gDvm.interpBreak & kSubModeMethodTrace) &&
+ if ((gDvm.activeProfilers != 0) &&
!gDvmJit.methodTraceSupport) {
bool resetRequired;
/*
@@ -828,4 +830,6 @@
dvmUnlockMutex(&gDvmJit.tableLock);
if (needUnchain)
dvmJitUnchainAll();
+ // Make sure all threads have current values
+ dvmJitUpdateState();
}