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