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
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to