TruffleSOM with SimpleLanguage-Style Call Caches

Stefan Marr java at
Tue Dec 10 07:02:51 PST 2013

Hi Chris:

On 10 Dec 2013, at 15:41, Chris Seaton <chris at> wrote:

> What's the difference between Unary, Binary and Ternary send nodes? Did you see a need to differentiate between them? They all have arrays of children, so it’s not removing the array indirection.

I rely on the argument array for Binary and Ternary because Christian suggested it, and I think, it is not supposed to make a difference. But indeed, at the moment, it is rather pointless to have the array there.
I wasn’t able to unify more of the code, so, I could remove the indirection, and make the code slightly nicer.

> Is it so that executedEvaluated can have parameters for each child and you don’t need to create an array?

Yes indeed. The main goal was to enable specialization for primitive operations.

I wanted to get the addition to be handled directly like this:

public abstract class AdditionPrim extends ArithmeticPrim {
  public AdditionPrim(final SSymbol selector, final Universe universe) { super(selector, universe); }
  public AdditionPrim(final AdditionPrim node) { this(node.selector, node.universe); }

  @Specialization(order = 1)
  public int doInteger(final int left, final int argument) {
    return left + argument;

And, in the previous design, such specialization would also have had the guard for the monomorphic send (which is here implicit, because if it is an `int`, its and `int`, no other check needed…) That way, a message send for a #+ would have ideally had as few indirection and nodes as possible. In the best case, the AdditionPrim node would really have been the direct node. And perhaps with polymorphic cases, it would have had another node in the next pointer chain.
With the new design, the polymorphic check is always down in an extra node. Which might contribute to clarity, but introduces a redundant check for this primitive. So, well, I am not extremely happy with it, but it is ok.

Back to the original question, yes, I need the distinction between the nodes to have the explicit and simple parameters here for doInteger, just two plain ints. Don’t know how reach this state with more generic code.

> I would just use an Object[] here. I used to have Unary, Binary and Ternary method calls in Ruby, but got rid of them one day and couldn’t see any performance difference when running on Graal (not just any statistically significant difference - literally no difference), with the benefit of a drastically simpler model.
Yes, the code gets ugly, and, I have a lot of code duplication that I do not like.

> I wouldn't worry about the number of nodes. Certainly having just one extra would never cross my mind as an issue. It may make interpreted performance a little better to have fewer, but really good compiled performance when you start to run on Graal relies on many minimal nodes with maximal specialisations. In Ruby lots of operations that look primitive and irreducible are made up of several nodes.

Well, not sure whether the extra indirection with the cached nodes is problematic, but at least in case of the primitive operations, the check for the monomorphic send is redundant.

> With escaping frames you mention @ExplodeLoop; you also know about @SlowPath, right?

Yes, but I don’t know how to use that properly. And what typical places should be where to use it, especially within nodes. What I already learned is that anything that returns a node should not be annotated with @SlowPath, because that prevents the partial evaluator to see the concrete return type, which leads to undesired virtual calls (causing escaping blocks).

Best regards

Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

More information about the graal-dev mailing list