On 09/08/2011 01:12 AM, John Rose wrote:
> On Sep 7, 2011, at 3:28 PM, Rémi Forax wrote:
>
>> On 09/07/2011 10:38 PM, John Rose wrote:
>>> Object l0, l1, l2, ...;
>>> l0 = l1 = l2 = ... null; // these are required only for definite
>>> assignment in the catch body
>>> try {
>>> ...do fast path...
>>> if (...constraint violated...) throw new DeoptExc(...);
>>> return ...fast result...
>>> } catch (DeoptExc ex) {
>>> Object[] display = { l0, l1, l2, ... };
>>> return backupInterpreter(ex, display); // N.B. could throw DeoptExc
>>> to caller also
>>> }
>>>
>>> This problem is that the eager initializations of the various locals slow
>>> down the fast path. (Did I get it right Remi?) The register allocator
>>> should push them down into the catch body, and maybe even into the static
>>> debug info of the JVM.
>> Locals is not the only problem, you have to track stack values too.
> To clarify, I meant only JVM locals, which serve as virtual registers for the
> application language locals, stacks, whatever. JVM stack elements are
> guaranteed to be thrown away when a JVM exception is thrown, so they function
> like virtual registers that are blown by deopt. events.
>
>> It's the combination of locals initialization, local variable creation
>> for storing stack values
> Yes, if there are logically stacked values that need tracking into slow
> paths, they need to be spilled to JVM locals. The cost of this will be
> reduced by good register allocations in the JIT. Ensuring this is part of
> the tuning job.
>
>> and supplementary exception handlers
>> (that's the main problem, or you have multiple handlers,
>> or you have one handler and a constant)
>> that slow down the fast path.
> I think a single handler is going to be simpler all the way around. Thus,
> the deopt. source location and value display map have to be stored somewhere
> so they can be made a parameter to the handler. I think the exception object
> is the most likely place to store it; TLS is also a candidate.
currently I'm thinking to use multiple exception handler entry points
but only one common code.
handler1:
iconst_0
goto common_handler
handler2:
iconst_1
goto common_handler
...
common_handler:
swap
pop // remove exception object
aload spill1
aload spill2
...
invokedynamic foo (ILObject;LObject ...)
>
> To extend on your cute idea below, have the source location and value display
> map be static parameters to the invokedynamic instruction which initiates
> transfer to the slow path. That way everything is in the class file, but
> lazily unpacked only if needed. There's little or no need to use executable
> bytecode instructions (other than an indy at the throw point and an indy in
> the local handler) to manage the deopt. transition. The actual bytecodes can
> be devoted to executing the fast path code, and testing for type-state faults.
for PHP.reboot I need the AST node corresponding to the operation that
overflow,
so I need a live value. But I can use one parameter of the method to
transfer all AST nodes
wrapped in one object bound to the current method.
>
> BTW, although one might think that the repertoire for static BSM arguments is
> limited (string, class, int, long, MH, MT), note that the MH gives a hook to
> open-ended constant formation. Just treat the MH as a thunk to be executed
> to materialize a desired constant.
but you can get live value unless you allow to insert live values to the
constant pool
when linking the class (another old dream).
>
>> Also, in the catch block you can use invokedynamic to avoid
>> the object array creation at call site.
> Yes, cute idea. Simplifying code on the slow path should make for faster
> loading and startup.
>
> Or (putting on my Pack200 hat), invokedynamic is the ultimate code-stream
> compressor.
>
> -- John
Rémi
_______________________________________________
mlvm-dev mailing list
[email protected]
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev