Implict Casts in Truffle DSL

Wei Zhang ndrzmansn at gmail.com
Thu Apr 3 00:20:46 UTC 2014


Hi Christian,

A generated node using @ImplicitCast rewrites itself with the minimunState
value of itself.
This value prevents a node re-specialization to the same type but with a
promoted operand type.

Say a SLMulBigIntegerNode has a long operand and a BigInteger operand.
At some point, the long operand become a BigInteger, and the node starts to
rewrite.
It should replace itself with another SLMulBigIntegerNode but with updated
operand implicit types.

I hope that make sense to you.
I suggest to just decrease the minimumState value by 1, but you might have
better solutions.

Thanks,


/Wei


On Wed, Apr 2, 2014 at 3:46 PM, Christian Humer
<christian.humer at gmail.com>wrote:

> Unfortunately you have to specify all transitive implicit casts. That
> gives you more control, but is also more verbose. Let me know if the number
> of casts explodes. If so we could add a feature for that.
>
> (Sent using Android)
> Am 02.04.2014 23:27 schrieb "Wei Zhang" <ndrzmansn at gmail.com>:
>
> Thanks for the patch. It works nicely!
>>
>> Yes, I'm planning to simplify the uses of @TypeCheck and @TypeCast, and
>> use @ImplicitCast instead for most of the cases.
>> However, I have a further question on that.
>> To implement multiple levels of implicit type coercions, e.g., from bool
>> to int and then to double, do I have to specify all possible conversions
>> separately?
>> Or can the generated code chain more than one @ImplicitCasts together to
>> convert a bool directly to double?
>>
>> Thanks,
>>
>> /Wei
>>
>>
>> On Wed, Apr 2, 2014 at 8:50 AM, Christian Humer <
>> christian.humer at gmail.com> wrote:
>>
>>> Ups that was too quick. Forget my previous patch and use the one below
>>> instead. In principle the DSL supports execute methods without a
>>> VirtualFrame parameter. However there are some glitches here and there. So
>>> please try to avoid them for now and always add a VirtualFrame parameter to
>>> execute methods.
>>>
>>> diff -r ed373ed4b717
>>> graal/edu.uci.python.nodes/src/edu/uci/python/nodes/expression/CastToBooleanNode.java
>>> ---
>>> a/graal/edu.uci.python.nodes/src/edu/uci/python/nodes/expression/CastToBooleanNode.java Wed
>>> Apr 02 00:06:40 2014 -0700
>>> +++
>>> b/graal/edu.uci.python.nodes/src/edu/uci/python/nodes/expression/CastToBooleanNode.java Wed
>>> Apr 02 17:47:21 2014 +0200
>>> @@ -40,7 +40,7 @@
>>>
>>>  public abstract class CastToBooleanNode extends UnaryOpNode {
>>>
>>> -    public abstract boolean executeBoolean(Object value);
>>> +    public abstract boolean executeBoolean(VirtualFrame frame, Object
>>> value);
>>>
>>>      @Override
>>>      public abstract boolean executeBoolean(VirtualFrame frame);
>>>
>>>
>>>
>>>
>>>
>>>
>>> - Christian Humer
>>>
>>>
>>> On Wed, Apr 2, 2014 at 4:43 PM, Christian Humer <
>>> christian.humer at gmail.com> wrote:
>>>
>>>> Hi Wei,
>>>>
>>>> You found a bug. Thanks for the report. In the future don't hesitate to
>>>> send a report even if you are not sure if it is already fixed. Here is a
>>>> temporary patch for you. I will push this fix with my next greater push to
>>>> openjdk.
>>>>
>>>> BTW.: you should get rid of your overly complicated @TypeCheck and
>>>> @TypeCast implementations in the type system. There may be a major
>>>> performance problem hidden here. Ideally you should only use the ones that
>>>> are generated by default. I think you can get rid of them mostly by using
>>>> ImplicitCasts. But maybe that's the thing you wanted to do anyway. Feel
>>>> free to contact me again if you need help with that.
>>>>
>>>> diff -r ed373ed4b717
>>>> graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java
>>>> ---
>>>> a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed
>>>> Apr 02 00:06:40 2014 -0700
>>>> +++
>>>> b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed
>>>> Apr 02 16:34:32 2014 +0200
>>>> @@ -2032,7 +2032,11 @@
>>>>
>>>>              CodeExecutableElement method = new
>>>> CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC :
>>>> FINAL), param.getType(), childExecuteName);
>>>>
>>>>  method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
>>>> -            method.addParameter(new
>>>> CodeVariableElement(getContext().getTruffleTypes().getFrame(),
>>>> "frameValue"));
>>>> +
>>>> +            if (expectType == null) {
>>>> +                method.addParameter(new
>>>> CodeVariableElement(getContext().getTruffleTypes().getFrame(),
>>>> "frameValue"));
>>>> +            }
>>>> +
>>>>              if (expectType != null) {
>>>>                  method.addParameter(new
>>>> CodeVariableElement(expectType.getPrimitiveType(),
>>>> valueNameEvaluated(param)));
>>>>              }
>>>>
>>>>
>>>> - Christian Humer
>>>>
>>>>
>>>> On Tue, Apr 1, 2014 at 10:10 PM, Wei Zhang <ndrzmansn at gmail.com> wrote:
>>>>
>>>>> Hi Christian,
>>>>>
>>>>> I'm experiencing a problem when using @ImplicitCast.
>>>>>
>>>>> I added the following code in PythonTypes.java:
>>>>>
>>>>> @ImplicitCast
>>>>> public String unboxPString(PString value) {
>>>>>       return value.getValue();
>>>>> }
>>>>>
>>>>> This use causes a javac error in the generated
>>>>> CastToBooleanNodeFactory.java.
>>>>>
>>>>> You can pull the latest change from ZipPy to reproduce this.
>>>>> I've commented the use of @ImplicitCast in PythonTypes.
>>>>> I did not report this problem earlier because I have not merge with
>>>>> the Graal repo for a while and expected that it might be fixed in a recent
>>>>> commit.
>>>>>
>>>>> Any suggestion?
>>>>> Thanks,
>>>>>
>>>>> /Wei
>>>>>
>>>>>
>>>>> On Sat, Dec 21, 2013 at 8:49 AM, Christian Humer <
>>>>> christian.humer at gmail.com> wrote:
>>>>>
>>>>>> Hey folks,
>>>>>>
>>>>>> There were some questions floating around about the ImplicitCast
>>>>>> feature in Truffle DSL.
>>>>>> So here is a short description of what it does:
>>>>>>
>>>>>> The idea behind ImplicitCasts is that it tries to reduce the number
>>>>>> of specializations required to define an operation. Imagine you got
>>>>>> arithmetics with tree different types. That could be int, double and
>>>>>> complex. However in our guest language we have several different
>>>>>> representations of the same type for optimization reasons. For instance an
>>>>>> int could be represented as Java int, IntSequence, IntVector or even as
>>>>>> LogicalToIntVectorClosure (this example is borrowed from R).
>>>>>> This makes a lot of combinations of types in binary operation to
>>>>>> fully specialize itself. So assuming that double and complex have the same
>>>>>> number of different representations and their number may even rise, the
>>>>>> number of specializations will explode at some point in time.
>>>>>> The solution for this problem was to introduce a new concept to the
>>>>>> DSL, namely @ImplicitCast. The idea behind is that you can define
>>>>>> casts that are inserted before a specialization is called on demand.
>>>>>>
>>>>>> So assume we have defined the specializations for a binary operation
>>>>>> which fully specializes for the types int and IntVector. Without
>>>>>> implicit casts you would have to define these four specializations.
>>>>>>
>>>>>> @Specialization int doOp(int left, int right) {...}
>>>>>> @Specialization int doOp(IntVector left, int right) {...}
>>>>>> @Specialization int doOp(int left, IntVector right) {...}
>>>>>> @Specialization int doOp(IntVector left, IntVector right) {...}
>>>>>>
>>>>>> However if we assume that all four specializations would want to
>>>>>> specialize to basically the same code we can use implicit casts to
>>>>>> declare this more elegantly. For this we introduce a new interface called
>>>>>> AbstractIntVector which is the base interface for IntVector, IntSequence
>>>>>> etc. and we have to define some implicit casts in the type system
>>>>>> like this:
>>>>>>
>>>>>>     @ImplicitCast
>>>>>>     public AbstractIntVector toAbstractIntVector(int value) {
>>>>>>         return DataFactory.createIntVectorFromScalar(value);
>>>>>>     }
>>>>>>     @ImplicitCast
>>>>>>     public AbstractIntVector toAbstractIntVector(IntVector vector) {
>>>>>>         return vector;
>>>>>>     }
>>>>>>
>>>>>>
>>>>>> @Specialization int
>>>>>> doOp(AbstractIntVector left, AbstractIntVector right) {...}
>>>>>>
>>>>>> Now we can just define one specialization and we get the same
>>>>>> specialization combinations as in the first example. Please be aware that
>>>>>> this is not completely the same thing as before since the implicit
>>>>>> cast method toAbstractIntVector is invoked prior to the invocation
>>>>>> of the specialization. However Graal/Truffle is pretty good in removing
>>>>>> unnecessary allocations for boxing if it sees the position of boxing as
>>>>>> well as the position of the unboxing.
>>>>>>
>>>>>> You may even combine both the upper with the lower approach, like
>>>>>> this:
>>>>>>
>>>>>> @Specialization int doOp(int left, int right) {...}
>>>>>> @Specialization int
>>>>>> doOp(AbstractIntVector left, AbstractIntVector right) {...}
>>>>>>
>>>>>> In this case you can provide a more optimized version for (int, int)
>>>>>> but not having to specialize all the other combinations. Implicit
>>>>>> casts are even more useful if the number of representations of the
>>>>>> same logical type is high. This enables you to keep the number of
>>>>>> specializations in binary nodes under control without breaking your
>>>>>> fingers.
>>>>>>
>>>>>> Please note: On the contrary to custom @TypeCheck and @TypeCast
>>>>>> methods, @ImplicitCasts are inserted on-demand. This means that they do not
>>>>>> introduce additional overhead in compiled code as custom @TypeCheck or
>>>>>> @TypeCast methods would.
>>>>>>
>>>>>> Feel free to ask further questions.
>>>>>>
>>>>>> - Christian Humer
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>


More information about the graal-dev mailing list