ZipPy status update

Chris Seaton chris at chrisseaton.com
Mon Dec 23 07:41:35 PST 2013


Specialising on not needing to catch the return exception:

Not all methods need to catch and handle ReturnException. Christian's
suggestion is that you speculate that they will not need it. You could do
this with two nodes - one that transfer to interpreter in the handler, and
one that actually does something in the handler. More simply you can do it
with just one node, and a BranchProfile in the handler. See the
BranchProfile class and tests to see how this works, and ask again if
that's not clear, but basically it's like

final BranchProfile catchBranchProfile = new BranchProfile()

...

catch (ReturnException e) {
    catchBranchProfile.enter();
    ...
}

This cuts of compilation of the catch node when it isn't ever used,
reducing code size. Reducing code size is an especially good proxy for
increasing code speed in Trufffle.

Non-local returns in Ruby:

Each method has a unique identifier allocated in the parser. The throw
nodes also store this integer, and they put it into the ReturnException
when they construct it. Then the ReturnException handlers check if the
exception is meant for them, and if it's not they re-throw it. In Ruby it's
very common to go through at least one scope like this - returns in a block
within a method return from the method, not the block, even though the
block is really a method in its own right. When the exception is finally
caught I just return it as the return value from the execute method and it
becomes a normal returned value.

Note that in Ruby the return handler is a node all on its own. This logic
isn't in RubyRootNode, RubyMethod, or the send node, like it looks like you
are here. Methods which need it have a CatchReturnNode in their prelude. I
also use this technique for things like checking that the number of
arguments is correct.

Then nodes which don't ever catch returns, like blocks, don't even have
this node to begin with.

Chris


On 23 December 2013 14:47, Stefan Marr <java at stefan-marr.de> wrote:

> Hi Christian,
> Hi Chris:
>
> I was wondering about alternative solutions for non-local returns.
> Christian, you said:
>
> > 1) Major: (OptimizedCallTarget.java:214) Method.execute(Method.java:72)
> > This method calls a method #messageSendExecution which contains a lot of
> control flow and allocations  [4] . Speculate on the fact that all of this
> code is not required. It contains a while loop + a lot of exception
> catches. I think on the fast-path it could just call the body of the method.
>
> The first thing, I noticed after you pointing me there, is that I was able
> to remove some of the complexity, because I intrinsified while loops, and
> don’t need support for the control flow exception anymore. However, that
> still leaves me with this:
>
>   protected static Object messageSendExecution(final VirtualFrame frame,
>       final ExpressionNode expr) {
>     FrameOnStackMarker marker =
> Arguments.get(frame).getFrameOnStackMarker();
>     Object result;
>
>     try {
>       result = expr.executeGeneric(frame);
>     } catch (ReturnException e) {
>       if (!e.reachedTarget(marker)) {
>         marker.frameNoLongerOnStack();
>         throw e;
>       } else {
>         result = e.result();
>       }
>     }
>
>     marker.frameNoLongerOnStack();
>     return result;
>   }
>
> So, the while loop is gone. We just got the exception handling for
> non-local returns.
> You said, speculate that you don’t need that. And I am now wondering
> whether I could go further than what you see above.
>
> Chris, how did you solve non-local returns for Ruby? I suppose Ruby’s
> return is more or less similar to Smalltalk’s?
>
> For SOM, I need to be able to return to the correct lexical scope, i.e., I
> want to return from the outer lexical method that’s still on the stack.
> However, in addition, I need to unwind the stack, and mark frames as
> ‘unwound’/removed from the stack in order to be able to handle blocks
> correctly that were return from a method, and were the outer activation
> does not exist anymore. Here, a non-local return just doesn’t have a good
> semantic, and needs to raise an error.
>
> So, I guess, this means, the only time I do not need this exception
> handling here is when a method does not define any blocks in its body.
> Chris, do you do that kind of special casing?
>
> Thanks
> Stefan
>
> --
> Stefan Marr
> Software Languages Lab
> Vrije Universiteit Brussel
> Pleinlaan 2 / B-1050 Brussels / Belgium
> http://soft.vub.ac.be/~smarr
> Phone: +32 2 629 2974
> Fax:   +32 2 629 3525
>
>


More information about the graal-dev mailing list