review request (L): 6939861: JVM should handle more conversion operations
john.r.rose at oracle.com
Thu May 5 04:16:53 PDT 2011
I have finished the last large chunk of JVM work for JDK 7 JSR 292, the implementation of so-called "ricochet frames". Here it is for review:
6939861: JVM should handle more conversion operations
This work started in April 2010 and was partially reviewed last October:
These frames allow one method handle to invoke a second recursively, with a third method handle as the continuation to invoke on a set of preset arguments, plus the return value from the second method handle. This is the simplest way to provide a "hook" for combining method handles without spinning bytecodes specific to the set of stacked intermediate arguments.
For example, this provides a way to convert a primitive value to a boxed reference: The first function accepts the primitive (plus maybe other arguments), passes it (alone) to a second function such as Long.valueOf(long), accepts the boxed value back, replaces the original argument with the boxed version (perhaps adjusting stack size, as occurs with long and double here), and invokes the third and final function which expects a boxed reference. (The inner function is tail-called, and gets all the pending arguments originally saved by the first function.) There are many points where the present JDK code will fail due to boxing, because of the lack of a bytecode class to manage the recursive call to Long.valueOf, while this mechanism allows all such cases to be handled simply and efficiently. This mechanism handles boxing, asCollector, filterArguments, filterReturnValue, and foldArguments.
There is more description about these control flow patterns in my recent post to mlvm-dev:
The main technical requirement for the JVM is that a recognizable stack frame be pushed during the intermediate method handle call, so that if there is an exception, or a GC, or some other stack walk, the stack will be parsed properly. Crucially, the pending arguments (saved for ) must be recognized as managed pointers.
With suitable JDK support (to be integrated next week), the JVM code passes strong tests of argument spreading and collecting, with references, primitives, and mixtures up to the maximum of 255 arguments. The JVM also runs "down-rev" JDK code just fine, so there's no "flag day". Here for reference is the JDK code:
(This JDK change does not yet discard hardwired bytecode adapter classes like ToGeneric and FromGeneric, but that will be done also before integration, assuming the platforms are ready for this.)
Known missing parts, which cause temporary performance reductions:
- methodHandleWalk support to decode the new adapters
- port to platforms other than x86
- removing obsolete JDK code, to use the new mechanism
- x86/64 fails some JSR 292 test cases (might be fixed for integration)
Known working parts:
- x86/32 (passes all unit tests)
- GC, stack walking, exception throwing (tested with stress tests)
- boxing of primitive arguments (the simplest case; requires a recursion to the GC)
- filtering, collecting, folding of arguments by user functions and primitives (boxing, varargs collection)
- arbitrary mixes of primitive and/or reference arguments and return types
More information about the hotspot-compiler-dev