Truffle: [TypeSystemCodeGenerator + ShortCircuit] generate a buggy code

Mohaned Y Qunaibit mqunaibi at uci.edu
Fri Jun 5 07:19:50 UTC 2015


Hi,

When we have a binary node that doesn't always execute both nodes, (like
AND, OR), TypeSystemCodeGenerator generate a type specialized node but with
the assumption that it can read both two children types.
Example:
Evaluate: "2 or 0"

    @NodeInfo(shortName = "or")
    @GenerateNodeFactory
    public abstract static class OrNode extends BinaryOpNode {

        @Child protected YesNode booleanCast;
        public OrNode() {
            this.booleanCast = YesNodeFactory.create(EmptyNode.create());
        }

        @ShortCircuit("rightNode")
        public boolean needsRightNode(VirtualFrame frame, Object left) {
            return !booleanCast.executeBoolean(frame, left);
        }

        @Specialization(order = 0)
        public boolean doBoolean(boolean left, boolean needsRight, boolean
right) {
            return needsRight ? right : left;
        }

        @Specialization(order = 1)
        public int doInteger(int left, boolean needsRight, int right) {
            return needsRight ? right : left;
        }

    }

Generated node:

        @GeneratedBy(OrNode.class)
        public static final class OrNodeGen extends OrNode implements
SpecializedNode {
        ...
                public Object execute(VirtualFrame frameValue) {
                    Object leftNodeValue_ = executeLeftNode_(frameValue);
                    boolean hasRightNodeValue =
root.needsRightNode(frameValue, leftNodeValue_); // return false
                    Object *rightNodeValue_ = null*;
                    if (hasRightNodeValue) {
                        rightNodeValue_ = executeRightNode_(frameValue);
                    }
                    return execute_(frameValue, leftNodeValue_,
hasRightNodeValue, *rightNodeValue_*);
                }

            ...
            @GeneratedBy(methodName = "doInteger(int, boolean, int)", value
= OrNode.class)
            private static final class IntegerNode_ extends BaseNode_ {

                private final Class<?> leftNodeImplicitType;
                private final Class<?> rightNodeImplicitType;

                IntegerNode_(OrNodeGen root, Object leftNodeValue, Object
*rightNodeValue*) { // rightNodeValue = null
                    super(root, 2);
                    this.leftNodeImplicitType =
LanguageTypesGen.getImplicitIntegerClass(leftNodeValue);
                    this.rightNodeImplicitType =
*LanguageTypesGen.getImplicitIntegerClass(rightNodeValue);
// Throws exception*
                }
                ...
            }
        ...
        }

Here after the executing of the uninitialized node, *rightNodeValue_* will
carry a *null* value all the way until it gets replaced with
*IntegerNode_* which
will call *getImplicitIntegerClass* and throw an exception because of the
*null* value.

The suggested fix:
TypeSystemCodeGenerator.java:53
-        builder.startStaticCall(createTypeSystemGen(typeSystem),
getImplicitClass(typeSystem,
type)).tree(value);
*+        builder.startParantheses().tree(value).string(" ==
").nullLiteral().end().string(" ? ").nullLiteral().string(" : ")*
*+
  .startStaticCall(createTypeSystemGen(typeSystem),
getImplicitClass(typeSystem,
type)).tree(value);*



Best,
Mohaned Qunaibit


More information about the graal-dev mailing list