Recent Truffle DSL changes.

Christian Humer christian.humer at gmail.com
Mon Aug 11 17:59:33 UTC 2014


Hi folks,

I just pushed some new features to the DSL for the upcoming Truffle
release. Please note that some of the changes may break existing Truffle
interpreters. Guest languages that don't use Truffle DSL are not affected
by this push.

Changes:

1) Specializations are now ordered in declaration order.

We have decided to make the manual definition of the specialization order
the default. Instead of the order attribute we are now using the
declaration order of the specialization method inside of the operation
class. As a result the order attribute is deprecated for this release and
will get removed in the next release.

Important: This might change the behaviour of existing Truffle
interpreters. So we encourage all guest language developers to review their
specializations to find out if the order of declaration matches the
specialization order of the operation.


2) New insertBefore attribute in @Specialization

Because there is no order attribute any longer we need to know how to order
specializations if they are declared in multiple classes of a class
hierarchy. The default behaviour is that specializations of subclasses are
appended to those of the base class. However if that is not what you want
then you can use the new insertBefore attribute in @Specialization
annotations.

See this example:

    @NodeChild("a")
    class BaseNode extends ValueNode {
        @Specialization String f1(String a) { return a;}
    }

    @NodeChild("a")
    class SubNode extends BaseNode {

        @Specialization(insertBefore = "f1")
        int f0(int a) { return a; }

        @Specialization
        double f2(double a) { return a;}

    }

This results in order f0, f1, f2 instead of f1, f0, f2 without insertBefore.


3) Better reachability check for specializations

We improved the reachability check for specializations in a way that it
prints error messages on specializations like this: "Specialization is not
reachable. It is shadowed by do2(int)".

Some specialization reachability problems that were previously not reported
are now reported.


4) Ability to declare a contains relation between specializations

Sometimes specializations contain other specializations in their
functionality. It is now possible to declare this relationship for
specializations.

See this example:

    @NodeChild("a")
     class MathAbs extends ValueNode {

        static boolean isPositive(int a) {
            return a >= 0;
        }

        @Specialization(guards = "isPositive")
        int onlyPositiveAbs(int a) {
            return a;
        }

        @Specialization(contains = "onlyPositiveAbs")
        int abs(int a) {
            return Math.abs(a);
        }
    }

Imagine now that the input values are 42 and -42. Without the contains
declaration the DSL implementation would chain the onlyPositiveAbs and the
abs specialization together. With the contains declaration the system knows
that it can remove the onlyPositiveAbs specialization if the abs
specialization is triggered. This way the operation can be represented
using a single monomorphic node again.

We also thought about making this relationship implicit. However you might
want the onlyPositiveAbs specialization not to be removed if the abs
specialization is triggered.

Specializations may contain multiple other specializations and the contains
relation can also be declared transitively. The containing specialization
must be strictly more generic as the contained specializations.


5) A new code layout

Also the generated code received some attention. We could get rid of the
generated executeGeneric0 and executeAndSpecialize0 methods which got huge
for operations with a lot of specializations.

We do not generate an explicit Generic node any longer. Instead we always
use a polymorphic chain. Using the new contains feature this polymorphic
chains can be managed in a way that they cannot get too big.

As a consequence of not generating an explicit Generic node we cannot
support the NodeFactory#createGeneric method and the @PolymorphicLimit
annotation any longer. They got removed from the API with this push.

6) Renamed @Generic to @Fallback

As promised already earlier on this list: the @Generic annotation got
renamed to a less confusing name @Fallback.

7) Experimental @Implies annotation for guards

We do not inspect the body of guard methods. Because of that we are not yet
able to infer logic relationships between guards. The new experimental
@Implies annotation provides the ability to declare logic dependencies
between guards manually.

See this example:

    @NodeChild("a")
    class MathAbs extends ValueNode {

        @Implies("isPositive")
        static boolean isZero(int a) {return a == 0;}
        static boolean isPositive(int a) {return a > 0;}

        @Specialization(guards = "isZero")
        int zero(int a) {
            return 0;
        }

        @Specialization(guards = "isPositive", contains = "zero")
        int positive(int a) {
            return a;
        }
    }

The @Implies annotation on isZero tells the DSL that isZero => isPositive.
Using this relationship the DSL can infer that the positive specialization
is strictly more generic than the zero specialization. Without this
@Implies annotation the DSL will not accept this operation as the DSL
cannot know if the positive specialization is more generic than zero
specialization.

At the moment this feature is limited to simple implies relationships. We
plan to support arbitrary expressions in the future.


As always please don't hesitate to ask questions.
If you experience problems or weird behaviour, please let me know.

Thanks!

- Christian Humer


More information about the graal-dev mailing list