How to do AST inlining of method calls?
Andreas Woess
andreas.woess at jku.at
Tue Sep 10 17:31:06 PDT 2013
Answers inline.
On 11.09.2013 01:20, Stefan Marr wrote:
> Hi:
>
> I am experimenting with AST inlining in the TruffleSOM implementation and would like to know what the suggested best practices are.
>
> I started to inline monomorphic message sends in order to avoid issues with mega-morphic send sites typically found when evaluating blocks (lambdas).
>
> Now I am wondering how far that inlining logic should be pushed.
> I attempted to just duplicate the relevant AST subtree and leave the nodes themselves more or less untouched.
> Specifically, this means, I still rely on a frame to be constructed in a new InlinedMonomorphicMessageNode, which I introduced.
> This approach allows me to preserve the semantics of having a frame, and with it access to the same Smalltalk local variables as previously, even so the AST nodes are inlined in the monomorphic all site. Another problem this design solves is the catching of the same control flow exceptions as the method node that got replaced. Especially, the non-local return still needs to be treated correctly, I think, even with inlining.
This is the correct approach. Note that you should duplicate the tree in
its uninitialized state (e.g. in the constructor of the method root node
and keep a copy there) so that the inlined tree specializes for that
particular call.
> Currently, my main issue with this naive approach is that I still need to create a VirtualFrame object.
> This is possible with the frame factory given to the inline(.) method of the InlinableCallSite interface, but it causes problems with the Graal/Truffle compiler. The VerifyFrameDoesNotEscapePhase causes issues, because it sees the frame creation and complains about the fact that the new frame is given to a method call. The executeInlined(..) method below is the relevant fragment.
Again, this is this the right way. You should get a stack trace with the
approximate location of the problem.
> private Object executeInlined(final PackedFrame caller, final Object rcvr,
> final Object[] args) {
> final VirtualFrame frame = frameFactory.create(
> inlinedMethod.getFrameDescriptor(), caller, new Arguments(rcvr, args));
>
> final FrameOnStackMarker marker = Misc.initializeFrame(frame.materialize(),
> inlinedMethod.getArgumentSlots(),
> universe.nilObject);
> return Misc.sendSiteExecution(marker, frame, methodBody); // this or any of the `executeGeneric(VirtualFrame)` calls in it are problematic
> }
The executeInlined method should still get the old VirtualFrame as a
parameter so that the Partial Evaluator will process the method and pick
up the new virtual frame. Hope this helps. I also wonder why you
immediately materialize the frame for initializeFrame; this shouldn't be
necessary.
Regarding your last email, you might want to consider rewriting control
structures / well-known messages like ifTrue, whileTrue, etc. to
specialized nodes instead of going through a normal call, e.g. a
WhileTrueNode with inlined condition and block.
- andreas
More information about the graal-dev
mailing list