diff options
author | buzbee <buzbee@google.com> | 2011-02-11 17:48:20 -0800 |
---|---|---|
committer | buzbee <buzbee@google.com> | 2011-02-19 13:35:30 -0800 |
commit | 9f601a917c8878204482c37aec7005054b6776fa (patch) | |
tree | f98216746f7d84c894627cb6256e5be66ca1a1f8 /vm/compiler/codegen/x86/CodegenDriver.c | |
parent | f7f82d5e083f6c99d0dd6de213650751ca314cff (diff) | |
download | android_dalvik-9f601a917c8878204482c37aec7005054b6776fa.tar.gz android_dalvik-9f601a917c8878204482c37aec7005054b6776fa.tar.bz2 android_dalvik-9f601a917c8878204482c37aec7005054b6776fa.zip |
Interpreter restructuring: eliminate InterpState
The key datastructure for the interpreter is InterpState.
This change eliminates it, merging its data with the Thread structure.
Here's why:
In principio creavit Fadden Thread et InterpState. And it was good.
Thread holds thread-private state, while InterpState captures data
associated with a Dalvik interpreter activation. Because JNI calls
can result in nested interpreter invocations, we can have more than one
InterpState for each actual thread. InterpState was relatively small,
and it all worked well. It was used enough that in the Arm version
a register (rGLUE) was dedicated to it.
Then, along came the JIT guys, who saw InterpState as a convenient place
to dump all sorts of useful data that they wanted quick access to through
that dedicated register. InterpState grew and grew. In terms of
space, this wasn't a big problem - but it did mean that the initialization
cost of each interpreter activation grew as well. For applications
that do a lot of callbacks from native code into Dalvik, this is
measurable. It's also mostly useless cost because much of the JIT-related
InterpState initialization was setting up useful constants - things that
don't need to be saved and restored all the time.
The biggest problem, though, deals with thread control. When something
interesting is happening that needs all threads to be stopped (such as
GC and debugger attach), we have access to all of the Thread structures,
but we don't have access to all of the InterpState structures (which
may be buried/nested on the native stack). As a result, polling for
thread suspension is done via a one-indirection pointer chase. InterpState
itself can't hold the stop bits because we can't always find it, so
instead it holds a pointer to the global or thread-specific stop control.
Yuck.
With this change, we eliminate InterpState and merge all needed data
into Thread. Further, we replace the decidated rGLUE register with a
pointer to the Thread structure (rSELF). The small subset of state
data that needs to be saved and restored across nested interpreter
activations is collected into a record that is saved to the interpreter
frame, and restored on exit. Further, these small records are linked
together to allow tracebacks to show nested activations. Old InterpState
variables that simply contain useful constants are initialized once at
thread creation time.
This CL is large enough by itself that the new ability to streamline
suspend checks is not done here - that will happen in a future CL. Here
we just focus on consolidation.
Change-Id: Ide6b2fb85716fea454ac113f5611263a96687356
Diffstat (limited to 'vm/compiler/codegen/x86/CodegenDriver.c')
-rw-r--r-- | vm/compiler/codegen/x86/CodegenDriver.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/vm/compiler/codegen/x86/CodegenDriver.c b/vm/compiler/codegen/x86/CodegenDriver.c index e440e37ab..a5ef56afb 100644 --- a/vm/compiler/codegen/x86/CodegenDriver.c +++ b/vm/compiler/codegen/x86/CodegenDriver.c @@ -46,7 +46,7 @@ static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset) loadConstant(cUnit, rPC, (int)(cUnit->method->insns + offset)); loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue loadWordDisp(cUnit, rECX, - offsetof(InterpState, jitToInterpEntries.dvmJitToInterpPunt), + offsetof(Thread, jitToInterpEntries.dvmJitToInterpPunt), rEAX); opReg(cUnit, kOpUncondBr, rEAX); } @@ -68,7 +68,7 @@ static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir) genPuntToInterp(cUnit, mir->offset); return; } - int entryAddr = offsetof(InterpState, + int entryAddr = offsetof(Thread, jitToInterpEntries.dvmJitToInterpSingleStep); loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue loadWordDisp(cUnit, rECX, entryAddr, rEAX); // rEAX<- entry address |