# HG changeset patch # User Lukas Stadler # Date 1336744944 -7200 # Node ID 3f9895797ff41cbfb5a3adf28b5df9ca8712ab7d # Parent 5097f21f6c2b9649984b0db67b076e27cb63e211# Parent 8be0c73cf1184f4bac45b557150d6020b9a406b4 Merge diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri May 11 16:02:24 2012 +0200 @@ -136,10 +136,15 @@ new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); new PhiStampPhase().apply(graph); + if (GraalOptions.PropagateTypes) { new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph); } + if (GraalOptions.CheckCastElimination) { + new CheckCastEliminationPhase().apply(graph); + } + if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } @@ -172,6 +177,9 @@ new LoweringPhase(runtime, assumptions).apply(graph); new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); + if (GraalOptions.CullFrameStates) { + new CullFrameStatesPhase().apply(graph); + } if (GraalOptions.Lower) { new FloatingReadPhase().apply(graph); if (GraalOptions.OptGVN) { @@ -185,6 +193,11 @@ if (GraalOptions.PropagateTypes) { new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph); } + + if (GraalOptions.CheckCastElimination) { + new CheckCastEliminationPhase().apply(graph); + } + if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Fri May 11 16:02:24 2012 +0200 @@ -164,6 +164,8 @@ // Code generator settings public static boolean PropagateTypes = ____; + public static boolean CheckCastElimination = true; + public static boolean CullFrameStates = ____; public static boolean UseProfilingInformation = true; static boolean RemoveNeverExecutedCode = true; static boolean UseExceptionProbability = true; diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java Fri May 11 16:02:24 2012 +0200 @@ -0,0 +1,331 @@ +/* + * 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.compiler.phases; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.compiler.graph.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.max.cri.ri.*; + +public class CheckCastEliminationPhase extends Phase { + + private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); + private static final DebugMetric metricIsTypeRegistered = Debug.metric("IsTypeRegistered"); + private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); + private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); + private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); + private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); + private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); + + private StructuredGraph graph; + + static PrintStream out = System.out; + + @Override + protected void run(StructuredGraph inputGraph) { + graph = inputGraph; +// if (!graph.method().holder().name().contains("DiskIndex")) { +// return; +// } +// if (!graph.method().name().equals("writeCategoryTable")) { +// return; +// } +// out.println("checkcast " + graph.method()); + + new EliminateCheckCasts(graph.start(), new State()).apply(); + } + + public static class State implements MergeableState { + + private IdentityHashMap knownTypes; + private HashSet knownNotNull; + private HashSet knownNull; + + public State() { + this.knownTypes = new IdentityHashMap<>(); + this.knownNotNull = new HashSet<>(); + this.knownNull = new HashSet<>(); + } + + public State(IdentityHashMap knownTypes, HashSet knownNotNull, HashSet knownNull) { + this.knownTypes = new IdentityHashMap<>(knownTypes); + this.knownNotNull = new HashSet<>(knownNotNull); + this.knownNull = new HashSet<>(knownNull); + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + IdentityHashMap newKnownTypes = new IdentityHashMap<>(); + HashSet newKnownNotNull = new HashSet<>(); + HashSet newKnownNull = new HashSet<>(); + + for (Map.Entry entry : knownTypes.entrySet()) { + ValueNode node = entry.getKey(); + RiResolvedType type = entry.getValue(); + + for (State other : withStates) { + RiResolvedType otherType = other.getNodeType(node); + type = widen(type, otherType); + if (type == null) { + break; + } + } + if (type == null && type != node.declaredType()) { + newKnownTypes.put(node, type); + } + } + for (ValueNode node : knownNotNull) { + boolean notNull = true; + for (State other : withStates) { + if (!other.knownNotNull.contains(node)) { + notNull = false; + break; + } + } + if (notNull) { + newKnownNotNull.add(node); + } + } + for (ValueNode node : knownNull) { + boolean nul = true; + for (State other : withStates) { + if (!other.knownNull.contains(node)) { + nul = false; + break; + } + } + if (nul) { + newKnownNull.add(node); + } + } + /* + // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) + if (!(merge instanceof LoopBeginNode)) { + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value && phi.kind() == CiKind.Object) { + ValueNode firstValue = phi.valueAt(0); + RiResolvedType type = getNodeType(firstValue); + boolean notNull = knownNotNull.contains(firstValue); + boolean nul = knownNull.contains(firstValue); + + for (int i = 0; i < withStates.size(); i++) { + State otherState = withStates.get(i); + ValueNode value = phi.valueAt(i + 1); + RiResolvedType otherType = otherState.getNodeType(value); + type = widen(type, otherType); + notNull &= otherState.knownNotNull.contains(value); + nul &= otherState.knownNull.contains(value); + } + if (type == null && type != phi.declaredType()) { + newKnownTypes.put(phi, type); + } + if (notNull) { + newKnownNotNull.add(phi); + } + if (nul) { + newKnownNull.add(phi); + } + } + } + } + */ + this.knownTypes = newKnownTypes; + this.knownNotNull = newKnownNotNull; + this.knownNull = newKnownNull; + return true; + } + + public RiResolvedType getNodeType(ValueNode node) { + RiResolvedType result = knownTypes.get(node); + return result == null ? node.declaredType() : result; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { + } + + @Override + public void afterSplit(FixedNode node) { + } + + @Override + public State clone() { + return new State(knownTypes, knownNotNull, knownNull); + } + } + + public static RiResolvedType widen(RiResolvedType a, RiResolvedType b) { + if (a == null || b == null) { + return null; + } else if (a == b) { + return a; + } else { + return a.leastCommonAncestor(b); + } + } + + public static RiResolvedType tighten(RiResolvedType a, RiResolvedType b) { + if (a == null) { + return b; + } else if (b == null) { + return a; + } else if (a == b) { + return a; + } else if (a.isSubtypeOf(b)) { + return a; + } else if (b.isSubtypeOf(a)) { + return b; + } else { + return a; + } + } + + public class EliminateCheckCasts extends PostOrderNodeIterator { + private BeginNode lastBegin = null; + + public EliminateCheckCasts(FixedNode start, State initialState) { + super(start, initialState); + } + + @Override + protected void node(FixedNode node) { + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; + lastBegin = begin; + Node pred = node.predecessor(); + if (pred != null && pred instanceof IfNode) { + IfNode ifNode = (IfNode) pred; + if (ifNode.compare() instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) ifNode.compare(); + if ((node == ifNode.trueSuccessor()) != instanceOf.negated()) { + ValueNode object = instanceOf.object(); + state.knownNotNull.add(object); + state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object))); + metricInstanceOfRegistered.increment(); + } + } else if (ifNode.compare() instanceof NullCheckNode) { + NullCheckNode nullCheck = (NullCheckNode) ifNode.compare(); + boolean isNotNull = (node == ifNode.trueSuccessor()) != nullCheck.expectedNull; + if (isNotNull) { + state.knownNotNull.add(nullCheck.object()); + } else { + state.knownNull.add(nullCheck.object()); + } + metricNullCheckRegistered.increment(); + } else if (ifNode.compare() instanceof IsTypeNode) { + IsTypeNode isType = (IsTypeNode) ifNode.compare(); + if (isType.objectClass() instanceof ReadHubNode && (node == ifNode.trueSuccessor())) { + ReadHubNode readHub = (ReadHubNode) isType.objectClass(); + ValueNode object = readHub.object(); + state.knownNotNull.add(object); + state.knownTypes.put(object, tighten(isType.type(), state.getNodeType(object))); + metricIsTypeRegistered.increment(); + } + } + } + for (GuardNode guard : begin.guards().snapshot()) { + boolean removeCheck = false; + if (guard.condition() instanceof NullCheckNode) { + NullCheckNode nullCheck = (NullCheckNode) guard.condition(); + if (state.knownNotNull.contains(nullCheck.object()) && !nullCheck.expectedNull) { + removeCheck = true; + } else if (state.knownNull.contains(nullCheck.object()) && nullCheck.expectedNull) { + removeCheck = true; + } + if (removeCheck) { + metricNullCheckGuardRemoved.increment(); + } + } + if (removeCheck) { + guard.replaceAtUsages(begin); + GraphUtil.killWithUnusedFloatingInputs(guard); + } + } + } else if (node instanceof CheckCastNode) { + CheckCastNode checkCast = (CheckCastNode) node; + RiResolvedType type = state.getNodeType(checkCast.object()); + if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) { + PiNode piNode; + if (state.knownNotNull.contains(checkCast.object())) { + piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, StampFactory.declaredNonNull(type))); + } else { + piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, StampFactory.declared(type))); + } + checkCast.replaceAtUsages(piNode); + graph.removeFixed(checkCast); + metricCheckCastRemoved.increment(); + } + } else if (node instanceof IfNode) { + IfNode ifNode = (IfNode) node; + BooleanNode replaceWith = null; + BooleanNode compare = ifNode.compare(); + if (compare instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) compare; + ValueNode object = instanceOf.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(instanceOf.negated(), graph); + } else if (state.knownNotNull.contains(object)) { + RiResolvedType type = state.getNodeType(object); + if (type != null && type.isSubtypeOf(instanceOf.targetClass())) { + replaceWith = ConstantNode.forBoolean(!instanceOf.negated(), graph); + } + } + if (replaceWith != null) { + metricInstanceOfRemoved.increment(); + } + } else if (compare instanceof NullCheckNode) { + NullCheckNode nullCheck = (NullCheckNode) compare; + ValueNode object = nullCheck.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(nullCheck.expectedNull, graph); + } else if (state.knownNotNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(!nullCheck.expectedNull, graph); + } + if (replaceWith != null) { + metricNullCheckRemoved.increment(); + } + } + if (replaceWith != null) { + ifNode.setCompare(replaceWith); + if (compare.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(compare); + } + } + } + } + } + +} diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CullFrameStatesPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CullFrameStatesPhase.java Fri May 11 16:02:24 2012 +0200 @@ -0,0 +1,115 @@ +/* + * 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.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.util.*; + +/** + * This phase culls unused FrameStates from the graph. + * It does a post order iteration over the graph, and + */ +public class CullFrameStatesPhase extends Phase { + + private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled"); + private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed"); + + @Override + protected void run(StructuredGraph graph) { + new CullFrameStates(graph.start(), new State(null)).apply(); + } + + public static class State implements MergeableState { + + private FrameState lastFrameState; + + public State(FrameState lastFrameState) { + this.lastFrameState = lastFrameState; + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + FrameState stateAfter = merge.stateAfter(); + if (merge instanceof LoopBeginNode) { + if (stateAfter != null) { + lastFrameState = stateAfter; + } + return true; + } + metricMergesTraversed.increment(); + if (stateAfter != null) { + for (State other : withStates) { + if (other.lastFrameState != lastFrameState) { + lastFrameState = stateAfter; + return true; + } + } + metricFrameStatesCulled.increment(); + merge.setStateAfter(null); + if (stateAfter.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(stateAfter); + } + } + return true; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { + } + + @Override + public void afterSplit(FixedNode node) { + } + + @Override + public State clone() { + return new State(lastFrameState); + } + } + + public static class CullFrameStates extends PostOrderNodeIterator { + + public CullFrameStates(FixedNode start, State initialState) { + super(start, initialState); + } + + @Override + protected void node(FixedNode node) { + if (node instanceof StateSplit) { + FrameState stateAfter = ((StateSplit) node).stateAfter(); + if (stateAfter != null) { + state.lastFrameState = stateAfter; + } + } + } + } + +} diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Fri May 11 16:02:24 2012 +0200 @@ -145,9 +145,9 @@ Debug.log("Register read to node %s.", readNode); FloatingReadNode floatingRead; if (readNode.location().locationIdentity() == LocationNode.FINAL_LOCATION) { - floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.guard(), readNode.location(), readNode.stamp())); + floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), null, readNode.stamp(), readNode.dependencies())); } else { - floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.guard(), readNode.location(), readNode.stamp(), getLocationForRead(readNode))); + floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), getLocationForRead(readNode), readNode.stamp(), readNode.dependencies())); } graph.replaceFixedWithFloating(readNode, floatingRead); } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Fri May 11 16:02:24 2012 +0200 @@ -208,6 +208,9 @@ if (GraalOptions.Intrinsify) { new IntrinsificationPhase(runtime).apply(newGraph); } + if (GraalOptions.CullFrameStates) { + new CullFrameStatesPhase().apply(newGraph); + } if (GraalOptions.CacheGraphs && cache != null) { cache.put(newGraph); } diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java Fri May 11 16:02:24 2012 +0200 @@ -32,9 +32,8 @@ @Override protected void run(StructuredGraph graph) { for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) { - if (n.dependencies().size() > 0) { - assert n.dependencies().size() == 1; - Node memoryInput = n.dependencies().get(0); + if (n.lastLocationAccess() != null) { + Node memoryInput = n.lastLocationAccess(); if (memoryInput instanceof WriteNode) { WriteNode other = (WriteNode) memoryInput; if (other.object() == n.object() && other.location() == n.location()) { diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java Fri May 11 16:02:24 2012 +0200 @@ -22,8 +22,24 @@ */ package com.oracle.graal.debug.internal; +import java.util.*; + public abstract class DebugValue { + public static final Comparator ORDER_BY_NAME = new Comparator() { + @Override + public int compare(DebugValue o1, DebugValue o2) { + // this keeps the "Runs" metric at the top of the list + if (o1.getName().equals("Runs")) { + return o2.getName().equals("Runs") ? 0 : -1; + } + if (o2.getName().equals("Runs")) { + return o1.getName().equals("Runs") ? 0 : 1; + } + return o1.getName().compareTo(o2.getName()); + } + }; + private String name; private int index; diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri May 11 16:02:24 2012 +0200 @@ -255,14 +255,17 @@ List topLevelMaps = DebugValueMap.getTopLevelMaps(); List debugValues = KeyRegistry.getDebugValues(); if (debugValues.size() > 0) { + ArrayList sortedValues = new ArrayList<>(debugValues); + Collections.sort(sortedValues, DebugValue.ORDER_BY_NAME); + if (GraalOptions.SummarizeDebugValues) { - printSummary(topLevelMaps, debugValues); + printSummary(topLevelMaps, sortedValues); } else if (GraalOptions.PerThreadDebugValues) { for (DebugValueMap map : topLevelMaps) { TTY.println("Showing the results for thread: " + map.getName()); map.group(); map.normalize(); - printMap(map, debugValues, 0); + printMap(map, sortedValues, 0); } } else { DebugValueMap globalMap = new DebugValueMap("Global"); @@ -279,7 +282,7 @@ globalMap.group(); } globalMap.normalize(); - printMap(globalMap, debugValues, 0); + printMap(globalMap, sortedValues, 0); } } } @@ -326,6 +329,7 @@ printIndent(level); TTY.println("%s", map.getName()); + for (DebugValue value : debugValues) { long l = map.getCurrentValue(value.getIndex()); if (l != 0) { diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Fri May 11 16:02:24 2012 +0200 @@ -290,7 +290,7 @@ int displacement = ((HotSpotField) field.field()).offset(); assert field.kind() != CiKind.Illegal; ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph), field.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, field.leafGraphId())); + memoryRead.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, field.leafGraphId())); graph.replaceFixedWithFixed(field, memoryRead); if (field.isVolatile()) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); @@ -302,7 +302,7 @@ StoreFieldNode storeField = (StoreFieldNode) n; HotSpotField field = (HotSpotField) storeField.field(); WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph))); - memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, storeField.leafGraphId())); + memoryWrite.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, storeField.leafGraphId())); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); @@ -336,16 +336,16 @@ } } else if (n instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool, loadIndexed.leafGraphId()); + Node boundsCheck = createBoundsCheck(loadIndexed, tool, loadIndexed.leafGraphId()); CiKind elementKind = loadIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp())); - memoryRead.setGuard(boundsCheck); + memoryRead.dependencies().add(boundsCheck); graph.replaceFixedWithFixed(loadIndexed, memoryRead); } else if (n instanceof StoreIndexedNode) { StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool, storeIndexed.leafGraphId()); + Node boundsCheck = createBoundsCheck(storeIndexed, tool, storeIndexed.leafGraphId()); CiKind elementKind = storeIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); @@ -365,17 +365,17 @@ assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); } } else { - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID); - FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull())); - arrayClass.setGuard(guard); - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), StampFactory.objectNonNull())); + Node guard = tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID); + FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), null, StampFactory.objectNonNull())); + arrayClass.dependencies().add(guard); + FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), null, StampFactory.objectNonNull())); checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value)); graph.addBeforeFixed(storeIndexed, checkcast); value = checkcast; } } WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); - memoryWrite.setGuard(boundsCheck); + memoryWrite.dependencies().add(boundsCheck); memoryWrite.setStateAfter(storeIndexed.stateAfter()); graph.replaceFixedWithFixed(storeIndexed, memoryWrite); @@ -392,7 +392,7 @@ IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph); location.setIndexScalingEnabled(false); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID)); + memoryRead.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; @@ -409,7 +409,7 @@ ReadHubNode objectClassNode = (ReadHubNode) n; LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph); ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID)); + memoryRead.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixed(objectClassNode, memoryRead); } else if (n instanceof CheckCastNode) { if (GraalOptions.HIRLowerCheckcast != null && graph.method() != null && graph.method().holder().name().contains(GraalOptions.HIRLowerCheckcast)) { @@ -445,8 +445,8 @@ return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph); } - private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) { - return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId); + private static Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) { + return tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId); } @Override @@ -467,7 +467,7 @@ StructuredGraph graph = new StructuredGraph(); LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); - FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull())); + FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), null, StampFactory.objectNonNull())); ReturnNode ret = graph.add(new ReturnNode(result)); graph.start().setNext(klassOop); klassOop.setNext(ret); @@ -480,7 +480,7 @@ SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID); graph.start().setNext(klassOop); // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null) - FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), StampFactory.forKind(CiKind.Int))); + FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), null, StampFactory.forKind(CiKind.Int))); ReturnNode ret = graph.add(new ReturnNode(result)); klassOop.setNext(ret); return graph; diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java Fri May 11 16:02:24 2012 +0200 @@ -22,28 +22,22 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** - * The {@code AnchorNode} can be used a lower bound for a Guard. It can also be used as an upper bound if no other FixedNode can be used for that purpose. + * The {@code AnchorNode} can be used a lower bound for a guard. It can also be used as an upper bound if no other FixedNode can be used for that purpose. + * The guards that should be kept above this node need to be added to the {@link #dependencies()} collection. */ public final class AnchorNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { - @Input(notDataflow = true) private final NodeInputList guards = new NodeInputList<>(this); - public AnchorNode() { super(StampFactory.illegal()); } - public void addGuard(GuardNode x) { - guards.add(x); - } - @Override public ValueNode canonical(CanonicalizerTool tool) { - if (this.usages().size() == 0 && guards.size() == 0) { + if (this.usages().size() == 0 && dependencies().isEmpty()) { return null; } return this; diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri May 11 16:02:24 2012 +0200 @@ -84,7 +84,7 @@ public void lower(CiLoweringTool tool) { AnchorNode newAnchor = graph().add(new AnchorNode()); for (BooleanNode b : conditions) { - newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason, action, leafGraphId)); + newAnchor.dependencies().add(tool.createGuard(b, deoptReason, action, leafGraphId)); } ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor); } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri May 11 16:02:24 2012 +0200 @@ -45,6 +45,11 @@ return compare; } + public void setCompare(BooleanNode x) { + updateUsages(compare, x); + compare = x; + } + public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability) { super(StampFactory.illegal(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability}); this.compare = condition; diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri May 11 16:02:24 2012 +0200 @@ -24,10 +24,10 @@ import java.util.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.type.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.type.*; /** * This class represents a value within the graph, including local variables, phis, and @@ -41,8 +41,11 @@ */ private Stamp stamp; - @Input private NodeInputList dependencies; + @Input(notDataflow = true) private NodeInputList dependencies; + /** + * This collection keeps dependencies that should be observed while scheduling (guards, etc.). + */ public NodeInputList dependencies() { return dependencies; } @@ -59,6 +62,12 @@ assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind(); } + public ValueNode(Stamp stamp, List dependencies) { + this.stamp = stamp; + this.dependencies = new NodeInputList<>(this, dependencies); + assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind(); + } + public Stamp stamp() { return stamp; } @@ -121,7 +130,7 @@ if (!dependencies.isEmpty()) { StringBuilder str = new StringBuilder(); for (int i = 0; i < dependencies.size(); i++) { - str.append(i == 0 ? "" : ", ").append(dependencies.get(i).toString(Verbosity.Id)); + str.append(i == 0 ? "" : ", ").append(dependencies.get(i) == null ? "null" : dependencies.get(i).toString(Verbosity.Id)); } properties.put("dependencies", str.toString()); } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Fri May 11 16:02:24 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.calc; +import java.util.*; + import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -35,4 +37,8 @@ public FloatingNode(Stamp stamp, Node... dependencies) { super(stamp, dependencies); } + + public FloatingNode(Stamp stamp, List dependencies) { + super(stamp, dependencies); + } } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri May 11 16:02:24 2012 +0200 @@ -60,6 +60,20 @@ return x(); } } + // canonicalize expressions like "(a + 1) + 2" + if (x() instanceof IntegerAddNode) { + IntegerAddNode other = (IntegerAddNode) x(); + if (other.y().isConstant()) { + ConstantNode sum; + if (kind() == CiKind.Int) { + sum = ConstantNode.forInt(y().asConstant().asInt() + other.y().asConstant().asInt(), graph()); + } else { + assert kind() == CiKind.Long; + sum = ConstantNode.forLong(y().asConstant().asLong() + other.y().asConstant().asLong(), graph()); + } + return graph().unique(new IntegerAddNode(kind(), other.x(), sum)); + } + } } return this; } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri May 11 16:02:24 2012 +0200 @@ -57,6 +57,20 @@ if (c > 0 && CiUtil.isPowerOf2(c)) { return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CiUtil.log2(c), graph()))); } + // canonicalize expressions like "(a * 1) * 2" + if (x() instanceof IntegerMulNode) { + IntegerMulNode other = (IntegerMulNode) x(); + if (other.y().isConstant()) { + ConstantNode sum; + if (kind() == CiKind.Int) { + sum = ConstantNode.forInt(y().asConstant().asInt() * other.y().asConstant().asInt(), graph()); + } else { + assert kind() == CiKind.Long; + sum = ConstantNode.forLong(y().asConstant().asLong() * other.y().asConstant().asLong(), graph()); + } + return graph().unique(new IntegerMulNode(kind(), other.x(), sum)); + } + } } return this; } diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Fri May 11 16:02:24 2012 +0200 @@ -28,7 +28,6 @@ public abstract class AccessNode extends FixedWithNextNode implements Access { @Input private ValueNode object; - @Input private GuardNode guard; @Input private LocationNode location; private boolean nullCheck; @@ -36,15 +35,6 @@ return object; } - public GuardNode guard() { - return guard; - } - - public void setGuard(GuardNode x) { - updateUsages(guard, x); - guard = x; - } - public LocationNode location() { return location; } diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Fri May 11 16:02:24 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import java.util.*; + import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -30,7 +32,6 @@ public abstract class FloatingAccessNode extends FloatingNode implements Access { @Input private ValueNode object; - @Input private GuardNode guard; @Input private LocationNode location; private boolean nullCheck; @@ -38,15 +39,6 @@ return object; } - public GuardNode guard() { - return guard; - } - - public void setGuard(GuardNode x) { - updateUsages(guard, x); - guard = x; - } - public LocationNode location() { return location; } @@ -59,17 +51,21 @@ this.nullCheck = check; } - public FloatingAccessNode(ValueNode object, GuardNode guard, LocationNode location, Stamp stamp) { + public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp) { super(stamp); this.object = object; - this.guard = guard; this.location = location; } - public FloatingAccessNode(ValueNode object, GuardNode guard, LocationNode location, Stamp stamp, Node... dependencies) { + public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, Node... dependencies) { super(stamp, dependencies); this.object = object; - this.guard = guard; + this.location = location; + } + + public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, List dependencies) { + super(stamp, dependencies); + this.object = object; this.location = location; } } diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Fri May 11 16:02:24 2012 +0200 @@ -22,18 +22,32 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; +import java.util.*; + import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { - public FloatingReadNode(ValueNode object, GuardNode guard, LocationNode location, Stamp stamp, Node... dependencies) { - super(object, guard, location, stamp, dependencies); + @Input private Node lastLocationAccess; + + public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, Node... dependencies) { + super(object, location, stamp, dependencies); + this.lastLocationAccess = lastLocationAccess; + } + + public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, List dependencies) { + super(object, location, stamp, dependencies); + this.lastLocationAccess = lastLocationAccess; + } + + public Node lastLocationAccess() { + return lastLocationAccess; } @Override diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java Fri May 11 16:02:24 2012 +0200 @@ -26,9 +26,11 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.*; // TODO (chaeubl) this should be a FloatingNode but Lowering is not possible in that case -public final class ReadHubNode extends FixedWithNextNode implements Lowerable { +public final class ReadHubNode extends FixedWithNextNode implements Lowerable, Canonicalizable { @Input private ValueNode object; public ValueNode object() { @@ -44,4 +46,20 @@ public void lower(CiLoweringTool tool) { tool.getRuntime().lower(this, tool); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + RiResolvedType exactType = object.exactType(); + + if (exactType == null && tool.assumptions() != null && object.declaredType() != null) { + exactType = object.declaredType().uniqueConcreteSubtype(); + if (exactType != null) { + tool.assumptions().recordConcreteSubtype(object.declaredType(), exactType); + } + } + if (exactType != null) { + return ConstantNode.forCiConstant(exactType.getEncoding(Representation.ObjectHub), tool.runtime(), graph()); + } + return this; + } } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Fri May 11 16:02:24 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.cri.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -40,9 +41,9 @@ @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId()); + Node guard = tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId()); ReadNode read = graph.add(new ReadNode(object(), location(), stamp())); - read.setGuard(guard); + read.dependencies().add(guard); graph.replaceFixedWithFixed(this, read); } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Fri May 11 16:02:24 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.cri.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -62,9 +63,9 @@ @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId()); + Node guard = tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, leafGraphId()); WriteNode write = graph.add(new WriteNode(object(), value(), location())); - write.setGuard(guard); + write.dependencies().add(guard); graph.replaceFixedWithFixed(this, write); } } diff -r 8be0c73cf118 -r 3f9895797ff4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Fri May 11 16:02:24 2012 +0200 @@ -25,12 +25,12 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.cri.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; /** * The base class of all instructions that access fields. @@ -102,6 +102,15 @@ } @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(verbosity) + "#" + field.name(); + } else { + return super.toString(verbosity); + } + } + + @Override public boolean verify() { assertTrue(object != null, "Access object can not be null"); return super.verify(); diff -r 8be0c73cf118 -r 3f9895797ff4 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 Fri May 11 14:11:56 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri May 11 16:02:24 2012 +0200 @@ -278,13 +278,7 @@ } else if (a == null || b == null) { return null; } else { - if (a.isSubtypeOf(b)) { - return b; - } else if (b.isSubtypeOf(a)) { - return a; - } else { - return null; - } + return a.leastCommonAncestor(b); } } }