# HG changeset patch # User Doug Simon # Date 1342445046 -7200 # Node ID a9ce56ad1860e2695396b2499f76d20697a52d14 # Parent f84d11672a869a1c5b7af23ed7ca9077f24c3dd8# Parent 610f9e377c70d2e74a63cb78a7c31accf72b8bbb Merge. diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jul 16 15:24:06 2012 +0200 @@ -199,9 +199,6 @@ if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - } if (GraalOptions.OptLoopTransform) { new LoopTransformLowPhase().apply(graph); diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingRead2Phase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingRead2Phase.java Mon Jul 16 15:24:06 2012 +0200 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import java.util.*; + +import com.oracle.graal.compiler.graph.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.extended.*; + +public class FloatingRead2Phase extends Phase { + + private IdentityHashMap> loopEndStatesMap; + + private static class LoopState { + public LoopBeginNode loopBegin; + public MemoryMap state; + public IdentityHashMap loopPhiLocations = new IdentityHashMap<>(); + public ValueNode loopEntryAnyLocation; + public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) { + this.loopBegin = loopBegin; + this.state = state; + this.loopEntryAnyLocation = loopEntryAnyLocation; + } + } + + private class MemoryMap implements MergeableState { + private IdentityHashMap lastMemorySnapshot; + private LinkedList loops; + + public MemoryMap(MemoryMap memoryMap) { + lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); + loops = new LinkedList<>(memoryMap.loops); + } + + public MemoryMap() { + lastMemorySnapshot = new IdentityHashMap<>(); + loops = new LinkedList<>(); + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + if (withStates.size() == 0) { + return true; + } + Debug.log("Merge with %s", lastMemorySnapshot); + IdentityHashMap visitedKeys = new IdentityHashMap<>(); + for (MemoryMap other : withStates) { + Debug.log(" other: %s", other.lastMemorySnapshot); + for (Map.Entry entry : lastMemorySnapshot.entrySet()) { + Object key = entry.getKey(); + visitedKeys.put(key, key); + ValueNode localNode = entry.getValue(); + ValueNode otherNode = other.lastMemorySnapshot.get(key); + if (otherNode == null) { + otherNode = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + } + assert localNode != null; + if (localNode != otherNode && !merge.isPhiAtMerge(localNode)) { + PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge)); + phi.addInput(localNode); + lastMemorySnapshot.put(key, phi); + } + } + } + for (Map.Entry entry : lastMemorySnapshot.entrySet()) { + ValueNode localNode = entry.getValue(); + PhiNode phi = null; + if (merge.isPhiAtMerge(localNode)) { + phi = (PhiNode) localNode; + } else if (!visitedKeys.containsKey(entry.getKey())) { + phi = merge.graph().add(new PhiNode(PhiType.Memory, merge)); + phi.addInput(localNode); + lastMemorySnapshot.put(entry.getKey(), phi); + } + if (phi != null) { + Debug.log("Phi @ %s for %s", merge, entry.getKey()); + for (MemoryMap other : withStates) { + ValueNode otherNode = other.lastMemorySnapshot.get(entry.getKey()); + if (otherNode == null) { + otherNode = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + } + assert otherNode != null; + phi.addInput(otherNode); + } + } + } + return true; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION)); + for (Map.Entry entry : lastMemorySnapshot.entrySet()) { + PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin)); + phi.addInput(entry.getValue()); + entry.setValue(phi); + loopState.loopPhiLocations.put(phi, entry.getKey()); + } + loops.push(loopState); + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { + loopEndStatesMap.put(loopBegin, loopEndStates); + tryFinishLoopPhis(this, loopBegin); + } + + @Override + public void afterSplit(FixedNode node) { + // nothing + } + + @Override + public MemoryMap clone() { + return new MemoryMap(this); + } + } + + @Override + protected void run(StructuredGraph graph) { + loopEndStatesMap = new IdentityHashMap<>(); + new PostOrderNodeIterator(graph.start(), new MemoryMap()) { + @Override + protected void node(FixedNode node) { + processNode(node, state); + } + }.apply(); + } + + private void processNode(FixedNode node, MemoryMap state) { + if (node instanceof ReadNode) { + processRead((ReadNode) node, state); + } else if (node instanceof WriteNode) { + processWrite((WriteNode) node, state); + } else if (node instanceof MemoryCheckpoint) { + processCheckpoint((MemoryCheckpoint) node, state); + } else if (node instanceof LoopExitNode) { + processLoopExit((LoopExitNode) node, state); + } + } + + private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { + for (Map.Entry entry : state.lastMemorySnapshot.entrySet()) { + entry.setValue((ValueNode) checkpoint); + } + state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, (ValueNode) checkpoint); + } + + private static void processWrite(WriteNode writeNode, MemoryMap state) { + if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) { + state.lastMemorySnapshot.clear(); + } + state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode); + } + + private void processRead(ReadNode readNode, MemoryMap state) { + StructuredGraph graph = (StructuredGraph) readNode.graph(); + assert readNode.getNullCheck() == false; + Object locationIdentity = readNode.location().locationIdentity(); + ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity); + FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies())); + floatingRead.setNullCheck(readNode.getNullCheck()); + ValueAnchorNode anchor = null; + for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) { + if (anchor == null) { + anchor = graph.add(new ValueAnchorNode()); + } + anchor.addAnchoredNode(guard); + } + if (anchor != null) { + graph.addAfterFixed(readNode, anchor); + } + graph.replaceFixedWithFloating(readNode, floatingRead); + } + + private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) { + ValueNode lastLocationAccess; + if (locationIdentity == LocationNode.FINAL_LOCATION) { + lastLocationAccess = null; + } else { + lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity); + if (lastLocationAccess == null) { + LoopState lastLoop = state.loops.peek(); + if (lastLoop == null) { + lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + Debug.log("getLastLocationAccessForRead(%s, %s) -> unknown, not in a loop : %s", state, locationIdentity, lastLocationAccess); + } else { + ValueNode phiInit; + if (state.loops.size() > 1) { + Debug.log("getLastLocationAccessForRead(%s, %s) -> unknown, in a non-outtermost loop, getting state in 2nd loop", state, locationIdentity); + phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity); + } else { + phiInit = lastLoop.loopEntryAnyLocation; + Debug.log("getLastLocationAccessForRead(%s, %s) -> unknown, in a outtermost loop : Phi(%s,...)", state, locationIdentity, phiInit); + } + PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin)); + phi.addInput(phiInit); + lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi); + lastLoop.loopPhiLocations.put(phi, locationIdentity); + tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin); + lastLocationAccess = phi; + } + state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess); + } else { + Debug.log("getLastLocationAccessForRead(%s, %s) -> directly : %s", state, locationIdentity, lastLocationAccess); + } + } + return lastLocationAccess; + } + + private static void processLoopExit(LoopExitNode exit, MemoryMap state) { + for (Map.Entry entry : state.lastMemorySnapshot.entrySet()) { + entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory))); + } + LoopState poped = state.loops.pop(); + assert poped.loopBegin == exit.loopBegin(); + } + + private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) { + List loopEndStates = loopEndStatesMap.get(loopBegin); + if (loopEndStates == null) { + return; + } + LoopState loopState = loopMemory.loops.get(0); + int i = 0; + while (loopState.loopBegin != loopBegin) { + loopState = loopMemory.loops.get(++i); + } + for (PhiNode phi : loopBegin.phis()) { + if (phi.type() == PhiType.Memory && phi.valueCount() == 1) { + Object location = loopState.loopPhiLocations.get(phi); + assert location != null : "unknown location for " + phi; + for (MemoryMap endState : loopEndStates) { + ValueNode otherNode = endState.lastMemorySnapshot.get(location); + if (otherNode == null) { + otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + } + phi.addInput(otherNode); + } + } + } + } +} diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java Mon Jul 16 15:24:06 2012 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.extended.*; public class ReadEliminationPhase extends Phase { @@ -39,20 +38,11 @@ for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) { if (isReadEliminable(n)) { NodeMap nodeMap = n.graph().createNodeMap(); - ValueNode value = getValue(n.lastLocationAccess(), nodeMap); + ValueNode value = getValue(n, n.lastLocationAccess(), nodeMap); Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value); graph.replaceFloating(n, value); } } - // get a proper stamp for the new phis - while (!newPhis.isEmpty()) { - PhiNode phi = newPhis.poll(); - if (phi.inferStamp()) { - for (PhiNode usagePhi : phi.usages().filter(PhiNode.class)) { - newPhis.add(usagePhi); - } - } - } } private boolean isReadEliminable(FloatingReadNode n) { @@ -82,7 +72,7 @@ return false; } - private ValueNode getValue(Node lastLocationAccess, NodeMap nodeMap) { + private ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap nodeMap) { ValueNode exisiting = nodeMap.get(lastLocationAccess); if (exisiting != null) { return exisiting; @@ -92,10 +82,10 @@ } if (lastLocationAccess instanceof PhiNode) { PhiNode phi = (PhiNode) lastLocationAccess; - PhiNode newPhi = phi.graph().add(new PhiNode(PhiType.Value, phi.merge())); + PhiNode newPhi = phi.graph().add(new PhiNode(n.kind(), phi.merge())); nodeMap.set(lastLocationAccess, newPhi); for (ValueNode value : phi.values()) { - newPhi.addInput(getValue(value, nodeMap)); + newPhi.addInput(getValue(n, value, nodeMap)); } newPhis.add(newPhi); return newPhi; diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 16 15:24:06 2012 +0200 @@ -291,7 +291,7 @@ graph.replaceFixedWithFixed(storeField, memoryWrite); FixedWithNextNode last = memoryWrite; - if (field.kind() == Kind.Object && !memoryWrite.value().isNullConstant()) { + if (field.kind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) { FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object())); graph.addAfterFixed(memoryWrite, writeBarrier); last = writeBarrier; @@ -306,7 +306,7 @@ // Separate out GC barrier semantics CompareAndSwapNode cas = (CompareAndSwapNode) n; ValueNode expected = cas.expected(); - if (expected.kind() == Kind.Object && !cas.newValue().isNullConstant()) { + if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) { ResolvedJavaType type = cas.object().objectStamp().type(); if (type != null && !type.isArrayClass() && type.toJava() != Object.class) { // Use a field write barrier since it's not an array store @@ -337,7 +337,7 @@ ValueNode value = storeIndexed.value(); CheckCastNode checkcast = null; ValueNode array = storeIndexed.array(); - if (elementKind == Kind.Object && !value.isNullConstant()) { + if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) { // Store check! ResolvedJavaType arrayType = array.objectStamp().type(); if (arrayType != null && array.objectStamp().isExactType()) { @@ -366,7 +366,7 @@ graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - if (elementKind == Kind.Object && !value.isNullConstant()) { + if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) { graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); } } else if (n instanceof UnsafeLoadNode) { @@ -385,7 +385,7 @@ WriteNode write = graph.add(new WriteNode(object, store.value(), location)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); - if (write.value().kind() == Kind.Object && !write.value().isNullConstant()) { + if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) { ResolvedJavaType type = object.objectStamp().type(); WriteBarrier writeBarrier; if (type != null && !type.isArrayClass() && type.toJava() != Object.class) { diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java Mon Jul 16 15:24:06 2012 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.micro; + +import org.junit.*; + + +public class FloatingReads { + public static long init = Runtime.getRuntime().totalMemory(); + private final int f = 10; + private int a; + private int b; + private int c; + + public int test(int d) { + a = 3; + b = 5; + c = 7; + for (int i = 0; i < d; i++) { + if (i % 2 == 0) { + a += b; + } + if (i % 4 == 0) { + b += c; + } else if (i % 3 == 0) { + b -= a; + } + if (i % 5 == 0) { + for (int j = 0; j < i; j++) { + c += a; + } + a -= f; + } + b = a ^ c; + if (i % 6 == 0) { + c--; + } else if (i % 7 == 0) { + Runtime.getRuntime().totalMemory(); + } + } + return a + b + c; + } + + @Test + public void run0() { + Assert.assertEquals(-42, test(10)); + } + + @Test + public void run1() { + Assert.assertEquals(2147465134, test(1000)); + } + + @Test + public void run2() { + Assert.assertEquals(-3, test(1)); + } + + @Test + public void run3() { + Assert.assertEquals(15, test(0)); + } +} diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Jul 16 15:24:06 2012 +0200 @@ -30,8 +30,10 @@ */ @SuppressWarnings("unused") public class Conditional01 { - private static final int RAM_SIZE = 0x100; + private static final int init = new Random().nextInt(); + private static final int init1 = new Register().val; + private static final Register init2 = new CPC().r1; public static int test(int arg) { Conditional01 c = new Conditional01(); diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -71,6 +71,7 @@ } else { // This begin node can be removed and all guards moved up to the preceding begin node. prepareDelete(); + tool.addToWorkList(next()); ((StructuredGraph) graph()).removeFixed(this); } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -36,7 +36,7 @@ public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType { public static enum PhiType { - Value(StampFactory.top()), // normal value phis + Value(null), // normal value phis Memory(StampFactory.dependency()); public final Stamp stamp; @@ -62,9 +62,7 @@ } /** - * Create a phi with the specified {@link PhiType}. - * If you use this to create a {@link PhiType#Value value} phi, its {@link Kind kind} will originally be {@link Kind#Void void} ; - * use {@link PhiNode#inferStamp()} to update it when it has valid inputs. + * Create a non-value phi ({@link PhiType#Memory} with the specified kind. * @param type the type of the new phi * @param merge the merge that the new phi belongs to */ diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -50,4 +50,17 @@ public void generate(LIRGeneratorTool generator) { generator.setResult(this, generator.operand(object)); } + + @Override + public boolean inferStamp() { + if (object().stamp().nonNull() && !stamp().nonNull()) { + setStamp(StampFactory.declaredNonNull(objectStamp().type())); + return true; + } + if (object().objectStamp().alwaysNull() && !objectStamp().alwaysNull()) { + setStamp(StampFactory.alwaysNull()); + return true; + } + return super.inferStamp(); + } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -22,9 +22,11 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.nodes.extended.*; + /** * The start node of a graph. */ -public class StartNode extends BeginStateSplitNode { +public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint{ } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -58,9 +58,9 @@ return ConstantNode.forBoolean(true, graph()); } - if (x().isNullConstant()) { + if (x().objectStamp().alwaysNull()) { return graph().unique(new IsNullNode(y())); - } else if (y().isNullConstant()) { + } else if (y().objectStamp().alwaysNull()) { return graph().unique(new IsNullNode(x())); } if (x().stamp().alwaysDistinct(y().stamp())) { diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Mon Jul 16 15:24:06 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; public interface Access { @@ -31,4 +32,6 @@ LocationNode location(); void setNullCheck(boolean check); + + Node node(); } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -57,4 +58,9 @@ this.object = object; this.location = location; } + + @Override + public Node node() { + return this; + } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -67,4 +68,9 @@ this.object = object; this.location = location; } + + @Override + public Node node() { + return this; + } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,7 +33,7 @@ * A floating read of a value from memory specified in terms of an object base and an object relative location. * This node does not null check the object. */ -public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { +public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable/*, Canonicalizable*/ { @Input private Node lastLocationAccess; @@ -57,20 +56,9 @@ gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck())); } - @Override + // Canonicalization disabled untill we have a solution for non-Object oops in Hotspot + /*@Override public ValueNode canonical(CanonicalizerTool tool) { - MetaAccessProvider runtime = tool.runtime(); - if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) { - if (this.location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) { - Object value = object().asConstant().asObject(); - long displacement = location().displacement(); - Kind kind = location().kind(); - Constant constant = kind.readUnsafeConstant(value, displacement); - if (constant != null) { - return ConstantNode.forConstant(constant, runtime, graph()); - } - } - } - return this; - } + return ReadNode.canonicalizeRead(this, tool); + }*/ } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -31,7 +31,7 @@ /** * Reads an {@linkplain AccessNode accessed} value. */ -public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { +public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable/*, Canonicalizable*/ { public ReadNode(ValueNode object, LocationNode location, Stamp stamp) { super(object, location, stamp); @@ -42,20 +42,26 @@ gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck())); } - @Override + // Canonicalization disabled untill we have a solution for non-Object oops in Hotspot + /*@Override public ValueNode canonical(CanonicalizerTool tool) { + return canonicalizeRead(this, tool); + }*/ + + public static ValueNode canonicalizeRead(Access read, CanonicalizerTool tool) { MetaAccessProvider runtime = tool.runtime(); - if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) { - if (location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) { - Object value = object().asConstant().asObject(); - long displacement = location().displacement(); - Kind kind = location().kind(); + if (runtime != null && read.object() != null && read.object().isConstant() && read.object().kind() == Kind.Object) { + if (read.location().locationIdentity() == LocationNode.FINAL_LOCATION && read.location().getClass() == LocationNode.class) { + Object value = read.object().asConstant().asObject(); + long displacement = read.location().displacement(); + Kind kind = read.location().getValueKind(); Constant constant = kind.readUnsafeConstant(value, displacement); if (constant != null) { - return ConstantNode.forConstant(constant, runtime, graph()); + System.out.println("Canon read to " + constant); + return ConstantNode.forConstant(constant, runtime, read.node().graph()); } } } - return this; + return (ValueNode) read; } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -41,7 +41,7 @@ } public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { - super(toType.kind().isObject() ? new ObjectStamp(toType, exactType, nonNull) : StampFactory.forKind(toType.kind())); + super(toType.kind().isObject() ? new ObjectStamp(toType, exactType, nonNull, false) : StampFactory.forKind(toType.kind())); this.object = object; this.toType = toType; } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -51,7 +51,7 @@ } public CheckCastNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object, JavaTypeProfile profile) { - super(targetClass == null ? StampFactory.forKind(Kind.Object) : StampFactory.declared(targetClass)); + super(targetClass == null ? StampFactory.object() : StampFactory.declared(targetClass)); this.targetClassInstruction = targetClassInstruction; this.targetClass = targetClass; this.object = object; @@ -69,6 +69,15 @@ } @Override + public boolean inferStamp() { + if (object().stamp().nonNull() && !stamp().nonNull()) { + setStamp(targetClass == null ? StampFactory.objectNonNull() : StampFactory.declaredNonNull(targetClass)); + return true; + } + return super.inferStamp(); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { assert object() != null : this; @@ -80,12 +89,8 @@ } } - Constant constant = object().asConstant(); - if (constant != null) { - assert constant.kind == Kind.Object; - if (constant.isNull()) { - return object(); - } + if (object().objectStamp().alwaysNull()) { + return object(); } return this; } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -103,15 +103,8 @@ // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time... } } - - Constant constant = object().asConstant(); - if (constant != null) { - assert constant.kind == Kind.Object; - if (constant.isNull()) { - return ConstantNode.forBoolean(false, graph()); - } else { - assert false : "non-null constants are always expected to provide an exact type"; - } + if (object().objectStamp().alwaysNull()) { + return ConstantNode.forBoolean(false, graph()); } return this; } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Mon Jul 16 15:24:06 2012 +0200 @@ -91,9 +91,6 @@ @Override public Stamp meet(Stamp otherStamp) { - if (otherStamp == StampFactory.top()) { - return this; - } FloatStamp other = (FloatStamp) otherStamp; assert kind() == other.kind(); double meetUpperBound = Math.max(upperBound, other.upperBound); diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Mon Jul 16 15:24:06 2012 +0200 @@ -53,9 +53,6 @@ @Override public Stamp meet(Stamp other) { - if (other == StampFactory.top()) { - return this; - } assert ((GenericStamp) other).type == type; return this; } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jul 16 15:24:06 2012 +0200 @@ -104,9 +104,6 @@ @Override public Stamp meet(Stamp otherStamp) { - if (otherStamp == StampFactory.top()) { - return this; - } IntegerStamp other = (IntegerStamp) otherStamp; assert kind() == other.kind(); long meetUpperBound = Math.max(upperBound, other.upperBound); diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Mon Jul 16 15:24:06 2012 +0200 @@ -30,13 +30,16 @@ private final ResolvedJavaType type; private final boolean exactType; private final boolean nonNull; + private final boolean alwaysNull; - public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull) { + public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { super(Kind.Object); assert !exactType || type != null; + assert !(nonNull && alwaysNull); this.type = type; this.exactType = exactType; this.nonNull = nonNull; + this.alwaysNull = alwaysNull; } @Override @@ -44,6 +47,10 @@ return nonNull; } + public boolean alwaysNull() { + return alwaysNull; + } + public ResolvedJavaType type() { return type; } @@ -56,13 +63,16 @@ public String toString() { StringBuilder str = new StringBuilder(); str.append(kind().typeChar); - str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.name()); + str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.name()).append(alwaysNull ? " NULL" : ""); return str.toString(); } @Override public boolean alwaysDistinct(Stamp otherStamp) { ObjectStamp other = (ObjectStamp) otherStamp; + if ((alwaysNull && other.nonNull) || (nonNull && other.alwaysNull)) { + return true; + } if (other.type == null || type == null) { // We have no type information for one of the values. return false; @@ -75,18 +85,32 @@ @Override public Stamp meet(Stamp otherStamp) { - if (otherStamp == StampFactory.top()) { - return this; + ObjectStamp other = (ObjectStamp) otherStamp; + ResolvedJavaType meetType; + boolean meetExactType; + boolean meetNonNull; + boolean meetAlwaysNull; + if (other.alwaysNull) { + meetType = type(); + meetExactType = exactType; + meetNonNull = false; + meetAlwaysNull = alwaysNull; + } else if (alwaysNull) { + meetType = other.type(); + meetExactType = other.exactType; + meetNonNull = false; + meetAlwaysNull = other.alwaysNull; + } else { + meetType = meetTypes(type(), other.type()); + meetExactType = meetType == type && meetType == other.type && exactType && other.exactType; + meetNonNull = nonNull && other.nonNull; + meetAlwaysNull = false; } - ObjectStamp other = (ObjectStamp) otherStamp; - ResolvedJavaType orType = meetTypes(type(), other.type()); - boolean meetExactType = orType == type && orType == other.type && exactType && other.exactType; - boolean meetNonNull = nonNull && other.nonNull; - if (orType == type && meetExactType == exactType && meetNonNull == nonNull) { + if (meetType == type && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) { return this; } else { - return new ObjectStamp(orType, meetExactType, meetNonNull); + return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull); } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jul 16 15:24:06 2012 +0200 @@ -28,10 +28,10 @@ public class StampFactory { - private static final TopStamp top = new TopStamp(); private static final Stamp[] stampCache = new Stamp[Kind.values().length]; - private static final Stamp objectStamp = new ObjectStamp(null, false, false); - private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true); + private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); + private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); + private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); private static final Stamp dependencyStamp = new GenericStamp(GenericStampType.Dependency); private static final Stamp extensionStamp = new GenericStamp(GenericStampType.Extension); private static final Stamp virtualStamp = new GenericStamp(GenericStampType.Virtual); @@ -98,10 +98,6 @@ return positiveInt; } - public static Stamp top() { - return top; - } - public static Stamp forInteger(Kind kind, long lowerBound, long upperBound, long mask) { return new IntegerStamp(kind, lowerBound, upperBound, mask); } @@ -128,7 +124,7 @@ assert value.kind == Kind.Object; if (value.kind == Kind.Object) { ResolvedJavaType type = value.isNull() ? null : runtime.getTypeOf(value); - return new ObjectStamp(type, value.isNonNull(), value.isNonNull()); + return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); } else { throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.kind); } @@ -142,6 +138,10 @@ return objectNonNullStamp; } + public static Stamp alwaysNull() { + return objectAlwaysNullStamp; + } + public static Stamp declared(ResolvedJavaType type) { return declared(type, false); } @@ -155,13 +155,13 @@ assert type.kind() == Kind.Object; ResolvedJavaType exact = type.exactType(); if (exact != null) { - return new ObjectStamp(exact, true, nonNull); + return new ObjectStamp(exact, true, nonNull, false); } else { - return new ObjectStamp(type, false, nonNull); + return new ObjectStamp(type, false, nonNull, false); } } public static Stamp exactNonNull(ResolvedJavaType type) { - return new ObjectStamp(type, true, true); + return new ObjectStamp(type, true, true, false); } } diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/TopStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/TopStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - - -public final class TopStamp extends Stamp { - - TopStamp() { - super(null); - } - - @Override - public boolean alwaysDistinct(Stamp other) { - return false; - } - - @Override - public Stamp meet(Stamp other) { - return other; - } - -} diff -r f84d11672a86 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/WordStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/WordStamp.java Mon Jul 16 15:20:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/WordStamp.java Mon Jul 16 15:24:06 2012 +0200 @@ -56,9 +56,6 @@ @Override public Stamp meet(Stamp otherStamp) { - if (otherStamp == StampFactory.top()) { - return this; - } WordStamp other = (WordStamp) otherStamp; if (other.nonNull == nonNull) { return this; diff -r f84d11672a86 -r a9ce56ad1860 src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java --- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java Mon Jul 16 15:20:50 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java Mon Jul 16 15:24:06 2012 +0200 @@ -112,7 +112,9 @@ @Override public void started(Group g) { - getDocument().addElement(g); + synchronized(OutlineTopComponent.this) { + getDocument().addElement(g); + } } };