Truffle CallNode API

Christian Humer christian.humer at gmail.com
Wed Mar 5 18:38:52 UTC 2014


Hi Stefan,

I recently changed the inlining heuristic and semantics. I will come up
with proper documentation about it soon.

Inlining now just pulls a lever for the truffle compiler to inline a
certain method in the call graph. As you said it does not contextualize the
callee AST into the caller AST anymore. The contextualization on inlining
required the interpreter to reprofile the AST after inlining, which delayed
the compilation in an unfavorable way.

Contextualization is of course still required. Therefore we introduced a
new concept called splitting. Splitting basically creates a new CallTarget
with an uninitialized AST of the same method and calls the new target
instead of the original target. This new target may then afterwards be
inlined or not depending on the inlining budget and other criteria.

While the inlining heuristic is already quite fine, the split heuristic is
still work in progress. So splitting is currently disabled by default.

The SimpleLanguage already implements the required parts to support and
enable splitting. To support splitting you have to override the methods
isSplittable and split in your RootNode implementation.

Here is the implementation from the SimpleLanguage which I think you can
reuse roughly.

    @Override
    public boolean isSplittable() {
        return true;
    }
    @Override
    public RootNode split() {
        return new SLRootNode(getFrameDescriptor().shallowCopy(),
NodeUtil.cloneNode(uninitializedBodyNode), name);
    }

There is also new API for the CallNode:
boolean isSplittable() true if the underlying RootNode returns true in
isSplittable
boolean isSplit() true if the CallTarget for this CallNode was split.
CallTarget getSplitCallTarget() returns the call target that was split.
boolean split() enforce a split on the CallTarget.

Splitting can also be disabled globally with -G:-TruffleSplittingEnabled
(enabled by default).

I have to admit that the current heuristic for splitting is quite rough. So
I can recommend you to enforce inlining and splitting with CallNode#inline
and CallNode#split on the important calls for now. Is that good enough for
you, for now?

In the future this decision will be based on the polymorphism of the called
method. Therefore we also introduced a new method to Node getKind. getKind
returns whether the actual node is specialized/monomorphic, polymorphic or
generic/megamorphic. By counting polymorphic/megamorphic nodes we can do a
good guess if a split could be worthwhile or not. For this heuristic to
work you have to implement #getKind() in your specializations. Nodes that
use Truffle DSL automatically get support for that.

Hope this helps.
Please feel free to ask further questions.

Thanks.




- Christian Humer


On Wed, Mar 5, 2014 at 4:57 PM, Stefan Marr <java at stefan-marr.de> wrote:

> Hi Christian:
>
> I finally adopted CallNodes, however I wonder how this interacts with
> things like lexical scoping.
> Until now, I had special treatment for lexical scoping of blocks that get
> inlined.
>
> How do I communicate that to your inlining framework?
> I found the `split()` method in RootNode, which happens to be unused in
> SimpleLanguage, and without a comment, I am kind of unsure whether it is
> the right hook.
>
> Is the idea that I return my properly contextualized copy from split?
>
> Perhaps a brief example to show the problem I am thinking of:
>
> foo: a = (
>   a = 0 ifTrue:  [ ^ a + 1 ]
>         ifFalse: [ ^ a + 'foobar' ]
> )
>
> Both blocks are methods that are eventually inlined. However, they both
> access `a`, and thus, they depend on FrameSlot of it.
> Now, extending the example by introducing the bar and baz methods:
>
> bar = ( ^ self foo: 0 )
> baz = ( ^ self foo: 'something and ' )
>
> When #foo: gets inlined into these two methods, I need to use independent
> copies of the original two block methods in each of the inlined versions,
> so that the FrameSlot can specialize independently. #bar is supposed to
> specialize completely for integers, and #baz should specialize to strings.
>
> Thanks
> Stefan
>
>
> On 29 Jan 2014, at 22:09, Christian Humer <christian.humer at gmail.com>
> wrote:
>
> > I just updated the Truffle Inlining API with a more robust solution (will
> > get pushed to openjdk this night).
> > I removed the old API namely the following interfaces InlinableCallSite
> and
> > InlinedCallSite.
> > As a replacement for those classes you should now use a new class
> CallNode.
> > This class is already a Node and can directly be used as such inside of
> an
> > polymorphic function inline cache.
> > For further information on how to use it please see SLDirectDispatchNode
> > and the javadoc in the CallNode class.
> >
> > Feel free to ask further questions.
> >
> > Thanks.
> >
> > - Christian Humer
>
> --
> Stefan Marr
> INRIA Lille - Nord Europe
> http://stefan-marr.de/research/
>
>
>
>


More information about the graal-dev mailing list