# HG changeset patch # User Thomas Wuerthinger # Date 1426717583 -3600 # Node ID a252927dfbfdc70bb74c639e8087979c23728b02 # Parent 5ee90d1bf6cdda2149525cafb766355724566fa4 Fix an issue when the result of canonicalization is appended in the graph builder. Introduce GraphBuilderPhase#recursiveAppend. diff -r 5ee90d1bf6cd -r a252927dfbfd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Mar 18 21:36:35 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Mar 18 23:26:23 2015 +0100 @@ -847,12 +847,19 @@ protected void afterClone(@SuppressWarnings("unused") Node other) { } + public boolean verifyInputs() { + for (Node input : inputs()) { + assertFalse(input.isDeleted(), "input was deleted"); + assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); + assertTrue(input.usages().contains(this), "missing usage in input %s", input); + } + return true; + } + public boolean verify() { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); - for (Node input : inputs()) { - assertTrue(input.usages().contains(this), "missing usage in input %s", input); - } + verifyInputs(); for (Node successor : successors()) { assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor()); assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor); @@ -864,7 +871,7 @@ while (iterator.hasNext()) { Position pos = iterator.nextPosition(); if (pos.get(usage) == this && pos.getInputType() != InputType.Unchecked) { - assert isAllowedUsageType(pos.getInputType()) : "invalid input of type " + pos.getInputType() + " from " + usage + " to " + this + " (" + pos.getName() + ")"; + assertTrue(isAllowedUsageType(pos.getInputType()), "invalid input of type " + pos.getInputType() + " from " + usage + " to " + this + " (" + pos.getName() + ")"); } } } diff -r 5ee90d1bf6cd -r a252927dfbfd graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Wed Mar 18 21:36:35 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Wed Mar 18 23:26:23 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; /** @@ -60,15 +59,15 @@ boolean isIntrinsic(); } - T append(T fixed); - - T append(T fixed); + T append(T value); - T append(T fixed); - - T append(T value); - - T append(T value); + /** + * Adds the given floating node to the graph and also adds recursively all referenced inputs. + * + * @param value the floating node to be added to the graph + * @return either the node added or an equivalent node + */ + T recursiveAppend(T value); StampProvider getStampProvider(); diff -r 5ee90d1bf6cd -r a252927dfbfd graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Wed Mar 18 21:36:35 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Wed Mar 18 23:26:23 2015 +0100 @@ -1033,7 +1033,7 @@ protected abstract ValueNode appendConstant(JavaConstant constant); - protected abstract ValueNode append(ValueNode v); + protected abstract T append(T v); protected boolean isNeverExecutedCode(double probability) { return probability == 0 && optimisticOpts.removeNeverExecutedCode(); diff -r 5ee90d1bf6cd -r a252927dfbfd graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 18 21:36:35 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 18 23:26:23 2015 +0100 @@ -1444,61 +1444,41 @@ return ConstantNode.forConstant(constant, metaAccess, currentGraph); } - @SuppressWarnings("unchecked") @Override - public ValueNode append(ValueNode v) { + public T append(T v) { if (v.graph() != null) { - // This node was already appended to the graph. return v; } - if (v instanceof ControlSinkNode) { - return append((ControlSinkNode) v); - } - if (v instanceof ControlSplitNode) { - return append((ControlSplitNode) v); - } - if (v instanceof FixedWithNextNode) { - return append((FixedWithNextNode) v); + T added = currentGraph.addOrUnique(v); + if (added == v) { + updateLastInstruction(v); } - if (v instanceof FloatingNode) { - return append((FloatingNode) v); - } - throw GraalInternalError.shouldNotReachHere("Can not append Node of type: " + v.getClass().getName()); - } - - public T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = null; return added; } - public T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = null; + public T recursiveAppend(T v) { + if (v.graph() != null) { + return v; + } + T added = currentGraph.addOrUniqueWithInputs(v); + if (added == v) { + updateLastInstruction(v); + } return added; } - public T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = added; - return added; - } - - public T append(T v) { - if (v.graph() != null) { - return v; + private void updateLastInstruction(T v) { + if (v instanceof FixedNode) { + FixedNode fixedNode = (FixedNode) v; + lastInstr.setNext(fixedNode); + if (fixedNode instanceof FixedWithNextNode) { + FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; + assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; + lastInstr = fixedWithNextNode; + } else { + lastInstr = null; + } } - T added = currentGraph.unique(v); - return added; } private Target checkLoopExit(FixedNode target, BciBlock targetBlock, HIRFrameStateBuilder state) { diff -r 5ee90d1bf6cd -r a252927dfbfd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Mar 18 21:36:35 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Mar 18 23:26:23 2015 +0100 @@ -151,25 +151,25 @@ Registration r = new Registration(plugins, declaringClass); r.register1("reverseBytes", type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(kind, b.append(new ReverseBytesNode(value).canonical(null, value))); + b.push(kind, b.recursiveAppend(new ReverseBytesNode(value).canonical(null, value))); return true; } }); r.register1("bitCount", type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Int, b.append(new BitCountNode(value).canonical(null, value))); + b.push(Kind.Int, b.recursiveAppend(new BitCountNode(value).canonical(null, value))); return true; } }); r.register2("divideUnsigned", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); + b.push(kind, b.recursiveAppend(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); return true; } }); r.register2("remainderUnsigned", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode dividend, ValueNode divisor) { - b.push(kind, b.append(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); + b.push(kind, b.recursiveAppend(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); return true; } }); @@ -183,7 +183,7 @@ ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); ZeroExtendNode charCast = b.append(new ZeroExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); - b.push(Kind.Char.getStackKind(), b.append(charCast.canonical(null, value))); + b.push(Kind.Char.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } }); @@ -197,7 +197,7 @@ ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); SignExtendNode charCast = b.append(new SignExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); - b.push(Kind.Short.getStackKind(), b.append(charCast.canonical(null, value))); + b.push(Kind.Short.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } }); @@ -207,13 +207,13 @@ Registration r = new Registration(plugins, Float.class); r.register1("floatToRawIntBits", float.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Int, b.append(new ReinterpretNode(Kind.Int, value).canonical(null, value))); + b.push(Kind.Int, b.recursiveAppend(new ReinterpretNode(Kind.Int, value).canonical(null, value))); return true; } }); r.register1("intBitsToFloat", int.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Float, b.append(new ReinterpretNode(Kind.Float, value).canonical(null, value))); + b.push(Kind.Float, b.recursiveAppend(new ReinterpretNode(Kind.Float, value).canonical(null, value))); return true; } }); @@ -223,13 +223,13 @@ Registration r = new Registration(plugins, Double.class); r.register1("doubleToRawLongBits", double.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Long, b.append(new ReinterpretNode(Kind.Long, value).canonical(null, value))); + b.push(Kind.Long, b.recursiveAppend(new ReinterpretNode(Kind.Long, value).canonical(null, value))); return true; } }); r.register1("longBitsToDouble", long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Double, b.append(new ReinterpretNode(Kind.Double, value).canonical(null, value))); + b.push(Kind.Double, b.recursiveAppend(new ReinterpretNode(Kind.Double, value).canonical(null, value))); return true; } }); @@ -239,32 +239,32 @@ Registration r = new Registration(plugins, Math.class); r.register1("abs", Float.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Float, b.append(new AbsNode(value).canonical(null, value))); + b.push(Kind.Float, b.recursiveAppend(new AbsNode(value).canonical(null, value))); return true; } }); r.register1("abs", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Double, b.append(new AbsNode(value).canonical(null, value))); + b.push(Kind.Double, b.recursiveAppend(new AbsNode(value).canonical(null, value))); return true; } }); r.register1("sqrt", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Double, b.append(new SqrtNode(value).canonical(null, value))); + b.push(Kind.Double, b.recursiveAppend(new SqrtNode(value).canonical(null, value))); return true; } }); if (getAndSetEnabled(arch)) { r.register1("log", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Double, b.append(MathIntrinsicNode.create(value, LOG))); + b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG))); return true; } }); r.register1("log10", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { - b.push(Kind.Double, b.append(MathIntrinsicNode.create(value, LOG10))); + b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG10))); return true; } }); @@ -313,25 +313,25 @@ r.register2("belowOrEqual", long.class, long.class, new UnsignedMathPlugin(Condition.BE)); r.register2("divide", int.class, int.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { - b.push(Kind.Int, b.append(new UnsignedDivNode(x, y).canonical(null, x, y))); + b.push(Kind.Int, b.recursiveAppend(new UnsignedDivNode(x, y).canonical(null, x, y))); return true; } }); r.register2("divide", long.class, long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { - b.push(Kind.Long, b.append(new UnsignedDivNode(x, y).canonical(null, x, y))); + b.push(Kind.Long, b.recursiveAppend(new UnsignedDivNode(x, y).canonical(null, x, y))); return true; } }); r.register2("remainder", int.class, int.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { - b.push(Kind.Int, b.append(new UnsignedRemNode(x, y).canonical(null, x, y))); + b.push(Kind.Int, b.recursiveAppend(new UnsignedRemNode(x, y).canonical(null, x, y))); return true; } }); r.register2("remainder", long.class, long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { - b.push(Kind.Long, b.append(new UnsignedRemNode(x, y).canonical(null, x, y))); + b.push(Kind.Long, b.recursiveAppend(new UnsignedRemNode(x, y).canonical(null, x, y))); return true; } }); @@ -366,14 +366,14 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode type, ValueNode object) { ValueNode nullCheckedType = nullCheckedValue(b, type); LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getConstantReflection(), nullCheckedType, object)); - b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null))); + b.push(Kind.Boolean.getStackKind(), b.recursiveAppend(new ConditionalNode(condition).canonical(null))); return true; } }); r.register2("isAssignableFrom", Receiver.class, Class.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode type, ValueNode otherType) { - ClassIsAssignableFromNode condition = b.append(new ClassIsAssignableFromNode(nullCheckedValue(b, type), otherType)); - b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null))); + ClassIsAssignableFromNode condition = b.recursiveAppend(new ClassIsAssignableFromNode(nullCheckedValue(b, type), otherType)); + b.push(Kind.Boolean.getStackKind(), b.recursiveAppend(new ConditionalNode(condition).canonical(null))); return true; } });