# HG changeset patch # User Gilles Duboscq # Date 1337004982 -7200 # Node ID af76b75d5928549bf7b6134df1bdf12a73b103f5 # Parent 9b44497fef98c3cf1877fa210c515eb99da40614# Parent 80ae8033fe01f9413bea3da64923d167a0b3ff25 Merge diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon May 14 16:16:22 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); } @@ -168,10 +173,13 @@ new GlobalValueNumberingPhase().apply(graph); } - graph.mark(); - new LoweringPhase(runtime).apply(graph); - new CanonicalizerPhase(target, runtime, assumptions, true, null).apply(graph); + int mark = graph.getMark(); + 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon May 14 16:16:22 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; @@ -256,6 +258,13 @@ public static int InstanceOfMaxHints = 1; /** + * Use HIR lowering instead of LIR lowering for checkcast instructions. + * Only checkcasts in methods in a class whose name contains this option will be HIR lowered. + * TDOD (dnsimon) remove once HIR checkcast lowering works reliably + */ + public static String HIRLowerCheckcast; + + /** * The profiling info cache directory. */ public static String PICache = null; diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon May 14 16:16:22 2012 +0200 @@ -836,7 +836,7 @@ case Virtual: assert callTarget.receiver().kind() == CiKind.Object : callTarget + ": " + callTarget.targetMethod().toString(); receiver = toXirArgument(callTarget.receiver()); - snippet = xir.genInvokeVirtual(site(x.node(), callTarget.receiver()), receiver, targetMethod, x.megamorph()); + snippet = xir.genInvokeVirtual(site(x.node(), callTarget.receiver()), receiver, targetMethod, x.isMegamorphic()); break; case Interface: assert callTarget.receiver().kind() == CiKind.Object : callTarget; diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Mon May 14 16:16:22 2012 +0200 @@ -37,18 +37,22 @@ private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes"); private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); - private boolean newNodes; + private int newNodesMark; private final CiTarget target; private final CiAssumptions assumptions; private final RiRuntime runtime; private final IsImmutablePredicate immutabilityPredicate; public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions) { - this(target, runtime, assumptions, false, null); + this(target, runtime, assumptions, -1, null); } - public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, boolean newNodes, IsImmutablePredicate immutabilityPredicate) { - this.newNodes = newNodes; + /** + * @param newNodesMark if non-negative, then only the {@linkplain Graph#getNewNodes(int) new nodes} specified by + * this mark are processed otherwise all nodes in the graph are processed + */ + public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { + this.newNodesMark = newNodesMark; this.target = target; this.assumptions = assumptions; this.runtime = runtime; @@ -57,9 +61,10 @@ @Override protected void run(StructuredGraph graph) { + boolean newNodes = newNodesMark >= 0; NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE); if (newNodes) { - nodeWorkList.addAll(graph.getNewNodes()); + nodeWorkList.addAll(graph.getNewNodes(newNodesMark)); } canonicalize(graph, nodeWorkList, runtime, target, assumptions, immutabilityPredicate); @@ -80,7 +85,7 @@ METRIC_PROCESSED_NODES.increment(); if (node instanceof Canonicalizable) { METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - graph.mark(); + int mark = graph.getMark(); ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| @@ -132,7 +137,7 @@ } } } - nodeWorkList.addAll(graph.getNewNodes()); + nodeWorkList.addAll(graph.getNewNodes(mark)); } } else if (node instanceof Simplifiable) { Debug.log("Canonicalizer: simplifying %s", node); diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:22 2012 +0200 @@ -0,0 +1,320 @@ +/* + * 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.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; + + @Override + protected void run(StructuredGraph inputGraph) { + graph = inputGraph; + 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Mon May 14 16:16:22 2012 +0200 @@ -84,10 +84,10 @@ graph.createNodeMap(); if (hints != null) { - scanInvokes((Iterable) Util.uncheckedCast(this.hints), -1, graph); + scanInvokes((Iterable) Util.uncheckedCast(this.hints), -1); } else { - scanInvokes(graph.getNodes(InvokeNode.class), 0, graph); - scanInvokes(graph.getNodes(InvokeWithExceptionNode.class), 0, graph); + scanInvokes(graph.getNodes(InvokeNode.class), 0); + scanInvokes(graph.getNodes(InvokeWithExceptionNode.class), 0); } while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { @@ -101,14 +101,14 @@ }); if (inline) { + int mark = graph.getMark(); Iterable newNodes = null; try { info.inline(graph, runtime, this); Debug.dump(graph, "after %s", info); - // get the new nodes here, the canonicalizer phase will reset the mark - newNodes = graph.getNewNodes(); + newNodes = graph.getNewNodes(mark); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, true, null).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); } // if (GraalOptions.Intrinsify) { // new IntrinsificationPhase(runtime).apply(graph); @@ -126,7 +126,7 @@ } if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) { - scanInvokes(newNodes, info.level + 1, graph); + scanInvokes(newNodes, info.level + 1); } } } @@ -144,11 +144,10 @@ } } - private void scanInvokes(final Iterable newNodes, final int level, final StructuredGraph graph) { + private void scanInvokes(final Iterable nodes, final int level) { Debug.scope("InliningDecisions", new Runnable() { public void run() { - graph.mark(); - for (Node node : newNodes) { + for (Node node : nodes) { if (node != null) { if (node instanceof Invoke) { Invoke invoke = (Invoke) node; @@ -209,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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Mon May 14 16:16:22 2012 +0200 @@ -29,7 +29,7 @@ public class InsertStateAfterPlaceholderPhase extends Phase { - private static class PlaceholderNode extends FixedWithNextNode implements StateSplit, Node.IterableNodeType, LIRLowerable { + private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable { public PlaceholderNode() { super(StampFactory.illegal()); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Mon May 14 16:16:22 2012 +0200 @@ -27,7 +27,9 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; /** @@ -36,9 +38,11 @@ public class LoweringPhase extends Phase { private final GraalRuntime runtime; + private final CiAssumptions assumptions; - public LoweringPhase(GraalRuntime runtime) { + public LoweringPhase(GraalRuntime runtime, CiAssumptions assumptions) { this.runtime = runtime; + this.assumptions = assumptions; } @Override @@ -67,10 +71,19 @@ // TODO (thomaswue): Document why this must not be called on floating nodes. throw new UnsupportedOperationException(); } + + @Override + public CiAssumptions assumptions() { + return assumptions; + } }; for (Node node : processed) { - if (node instanceof Lowerable) { - assert !(node instanceof FixedNode) || node.predecessor() == null; + if (node instanceof CheckCastNode) { + // This is a checkcast that was created while lowering some other node (e.g. StoreIndexed). + // This checkcast must now be LIR lowered. + // TODO (dnsimon) this is temp workaround that will be removed + } else if (node instanceof Lowerable) { + assert !(node instanceof FixedNode) || node.predecessor() == null : node; ((Lowerable) node).lower(loweringTool); } } @@ -135,6 +148,11 @@ activeGuards.mark(newGuard); return newGuard; } + + @Override + public CiAssumptions assumptions() { + return assumptions; + } }; // Lower the instructions of this block. diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Mon May 14 16:16:22 2012 +0200 @@ -40,6 +40,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.max.cri.ci.*; @@ -287,7 +288,7 @@ PhiNode exceptionObjectPhi = null; if (invoke instanceof InvokeWithExceptionNode) { InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke; - BeginNode exceptionEdge = invokeWithException.exceptionEdge(); + DispatchBeginNode exceptionEdge = invokeWithException.exceptionEdge(); ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next(); exceptionMerge = graph.add(new MergeNode()); @@ -634,7 +635,7 @@ return null; } } else { - invoke.setMegamorph(true); + invoke.setMegamorphic(true); if (optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0 || optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { // TODO (chaeubl) inlining of multiple methods should work differently // 1. check which methods can be inlined @@ -785,7 +786,7 @@ ArrayList nodes = new ArrayList<>(); ReturnNode returnNode = null; UnwindNode unwindNode = null; - BeginNode entryPointNode = inlineGraph.start(); + StartNode entryPointNode = inlineGraph.start(); FixedNode firstCFGNode = entryPointNode.next(); for (Node node : inlineGraph.getNodes()) { if (node == entryPointNode || node == entryPointNode.stateAfter()) { @@ -921,11 +922,12 @@ final StructuredGraph snippetGraph, final boolean explodeLoops, final IsImmutablePredicate immutabilityPredicate, + final CiLoweringTool tool, final Object... args) { Debug.scope("InliningSnippet", snippetGraph.method(), new Runnable() { @Override public void run() { - inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, args); + inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, tool, args); } }); } @@ -935,7 +937,10 @@ StructuredGraph snippetGraph, boolean explodeLoops, IsImmutablePredicate immutabilityPredicate, - Object... args) { + CiLoweringTool tool, Object... args) { + + Debug.dump(replacee.graph(), "Before lowering %s", replacee); + // Copy snippet graph, replacing parameters with given args in the process StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap replacements = new IdentityHashMap<>(); @@ -957,7 +962,7 @@ assert localCount == args.length : "snippet argument count mismatch"; snippetCopy.addDuplicates(snippetGraph.getNodes(), replacements); if (!replacements.isEmpty()) { - new CanonicalizerPhase(null, runtime, null, false, immutabilityPredicate).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, null, -1, immutabilityPredicate).apply(snippetCopy); } // Explode all loops in the snippet if requested @@ -967,19 +972,23 @@ LoopBeginNode loopBegin = loop.loopBegin(); SuperBlock wholeLoop = LoopTransformUtil.wholeLoop(loop); Debug.dump(snippetCopy, "Before exploding loop %s", loopBegin); + int peel = 0; while (!loopBegin.isDeleted()) { - snippetCopy.mark(); + int mark = snippetCopy.getMark(); LoopTransformUtil.peel(loop, wholeLoop); - new CanonicalizerPhase(null, runtime, null, true, immutabilityPredicate).apply(snippetCopy); + Debug.dump(snippetCopy, "After peel %d", peel); + new CanonicalizerPhase(null, runtime, null, mark, immutabilityPredicate).apply(snippetCopy); + peel++; } Debug.dump(snippetCopy, "After exploding loop %s", loopBegin); } + new DeadCodeEliminationPhase().apply(snippetCopy); } - // Gather the nodes in the snippets that are to be inlined + // Gather the nodes in the snippet that are to be inlined ArrayList nodes = new ArrayList<>(); ReturnNode returnNode = null; - BeginNode entryPointNode = snippetCopy.start(); + StartNode entryPointNode = snippetCopy.start(); FixedNode firstCFGNode = entryPointNode.next(); replacements.clear(); for (Node node : snippetCopy.getNodes()) { @@ -1003,21 +1012,39 @@ // Inline the gathered snippet nodes StructuredGraph graph = (StructuredGraph) replacee.graph(); + int mark = graph.getMark(); Map duplicates = graph.addDuplicates(nodes, replacements); + Debug.dump(graph, "After inlining snippet %s", snippetCopy.method()); // Remove all frame states from the inlined snippet graph. Snippets must be atomic (i.e. free // of side-effects that prevent deoptimizing to a point before the snippet). - for (Node node : duplicates.values()) { + if (tool != null) { + boolean innerLowering = false; + for (Node node : duplicates.values()) { + if (node instanceof Lowerable) { + innerLowering = true; + ((Lowerable) node).lower(tool); + + } + } + if (innerLowering) { + Debug.dump(graph, "After inner lowering"); + } + } + + for (Node node : graph.getNewNodes(mark)) { if (node instanceof StateSplit) { StateSplit stateSplit = (StateSplit) node; FrameState frameState = stateSplit.stateAfter(); - assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node; + assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node + "\n " + replacee.graph(); if (frameState != null) { stateSplit.setStateAfter(null); } } } + Debug.dump(graph, "After removing frame states"); + // Rewire the control flow graph around the replacee FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); anchor.replaceAtPredecessors(firstCFGNodeDuplicate); diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon May 14 16:16:22 2012 +0200 @@ -45,7 +45,6 @@ private final ArrayList nodeCacheFirst; private final ArrayList nodeCacheLast; private int deletedNodeCount; - private int mark; private GraphEventLog eventLog; ArrayList usagesDropped = new ArrayList<>(); @@ -221,10 +220,10 @@ } /** - * @see #getNewNodes() + * Gets a mark that can be used with {@link #getNewNodes()}. */ - public void mark() { - this.mark = nodeIdCount(); + public int getMark() { + return nodeIdCount(); } private class NodeIterator implements Iterator { @@ -277,11 +276,10 @@ } /** - * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#mark() mark}. - * @return an {@link Iterable} providing the new nodes + * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#getMark() mark}. */ - public NodeIterable getNewNodes() { - final int index = this.mark; + public NodeIterable getNewNodes(int mark) { + final int index = mark; return new NodeIterable() { @Override public Iterator iterator() { diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Mon May 14 16:16:22 2012 +0200 @@ -67,7 +67,7 @@ return count; } public boolean isEmpty() { - return count() == 0; + return !iterator().hasNext(); } public boolean isNotEmpty() { return iterator().hasNext(); diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon May 14 16:16:22 2012 +0200 @@ -79,8 +79,6 @@ cancelled = true; } -// private static PrintStream out = System.out; - public void run() { withinEnqueue.set(Boolean.FALSE); try { diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Mon May 14 16:16:22 2012 +0200 @@ -148,8 +148,7 @@ return null; } Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output)); - // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__ - Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope())); + Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) { Debug.log("Context obj %s", o); if (o instanceof Graph) { diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon May 14 16:16:22 2012 +0200 @@ -53,7 +53,6 @@ private final Compiler compiler; private IntrinsifyArrayCopyPhase intrinsifyArrayCopy; - private LowerCheckCastPhase lowerCheckCastPhase; public final HotSpotTypePrimitive typeBoolean; public final HotSpotTypePrimitive typeChar; @@ -116,12 +115,8 @@ @Override public void run() { VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); - VMToCompilerImpl.this.lowerCheckCastPhase = new LowerCheckCastPhase(runtime); GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget()); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets()); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets()); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets()); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new CheckCastSnippets()); + runtime.installSnippets(); } }); @@ -260,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"); @@ -284,7 +282,7 @@ globalMap.group(); } globalMap.normalize(); - printMap(globalMap, debugValues, 0); + printMap(globalMap, sortedValues, 0); } } } @@ -331,6 +329,7 @@ printIndent(level); TTY.println("%s", map.getName()); + for (DebugValue value : debugValues) { long l = map.getCurrentValue(value.getIndex()); if (l != 0) { @@ -495,7 +494,6 @@ if (GraalOptions.Intrinsify) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy); } - phasePlan.addPhase(PhasePosition.HIGH_LEVEL, lowerCheckCastPhase); return phasePlan; } diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Mon May 14 16:16:22 2012 +0200 @@ -28,18 +28,24 @@ import java.util.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.util.*; import com.oracle.graal.cri.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.hotspot.target.amd64.*; 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.snippets.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ci.CiTargetMethod.Call; import com.oracle.max.cri.ci.CiTargetMethod.DataPatch; @@ -58,6 +64,7 @@ final HotSpotRegisterConfig regConfig; private final HotSpotRegisterConfig globalStubRegConfig; private final Compiler compiler; + private RiResolvedMethod checkcastSnippet; public HotSpotRuntime(HotSpotVMConfig config, Compiler compiler) { this.config = config; @@ -68,6 +75,19 @@ System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName()); } + public void installSnippets() { + Snippets.install(this, compiler.getTarget(), new SystemSnippets()); + Snippets.install(this, compiler.getTarget(), new UnsafeSnippets()); + Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets()); + Snippets.install(this, compiler.getTarget(), new CheckCastSnippets()); + try { + checkcastSnippet = getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class)); + } catch (NoSuchMethodException e) { + throw new GraalInternalError(e); + } + } + + @Override public int codeOffset() { return 0; @@ -270,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)); @@ -282,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); @@ -316,20 +336,21 @@ } } 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()); ValueNode value = storeIndexed.value(); + CheckCastNode checkcast = null; ValueNode array = storeIndexed.array(); if (elementKind == CiKind.Object && !value.isNullConstant()) { // Store check! @@ -337,24 +358,24 @@ RiResolvedType elementType = array.exactType().componentType(); if (elementType.superType() != null) { ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph); - CheckCastNode checkcast = graph.add(new CheckCastNode(type, elementType, value)); + checkcast = graph.add(new CheckCastNode(type, elementType, value)); graph.addBeforeFixed(storeIndexed, checkcast); value = checkcast; } else { 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())); - CheckCastNode checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value)); + 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); @@ -362,13 +383,16 @@ if (elementKind == CiKind.Object && !value.isNullConstant()) { graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); } + if (checkcast != null) { + checkcast.lower(tool); + } } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != CiKind.Illegal; 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; @@ -385,8 +409,33 @@ 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)) { + final Map hintHubsSet = new IdentityHashMap<>(); + IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() { + public boolean apply(CiConstant constant) { + return hintHubsSet.containsKey(constant); + } + }; + CheckCastNode checkcast = (CheckCastNode) n; + ValueNode hub = checkcast.targetClassInstruction(); + ValueNode object = checkcast.object(); + TypeCheckHints hints = new TypeCheckHints(checkcast.targetClass(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); + StructuredGraph snippetGraph = (StructuredGraph) checkcastSnippet.compilerStorage().get(Graph.class); + assert snippetGraph != null : CheckCastSnippets.class.getSimpleName() + " should be installed"; + HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length]; + for (int i = 0; i < hintHubs.length; i++) { + hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop(); + } + final CiConstant hintHubsConst = CiConstant.forObject(hintHubs); + hintHubsSet.put(hintHubsConst, hintHubsConst); + Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact); + + InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, tool, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact)); + new DeadCodeEliminationPhase().apply(graph); + } } else { assert false : "Node implementing Lowerable not handled: " + n; } @@ -396,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 @@ -418,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); @@ -431,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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/LowerCheckCastPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/LowerCheckCastPhase.java Mon May 14 16:16:12 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * 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.hotspot.snippets; - -import java.util.*; - -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate; -import com.oracle.graal.compiler.util.*; -import com.oracle.graal.cri.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.ri.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.criutils.*; - -/** - * Lowers a {@link CheckCastNode} by replacing it with the graph of a {@linkplain CheckCastSnippets checkcast snippet}. - */ -public class LowerCheckCastPhase extends Phase { - private final GraalRuntime runtime; - private final RiResolvedMethod checkcast; - - public LowerCheckCastPhase(GraalRuntime runtime) { - this.runtime = runtime; - try { - checkcast = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class)); - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - - @Override - protected void run(StructuredGraph graph) { - final Map hintHubsSet = new IdentityHashMap<>(); - IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() { - public boolean apply(CiConstant constant) { - return hintHubsSet.containsKey(constant); - } - }; - for (CheckCastNode node : graph.getNodes(CheckCastNode.class)) { - ValueNode hub = node.targetClassInstruction(); - ValueNode object = node.object(); - CiAssumptions assumptions = null; - TypeCheckHints hints = new TypeCheckHints(node.targetClass(), node.profile(), assumptions, GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); - StructuredGraph snippetGraph = (StructuredGraph) checkcast.compilerStorage().get(Graph.class); - assert snippetGraph != null : CheckCastSnippets.class.getSimpleName() + " should be installed"; - HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length]; - for (int i = 0; i < hintHubs.length; i++) { - hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop(); - } - final CiConstant hintHubsConst = CiConstant.forObject(hintHubs); - hintHubsSet.put(hintHubsConst, hintHubsConst); - Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, node, Arrays.toString(hints.types), hints.exact); - - InliningUtil.inlineSnippet(runtime, node, node, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact)); - } - if (!hintHubsSet.isEmpty()) { - Debug.log("Lowered %d checkcasts in %s ", hintHubsSet.size(), graph); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime, null, false, immutabilityPredicate).apply(graph); - } - } -} diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon May 14 16:16:22 2012 +0200 @@ -165,7 +165,7 @@ frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); // finish the start block - lastInstr.setStateAfter(frameState.create(0)); + ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); if (blockMap.startBlock.isLoopHeader) { appendGoto(createTarget(blockMap.startBlock, frameState)); } else { @@ -241,7 +241,7 @@ return handler.catchTypeCPI() == 0; } - private BeginNode handleException(ValueNode exceptionObject, int bci) { + private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); @@ -255,7 +255,7 @@ FrameStateBuilder dispatchState = frameState.copy(); dispatchState.clearStack(); - BeginNode dispatchBegin = currentGraph.add(new DispatchBeginNode()); + DispatchBeginNode dispatchBegin = currentGraph.add(new DispatchBeginNode()); dispatchBegin.setStateAfter(dispatchState.create(bci)); if (exceptionObject == null) { @@ -948,7 +948,7 @@ frameState.pushReturn(resultType, result); } else { - BeginNode exceptionEdge = handleException(null, bci()); + DispatchBeginNode exceptionEdge = handleException(null, bci()); InvokeWithExceptionNode invoke = currentGraph.add(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci(), graphId)); ValueNode result = append(invoke); frameState.pushReturn(resultType, result); @@ -1469,9 +1469,13 @@ frameState.clearNonLiveLocals(currentBlock.localsLiveOut); } if (lastInstr instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) lastInstr; - if (stateSplit.stateAfter() == null) { - stateSplit.setStateAfter(frameState.create(bci)); + if (lastInstr.getClass() == BeginNode.class) { + // BeginNodes do not need a frame state + } else { + StateSplit stateSplit = (StateSplit) lastInstr; + if (stateSplit.stateAfter() == null) { + stateSplit.setStateAfter(frameState.create(bci)); + } } } if (bci < endBCI) { diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Mon May 14 16:16:22 2012 +0200 @@ -23,11 +23,13 @@ package com.oracle.graal.cri; import com.oracle.graal.graph.*; +import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; public interface CiLoweringTool { GraalRuntime getRuntime(); Node getGuardAnchor(); Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId); + CiAssumptions assumptions(); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Mon May 14 16:16:22 2012 +0200 @@ -0,0 +1,51 @@ +/* + * 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; + +import com.oracle.graal.nodes.type.*; + +/** + * Provides an implementation of {@link StateSplit}. + */ +public abstract class AbstractStateSplit extends FixedWithNextNode implements StateSplit { + + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } + + public AbstractStateSplit(Stamp stamp) { + super(stamp); + } +} diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon May 14 16:16:22 2012 +0200 @@ -31,7 +31,23 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Node.IterableNodeType { +public class BeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, Node.IterableNodeType { + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return false; + } + public BeginNode() { super(StampFactory.illegal()); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon May 14 16:16:22 2012 +0200 @@ -24,6 +24,8 @@ /** * Base class for {@link BeginNode}s that are associated with a frame state. + * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit} + * which is not possible until loop peeling works without requiring begin nodes to have frames states */ public abstract class BeginStateSplitNode extends BeginNode implements StateSplit { diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,43 +22,13 @@ */ package com.oracle.graal.nodes; -import java.util.*; - import com.oracle.graal.nodes.type.*; /** * Base class of all nodes that are fixed within the control flow graph and have an immediate successor. - * This class also provides an implementation of {@link StateSplit} without being a {@link StateSplit} itself. */ public abstract class FixedWithNextNode extends FixedNode { - @Input(notDataflow = true) private FrameState stateAfter; - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - assert this instanceof StateSplit : getClass() + " does not implement " + StateSplit.class; - updateUsages(stateAfter, x); - stateAfter = x; - } - - // Subclasses that implement StateSplit but do not represent side-effecting instructions must override this. - public boolean hasSideEffect() { - return true; - } - - @Override - public Map getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - if (stateAfter() != null) { - debugProperties.put("stateAfter", stateAfter().toString(Verbosity.Debugger)); - } - return debugProperties; - } - public FixedNode next() { assert scheduledNext() == null || scheduledNext() instanceof FixedNode : "next() cannot be used while the graph is scheduled"; return (FixedNode) scheduledNext(); diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Mon May 14 16:16:22 2012 +0200 @@ -55,9 +55,12 @@ void setUseForInlining(boolean value); - boolean megamorph(); + /** + * True if this invocation is almost certainly megamorphic, false when in doubt. + */ + boolean isMegamorphic(); - void setMegamorph(boolean megamorph); + void setMegamorphic(boolean value); long leafGraphId(); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon May 14 16:16:22 2012 +0200 @@ -34,12 +34,11 @@ /** * The {@code InvokeNode} represents all kinds of method calls. */ -public final class InvokeNode extends FixedWithNextNode implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint { +public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint { @Input private final MethodCallTargetNode callTarget; private final int bci; - // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt - private boolean megamorph; + private boolean megamorphic; private boolean useForInlining; private final long leafGraphId; @@ -56,7 +55,7 @@ this.callTarget = callTarget; this.bci = bci; this.leafGraphId = leafGraphId; - this.megamorph = false; + this.megamorphic = false; this.useForInlining = true; } @@ -65,13 +64,13 @@ } @Override - public boolean megamorph() { - return megamorph; + public boolean isMegamorphic() { + return megamorphic; } @Override - public void setMegamorph(boolean megamorph) { - this.megamorph = megamorph; + public void setMegamorphic(boolean value) { + this.megamorphic = value; } public boolean useForInlining() { diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon May 14 16:16:22 2012 +0200 @@ -39,7 +39,7 @@ @Input private FrameState stateAfter; private final int bci; // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt - private boolean megamorph; + private boolean megamorphic; private boolean useForInlining; private final long leafGraphId; @@ -48,17 +48,17 @@ * @param blockSuccessors * @param branchProbability */ - public InvokeWithExceptionNode(MethodCallTargetNode callTarget, BeginNode exceptionEdge, int bci, long leafGraphId) { + public InvokeWithExceptionNode(MethodCallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) { super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0}); this.bci = bci; this.callTarget = callTarget; this.leafGraphId = leafGraphId; - this.megamorph = true; + this.megamorphic = true; this.useForInlining = true; } - public BeginNode exceptionEdge() { - return blockSuccessor(EXCEPTION_EDGE); + public DispatchBeginNode exceptionEdge() { + return (DispatchBeginNode) blockSuccessor(EXCEPTION_EDGE); } public void setExceptionEdge(BeginNode x) { @@ -78,13 +78,13 @@ } @Override - public boolean megamorph() { - return megamorph; + public boolean isMegamorphic() { + return megamorphic; } @Override - public void setMegamorph(boolean megamorph) { - this.megamorph = megamorph; + public void setMegamorphic(boolean value) { + this.megamorphic = value; } @Override diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes; +import java.util.*; + import com.oracle.graal.graph.*; public class ScheduledNode extends Node { @@ -36,4 +38,17 @@ updatePredecessors(scheduledNext, x); scheduledNext = x; } + + @Override + public Map getDebugProperties() { + Map debugProperties = super.getDebugProperties(); + if (this instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) this; + if (stateSplit.stateAfter() != null) { + debugProperties.put("stateAfter", stateSplit.stateAfter().toString(Verbosity.Debugger)); + } + } + return debugProperties; + } + } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon May 14 16:16:22 2012 +0200 @@ -40,7 +40,7 @@ public static final long INVALID_GRAPH_ID = -1; private static final AtomicLong uniqueGraphIds = new AtomicLong(); - private final BeginNode start; + private final StartNode start; private final RiResolvedMethod method; private final long graphId; @@ -94,7 +94,7 @@ return buf.toString(); } - public BeginNode start() { + public StartNode start() { return start; } diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon May 14 16:16:22 2012 +0200 @@ -27,8 +27,11 @@ import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; - - +/** + * A value proxy that is inserted in the frame state of a loop exit for any value that is + * created inside the loop (i.e. was not live on entry to the loop) and is (potentially) + * used after the loop. + */ public class ValueProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable { @Input(notDataflow = true) private BeginNode proxyPoint; @Input private ValueNode value; diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java Mon May 14 16:16:22 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -public abstract class AbstractCallNode extends FixedWithNextNode implements StateSplit, MemoryCheckpoint { +public abstract class AbstractCallNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint { @Input protected final NodeInputList arguments; diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,16 +22,16 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; -public final class BoxNode extends FixedWithNextNode implements StateSplit, Node.IterableNodeType { +public final class BoxNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType { @Input private ValueNode source; private int bci; diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon May 14 16:16:22 2012 +0200 @@ -30,7 +30,7 @@ /** * Creates a memory barrier. */ -public class MembarNode extends FixedWithNextNode implements StateSplit, LIRLowerable, MemoryCheckpoint { +public class MembarNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint { private final int barriers; diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Mon May 14 16:16:22 2012 +0200 @@ -23,17 +23,33 @@ 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.*; +import com.oracle.graal.nodes.type.*; import com.oracle.max.cri.ci.*; -import com.oracle.graal.nodes.type.*; import com.oracle.max.cri.ri.*; public class SafeWriteNode extends SafeAccessNode implements StateSplit, Lowerable{ @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location, long leafGraphId) { super(object, location, StampFactory.forKind(CiKind.Void), leafGraphId); @@ -47,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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon May 14 16:16:22 2012 +0200 @@ -38,6 +38,21 @@ @Input private ValueNode value; private final int displacement; private final CiKind storeKind; + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } public UnsafeStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, CiKind kind) { super(StampFactory.illegal()); diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Mon May 14 16:16:22 2012 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.nodes.type.*; -public final class WriteMemoryCheckpointNode extends FixedWithNextNode implements StateSplit, LIRLowerable, MemoryCheckpoint { +public final class WriteMemoryCheckpointNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint { public WriteMemoryCheckpointNode() { this(StampFactory.illegal()); diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,14 +22,29 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.max.cri.ci.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable { @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } public ValueNode value() { return value; diff -r 80ae8033fe01 -r af76b75d5928 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 Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon May 14 16:16:22 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 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon May 14 16:16:22 2012 +0200 @@ -43,7 +43,7 @@ * {@link MonitorEnterNode}. Optimization phases are free to throw {@link CiBailout} if they detect such cases. * Otherwise, they are detected during LIR construction. */ -public abstract class AccessMonitorNode extends FixedWithNextNode implements StateSplit, MemoryCheckpoint { +public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint { @Input private ValueNode object; private boolean eliminated; diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.cri.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -34,7 +35,7 @@ /** * Implements a type check that results in a {@link ClassCastException} if it fails. */ -public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable { +public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Lowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable { @Input private ValueNode object; @Input private ValueNode targetClassInstruction; @@ -60,6 +61,11 @@ } @Override + public void lower(CiLoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.visitCheckCast(this); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon May 14 16:16:22 2012 +0200 @@ -33,7 +33,7 @@ * Represents an atomic compare-and-swap operation * The result is a boolean that contains whether the value matched the expected value. */ -public class CompareAndSwapNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint { +public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint { @Input private ValueNode object; @Input private ValueNode offset; diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon May 14 16:16:22 2012 +0200 @@ -31,7 +31,7 @@ /** * The {@code ExceptionObject} instruction represents the incoming exception object to an exception handler. */ -public class ExceptionObjectNode extends FixedWithNextNode implements StateSplit, LIRLowerable, MemoryCheckpoint { +public class ExceptionObjectNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint { /** * Constructs a new ExceptionObject instruction. diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java Mon May 14 16:16:22 2012 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.type.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.Representation; public final class IsTypeNode extends BooleanNode implements Canonicalizable, LIRLowerable { @@ -62,6 +63,13 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { + if (objectClass().isConstant()) { + CiConstant constant = objectClass().asConstant(); + CiConstant typeHub = type.getEncoding(Representation.ObjectHub); + assert constant.kind == typeHub.kind; + return ConstantNode.forBoolean(constant.equivalent(typeHub), graph()); + } + // TODO(ls) since a ReadHubNode with an exactType should canonicalize itself to a constant this should actually never happen, maybe turn into an assertion? RiResolvedType exactType = objectClass() instanceof ReadHubNode ? ((ReadHubNode) objectClass()).object().exactType() : null; if (exactType != null) { return ConstantNode.forBoolean(exactType == type(), graph()); diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon May 14 16:16:22 2012 +0200 @@ -31,7 +31,7 @@ /** * This node is used to perform the finalizer registration at the end of the java.lang.Object constructor. */ -public final class RegisterFinalizerNode extends FixedWithNextNode implements StateSplit, Canonicalizable, LIRLowerable { +public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable { @Input private ValueNode object; diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon May 14 16:16:22 2012 +0200 @@ -32,6 +32,21 @@ public final class StoreFieldNode extends AccessFieldNode implements StateSplit { @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } public ValueNode value() { return value; diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon May 14 16:16:22 2012 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.max.cri.ci.*; 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.*; /** * The {@code StoreIndexedNode} represents a write to an array element. @@ -34,6 +34,21 @@ public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable { @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } public ValueNode value() { return value; diff -r 80ae8033fe01 -r af76b75d5928 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 May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon May 14 16:16:22 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); } } } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java Mon May 14 16:16:22 2012 +0200 @@ -108,7 +108,7 @@ MethodCallTargetNode callTarget = invoke.callTarget(); RiResolvedMethod targetMethod = callTarget.targetMethod(); RiResolvedType holder = targetMethod.holder(); - if (holder.isSubtypeOf(runtime.getType(SnippetsInterface.class))) { + if (enclosedInSnippetsClass(holder)) { StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class); if (targetGraph == null) { targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool); @@ -140,6 +140,17 @@ return graph; } + + private boolean enclosedInSnippetsClass(RiResolvedType holder) { + Class enclosingClass = holder.toJava(); + while (enclosingClass != null) { + if (SnippetsInterface.class.isAssignableFrom(enclosingClass)) { + return true; + } + enclosingClass = enclosingClass.getEnclosingClass(); + } + return false; + } }); } diff -r 80ae8033fe01 -r af76b75d5928 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java Mon May 14 16:16:12 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java Mon May 14 16:16:22 2012 +0200 @@ -52,7 +52,7 @@ private void test(String snippet) { StructuredGraph graph = parse(snippet); - new LoweringPhase(runtime()).apply(graph); + new LoweringPhase(runtime(), null).apply(graph); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 80ae8033fe01 -r af76b75d5928 mxtool/mx.py --- a/mxtool/mx.py Mon May 14 16:16:12 2012 +0200 +++ b/mxtool/mx.py Mon May 14 16:16:22 2012 +0200 @@ -1685,6 +1685,9 @@ if suite is None: suite = _mainSuite + def println(out, obj): + out.write(str(obj) + '\n') + updated = False for p in projects(): if p.native: @@ -1898,60 +1901,94 @@ parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') parser.add_argument('--argfile', action='store', help='name of file containing extra javadoc options') parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM') - + parser.add_argument('--wiki', action='store_true', help='generate Confluence Wiki format for package-info.java files') + parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)') + args = parser.parse_args(args) - + # build list of projects to be processed candidates = sorted_deps() if args.projects is not None: candidates = [project(name) for name in args.projects.split(',')] - + + # optionally restrict packages within a project (most useful for wiki) + packages = [] + if args.packages is not None: + packages = [name for name in args.packages.split(',')] + + # the WikiDoclet cannot see the -classpath argument passed to javadoc so we pass the + # full list of projects as an explicit argument, thereby enabling it to map classes + # to projects, which is needed to generate Wiki links to the source code. + # There is no virtue in running the doclet on dependent projects as there are + # no generated links between Wiki pages + docletArgs = [] + if args.wiki: + docDir = 'wikidoc' + toolsDir = project('com.oracle.max.tools').output_dir() + baseDir = project('com.oracle.max.base').output_dir() + dp = os.pathsep.join([toolsDir, baseDir]) + project_list = ','.join(p.name for p in sorted_deps()) + docletArgs = ['-docletpath', dp, '-doclet', 'com.oracle.max.tools.javadoc.wiki.WikiDoclet', '-projects', project_list] + else: + docDir = 'javadoc' + + def check_package_list(p): + if args.wiki: + return True + else: + return not exists(join(p.dir, docDir, 'package-list')) + def assess_candidate(p, projects): if p in projects: return False - if args.force or args.unified or not exists(join(p.dir, 'javadoc', 'package-list')): + if args.force or args.unified or check_package_list(p): projects.append(p) return True return False - + projects = [] for p in candidates: if not p.native: - deps = p.all_deps([], includeLibs=False, includeSelf=False) - for d in deps: - assess_candidate(d, projects) + if not args.wiki: + deps = p.all_deps([], includeLibs=False, includeSelf=False) + for d in deps: + assess_candidate(d, projects) if not assess_candidate(p, projects): log('[package-list file exists - skipping {0}]'.format(p.name)) - + def find_packages(sourceDirs, pkgs=set()): for sourceDir in sourceDirs: for root, _, files in os.walk(sourceDir): if len([name for name in files if name.endswith('.java')]) != 0: - pkgs.add(root[len(sourceDir) + 1:].replace('/','.')) + pkg = root[len(sourceDir) + 1:].replace('/','.') + if (len(packages) == 0) | (pkg in packages): + pkgs.add(pkg) return pkgs extraArgs = [] if args.argfile is not None: extraArgs += ['@' + args.argfile] + memory = '2g' if args.memory is not None: - extraArgs.append('-J-Xmx' + args.memory) + memory = args.memory + memory = '-J-Xmx' + memory if not args.unified: for p in projects: pkgs = find_packages(p.source_dirs(), set()) deps = p.all_deps([], includeLibs=False, includeSelf=False) - links = ['-link', 'http://docs.oracle.com/javase/6/docs/api/'] - out = join(p.dir, 'javadoc') + links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/'] + out = join(p.dir, docDir) for d in deps: - depOut = join(d.dir, 'javadoc') + depOut = join(d.dir, docDir) links.append('-link') links.append(os.path.relpath(depOut, out)) cp = classpath(p.name, includeSelf=True) sp = os.pathsep.join(p.source_dirs()) - log('Generating javadoc for {0} in {1}'.format(p.name, out)) - run([java().javadoc, '-J-Xmx2g', '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + links + extraArgs + list(pkgs)) - log('Generated javadoc for {0} in {1}'.format(p.name, out)) + log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) + run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs)) + log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) else: pkgs = set() sp = [] @@ -1960,14 +1997,14 @@ find_packages(p.source_dirs(), pkgs) sp += p.source_dirs() names.append(p.name) - - links = ['-link', 'http://docs.oracle.com/javase/6/docs/api/'] - out = join(_mainSuite.dir, 'javadoc') + + links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/'] + out = join(_mainSuite.dir, docDir) cp = classpath() sp = os.pathsep.join(sp) - log('Generating javadoc for {0} in {1}'.format(', '.join(names), out)) - run([java().javadoc, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + links + extraArgs + list(pkgs)) - log('Generated javadoc for {0} in {1}'.format(', '.join(names), out)) + log('Generating {2} for {0} in {1}'.format(', '.join(names), out, docDir)) + run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs)) + log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir)) def javap(args): """launch javap with a -classpath option denoting all available classes