# HG changeset patch # User Erik Eckstein # Date 1387178436 -3600 # Node ID f17969ae4a3546e23b18626e33227875912eaea5 # Parent 0393767ae0fc674bf45e2055f679b01ef7b0b931# Parent 652f24858aad19d70183faac69952c361015aec2 Merge diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Dec 16 08:20:36 2013 +0100 @@ -110,6 +110,10 @@ return isEnabled(logFilter); } + public boolean isLogEnabledForMethod() { + return isEnabledForMethod(logFilter); + } + public boolean isMeterEnabled() { return isEnabled(meterFilter); } @@ -118,6 +122,10 @@ return isEnabled(dumpFilter); } + public boolean isDumpEnabledForMethod() { + return isEnabledForMethod(dumpFilter); + } + public boolean isTimeEnabled() { return isEnabled(timerFilter); } @@ -130,6 +138,10 @@ return checkDebugFilter(Debug.currentScope(), filter) && checkMethodFilter(); } + private boolean isEnabledForMethod(DebugFilter filter) { + return filter != null && checkMethodFilter(); + } + private static boolean checkDebugFilter(String currentScope, DebugFilter filter) { return filter != null && filter.matches(currentScope); } diff -r 0393767ae0fc -r f17969ae4a35 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 Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Dec 16 08:20:36 2013 +0100 @@ -83,12 +83,6 @@ private final boolean printIRWithLIR; /** - * Maps constants to variables within the scope of a single block to avoid loading a constant - * more than once per block. - */ - private Map constantsLoadedInCurrentBlock; - - /** * Handle for an operation that loads a constant into a variable. The operation starts in the * first block where the constant is used but will eventually be * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the @@ -246,63 +240,46 @@ if (nodeOperands == null) { return null; } - Value operand = !node.isExternal() ? nodeOperands.get(node) : null; + Value operand = nodeOperands.get(node); if (operand == null) { return getConstantOperand(node); } return operand; } - /** - * Controls whether commoning is performed on {@linkplain #canInlineConstant(Constant) - * non-inlinable} constants. - */ - private static final boolean CommonConstantLoads = Boolean.parseBoolean(System.getProperty("graal.commonConstantLoads", "true")); - private Value getConstantOperand(ValueNode node) { if (!ConstantNodeRecordsUsages) { Constant value = node.asConstant(); if (value != null) { if (canInlineConstant(value)) { - return !node.isExternal() ? setResult(node, value) : value; + return setResult(node, value); } else { Variable loadedValue; - if (CommonConstantLoads) { - if (constantLoads == null) { - constantLoads = new HashMap<>(); - } - LoadConstant load = constantLoads.get(value); - if (load == null) { - int index = lir.lir(currentBlock).size(); - // loadedValue = newVariable(value.getPlatformKind()); - loadedValue = emitMove(value); - LIRInstruction op = lir.lir(currentBlock).get(index); - constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op)); + if (constantLoads == null) { + constantLoads = new HashMap<>(); + } + LoadConstant load = constantLoads.get(value); + if (load == null) { + int index = lir.lir(currentBlock).size(); + // loadedValue = newVariable(value.getPlatformKind()); + loadedValue = emitMove(value); + LIRInstruction op = lir.lir(currentBlock).get(index); + constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op)); + } else { + Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock); + loadedValue = load.variable; + if (dominator != load.block) { + if (load.index >= 0) { + // Replace the move with a filler op so that the operation + // list does not need to be adjusted. + List instructions = lir.lir(load.block); + instructions.set(load.index, new NoOp(null, -1)); + load.index = -1; + } } else { - Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock); - loadedValue = load.variable; - if (dominator != load.block) { - if (load.index >= 0) { - List instructions = lir.lir(load.block); - instructions.set(load.index, new NoOp(null, -1)); - load.index = -1; - } - } else { - assert load.block != currentBlock || load.index < lir.lir(currentBlock).size(); - } - load.block = dominator; + assert load.block != currentBlock || load.index < lir.lir(currentBlock).size(); } - } else { - if (constantsLoadedInCurrentBlock == null) { - constantsLoadedInCurrentBlock = new HashMap<>(); - loadedValue = null; - } else { - loadedValue = constantsLoadedInCurrentBlock.get(value); - } - if (loadedValue == null) { - loadedValue = emitMove(value); - constantsLoadedInCurrentBlock.put(value, loadedValue); - } + load.block = dominator; } return loadedValue; } @@ -455,7 +432,6 @@ } currentBlock = block; - resetLoadedConstants(); // set up the list of LIR instructions assert lir.lir(block) == null : "LIR list already computed for this block"; @@ -519,12 +495,6 @@ } } - private void resetLoadedConstants() { - if (constantsLoadedInCurrentBlock != null && !constantsLoadedInCurrentBlock.isEmpty()) { - constantsLoadedInCurrentBlock.clear(); - } - } - protected abstract boolean peephole(ValueNode valueNode); private boolean hasBlockEnd(Block block) { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Dec 16 08:20:36 2013 +0100 @@ -69,6 +69,17 @@ return ENABLED; } + public static boolean isDumpEnabledForMethod() { + if (!ENABLED) { + return false; + } + DebugConfig config = DebugScope.getConfig(); + if (config == null) { + return false; + } + return config.isDumpEnabledForMethod(); + } + public static boolean isDumpEnabled() { return ENABLED && DebugScope.getInstance().isDumpEnabled(); } @@ -81,6 +92,17 @@ return ENABLED && DebugScope.getInstance().isTimeEnabled(); } + public static boolean isLogEnabledForMethod() { + if (!ENABLED) { + return false; + } + DebugConfig config = DebugScope.getConfig(); + if (config == null) { + return false; + } + return config.isLogEnabledForMethod(); + } + public static boolean isLogEnabled() { return ENABLED && DebugScope.getInstance().isLogEnabled(); } @@ -431,6 +453,10 @@ return isLogEnabled; } + public boolean isLogEnabledForMethod() { + return isLogEnabled; + } + @Override public boolean isMeterEnabled() { return isMeterEnabled; @@ -441,6 +467,10 @@ return isDumpEnabled; } + public boolean isDumpEnabledForMethod() { + return isDumpEnabled; + } + @Override public boolean isTimeEnabled() { return isTimerEnabled; diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Mon Dec 16 08:20:36 2013 +0100 @@ -36,6 +36,12 @@ boolean isLogEnabled(); /** + * Determines if logging can be enabled in the current method, regardless of the + * {@linkplain Debug#currentScope() current debug scope}. + */ + boolean isLogEnabledForMethod(); + + /** * Determines if metering is enabled in the {@linkplain Debug#currentScope() current debug * scope}. * @@ -52,6 +58,12 @@ boolean isDumpEnabled(); /** + * Determines if dumping can be enabled in the current method, regardless of the + * {@linkplain Debug#currentScope() current debug scope}. + */ + boolean isDumpEnabledForMethod(); + + /** * Adds an object the context used by this configuration to do filtering. */ void addToContext(Object o); diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Mon Dec 16 08:20:36 2013 +0100 @@ -38,6 +38,10 @@ return delegate.isLogEnabled(); } + public boolean isLogEnabledForMethod() { + return delegate.isLogEnabledForMethod(); + } + @Override public boolean isMeterEnabled() { return delegate.isMeterEnabled(); @@ -48,6 +52,10 @@ return delegate.isDumpEnabled(); } + public boolean isDumpEnabledForMethod() { + return delegate.isDumpEnabledForMethod(); + } + @Override public boolean isTimeEnabled() { return delegate.isTimeEnabled(); diff -r 0393767ae0fc -r f17969ae4a35 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 Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Dec 16 08:20:36 2013 +0100 @@ -75,11 +75,6 @@ NodeChangedListener usagesDroppedToZeroListener; private final HashMap cachedNodes = new HashMap<>(); - /** - * Determines if external nodes will use {@link Graph}'s canonicalization cache. - */ - public static final boolean CacheExternalNodesInGraph = Boolean.parseBoolean(System.getProperty("graal.cacheExternalNodesInGraph", "false")); - private static final class CacheEntry { private final Node node; @@ -347,24 +342,6 @@ return uniqueHelper(node, true); } - /** - * Looks for a node similar to {@code node}. If not found, {@code node} is added to a - * cache in this graph used to canonicalize nodes. - *

- * Note that node must implement {@link ValueNumberable} and must be an - * {@linkplain Node#isExternal() external} node. - * - * @return a node similar to {@code node} if one exists, otherwise {@code node} - */ - public T uniqueExternal(T node) { - assert node.isExternal() : node; - assert node instanceof ValueNumberable : node; - if (!CacheExternalNodesInGraph) { - return node; - } - return uniqueHelper(node, false); - } - @SuppressWarnings("unchecked") T uniqueHelper(T node, boolean addIfMissing) { assert node.getNodeClass().valueNumberable(); @@ -381,14 +358,13 @@ } void putNodeIntoCache(Node node) { - assert node.isExternal() || node.graph() == this || node.graph() == null; + assert node.graph() == this || node.graph() == null; assert node.getNodeClass().valueNumberable(); assert node.getNodeClass().isLeafNode() : node.getClass(); cachedNodes.put(new CacheEntry(node), node); } Node findNodeInCache(Node node) { - assert !node.isExternal() || CacheExternalNodesInGraph; CacheEntry key = new CacheEntry(node); Node result = cachedNodes.get(key); if (result != null && result.isDeleted()) { @@ -589,7 +565,7 @@ * ordering between the nodes within the list. */ public boolean maybeCompress() { - if (Debug.isEnabled()) { + if (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()) { return false; } int liveNodeCount = getNodeCount(); @@ -785,7 +761,6 @@ } void register(Node node) { - assert !node.isExternal(); assert node.id() == Node.INITIAL_ID; if (nodes.length == nodesSize) { nodes = Arrays.copyOf(nodes, (nodesSize * 2) + 1); diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Dec 16 08:20:36 2013 +0100 @@ -157,11 +157,9 @@ } /** - * Gets the graph context of this node. This must not be called for {@linkplain #isExternal() - * external} nodes. + * Gets the graph context of this node. */ public Graph graph() { - assert !isExternal() : "external node has no graph: " + this; return graph; } @@ -288,15 +286,6 @@ } /** - * Determines if this node has a {@linkplain #graph() graph} context or is external to any - * graph. The {@link #graph()} method must only be called on nodes for which this method returns - * true. - */ - public boolean isExternal() { - return false; - } - - /** * Finds the index of the last non-null entry in a node array. The search assumes that all * non-null entries precede the first null entry in the array. * @@ -531,7 +520,6 @@ assert assertFalse(other == this, "cannot replace a node with itself"); assert assertFalse(isDeleted(), "cannot replace deleted node"); assert assertTrue(other == null || !other.isDeleted(), "cannot replace with deleted node %s", other); - assert assertTrue(other == null || other.isExternal() || other.graph() == graph, "cannot replace with node in different graph: %s", other == null || other.isExternal() ? null : other.graph()); return true; } @@ -588,7 +576,7 @@ assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); for (Node input : inputs()) { - if (input.recordsUsages() && !input.isExternal()) { + if (input.recordsUsages()) { removeThisFromUsages(input); if (input.usages().isEmpty()) { NodeChangedListener listener = graph.usagesDroppedToZeroListener; @@ -637,7 +625,6 @@ } public final Node copyWithInputs() { - assert !isExternal(); Node newNode = clone(graph); NodeClass clazz = getNodeClass(); clazz.copyInputs(this, newNode); @@ -676,7 +663,6 @@ } final Node clone(Graph into, boolean clearInputsAndSuccessors) { - assert !isExternal(); NodeClass nodeClass = getNodeClass(); if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) { Node otherNode = into.findNodeInCache(this); @@ -711,23 +697,6 @@ return newNode; } - /** - * Determines if a given node is {@linkplain Graph#uniqueExternal(Node) unique} within a given - * graph if the node is non-null and {@linkplain #isExternal() external}. - * - * @param node node to check - * @param graph graph context to use - * @return true if node is null, not external or unique within {@code graph} otherwise raises a - * {@link VerificationError} - */ - public static boolean verifyUniqueIfExternal(Node node, Graph graph) { - if (node != null && node.isExternal() && Graph.CacheExternalNodesInGraph) { - Node cached = graph.findNodeInCache(node); - node.assertTrue(cached == node, "external node does not match canonical node %s", cached); - } - return true; - } - protected void afterClone(@SuppressWarnings("unused") Node other) { } @@ -736,8 +705,6 @@ assertTrue(graph() != null, "null graph"); for (Node input : inputs()) { assertTrue(!input.recordsUsages() || input.usages().contains(this), "missing usage in input %s", input); - assert verifyUniqueIfExternal(input, graph()); - assertTrue(input.isExternal() || input.graph() == graph(), "mismatching graph in input %s", input); } for (Node successor : successors()) { assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor()); @@ -791,9 +758,7 @@ } /** - * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. For this - * reason, {@linkplain #isExternal() external} nodes should still be {@link Graph#unique unique} - * within the context of a graph. + * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. */ @Override public final int hashCode() { @@ -801,8 +766,7 @@ } /** - * Equality tests must rely solely on identity. For this reason, {@linkplain #isExternal() - * external} nodes should still be {@link Graph#unique unique} within the context of a graph. + * Equality tests must rely solely on identity. */ @Override public final boolean equals(Object obj) { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Dec 16 08:20:36 2013 +0100 @@ -937,7 +937,6 @@ if (input != null) { Node newInput = duplicationReplacement.replacement(input, true); node.updateUsages(null, newInput); - assert Node.verifyUniqueIfExternal(newInput, node.graph()); assert newInput == null || fieldTypes.get(inputOffsets[index]).isAssignableFrom(newInput.getClass()) : "Can not assign " + newInput.getClass() + " to " + fieldTypes.get(inputOffsets[index]) + " in " + node; putNode(node, inputOffsets[index], newInput); @@ -994,7 +993,6 @@ Node oldNode = list.get(i); if (oldNode != null) { Node newNode = duplicationReplacement.replacement(oldNode, true); - assert Node.verifyUniqueIfExternal(newNode, node.graph()); result.set(i, newNode); } } @@ -1079,7 +1077,6 @@ } public boolean replaceFirstInput(Node node, Node old, Node other) { - assert Node.verifyUniqueIfExternal(other, node.graph()); int index = 0; while (index < directInputCount) { Node input = getNode(node, inputOffsets[index]); @@ -1384,9 +1381,6 @@ InplaceUpdateClosure replacementClosure = new InplaceUpdateClosure() { public Node replacement(Node node, boolean isInput) { - if (node.isExternal() && node instanceof ValueNumberable) { - return graph.uniqueExternal(node); - } Node target = newNodes.get(node); if (target == null) { Node replacement = node; diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Mon Dec 16 08:20:36 2013 +0100 @@ -84,7 +84,7 @@ } public boolean isOutsideLoop(Node n) { - return n.isExternal() || !whole().contains(n); + return !whole().contains(n); } public LoopBeginNode loopBegin() { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Dec 16 08:20:36 2013 +0100 @@ -71,10 +71,7 @@ @SuppressWarnings("unchecked") public New getDuplicatedNode(Old n) { assert isDuplicate(); - if (!n.isExternal()) { - return (New) duplicationMap.get(n); - } - return n; + return (New) duplicationMap.get(n); } protected void putDuplicatedNode(Old oldNode, New newNode) { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes; -import static com.oracle.graal.graph.Graph.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -68,40 +66,17 @@ return value; } - private static boolean ConstantNodesAreExternal = Boolean.parseBoolean(System.getProperty("graal.constantNodesAreExternal", "true")); - /** * Used to measure the impact of ConstantNodes not recording their usages. This and all code * predicated on this value being true will be removed at some point. */ - public static final boolean ConstantNodeRecordsUsages = !ConstantNodesAreExternal && Boolean.getBoolean("graal.constantNodeRecordsUsages"); + public static final boolean ConstantNodeRecordsUsages = Boolean.getBoolean("graal.constantNodeRecordsUsages"); @Override public boolean recordsUsages() { return ConstantNodeRecordsUsages; } - @Override - public boolean isDeleted() { - if (!ConstantNodesAreExternal) { - return super.isDeleted(); - } - return false; - } - - @Override - public boolean isAlive() { - if (!ConstantNodesAreExternal) { - return super.isAlive(); - } - return true; - } - - @Override - public boolean isExternal() { - return ConstantNodesAreExternal; - } - /** * Computes the usages of this node by iterating over all the nodes in the graph, searching for * those that have this node as an input. @@ -121,23 +96,10 @@ /** * Gathers all the {@link ConstantNode}s that are inputs to the - * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. This is an expensive - * operation that should only be used in test/verification/AOT code. + * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. */ public static NodeIterable getConstantNodes(StructuredGraph graph) { - if (!ConstantNodesAreExternal) { - return graph.getNodes().filter(ConstantNode.class); - } - - Map result = new HashMap<>(); - for (Node node : graph.getNodes()) { - for (Node input : node.inputs()) { - if (input instanceof ConstantNode) { - result.put((ConstantNode) input, (ConstantNode) input); - } - } - } - return new ConstantNodeList(result.keySet()); + return graph.getNodes().filter(ConstantNode.class); } /** @@ -150,9 +112,7 @@ for (Node usage : usages) { usage.replaceFirstInput(this, replacement); } - if (!isExternal()) { - graph.removeFloating(this); - } + graph.removeFloating(this); } else { assert graph == graph(); graph().replaceFloating(this, replacement); @@ -184,10 +144,6 @@ if (constant.getKind().getStackKind() == Kind.Int && constant.getKind() != Kind.Int) { return forInt(constant.asInt(), graph); } - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - Stamp stamp = constant.getKind() == Kind.Object ? StampFactory.forConstant(constant, metaAccess) : StampFactory.forConstant(constant); - return graph.asConstantNode(constant, stamp); - } if (constant.getKind() == Kind.Object) { return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess))); } else { @@ -210,9 +166,6 @@ * @return a node for a double constant */ public static ConstantNode forDouble(double d, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forDouble(d), null); - } return unique(graph, createPrimitive(Constant.forDouble(d))); } @@ -223,9 +176,6 @@ * @return a node for a float constant */ public static ConstantNode forFloat(float f, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forFloat(f), null); - } return unique(graph, createPrimitive(Constant.forFloat(f))); } @@ -236,9 +186,6 @@ * @return a node for an long constant */ public static ConstantNode forLong(long i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forLong(i), null); - } return unique(graph, createPrimitive(Constant.forLong(i))); } @@ -249,9 +196,6 @@ * @return a node for an integer constant */ public static ConstantNode forInt(int i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forInt(i), null); - } return unique(graph, createPrimitive(Constant.forInt(i))); } @@ -262,9 +206,6 @@ * @return a node representing the boolean */ public static ConstantNode forBoolean(boolean i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(i ? Constant.INT_1 : Constant.INT_0, null); - } return unique(graph, createPrimitive(Constant.forInt(i ? 1 : 0))); } @@ -275,9 +216,6 @@ * @return a node representing the byte */ public static ConstantNode forByte(byte i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forInt(i), null); - } return unique(graph, createPrimitive(Constant.forInt(i))); } @@ -288,9 +226,6 @@ * @return a node representing the char */ public static ConstantNode forChar(char i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forInt(i), null); - } return unique(graph, createPrimitive(Constant.forInt(i))); } @@ -301,9 +236,6 @@ * @return a node representing the short */ public static ConstantNode forShort(short i, StructuredGraph graph) { - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(Constant.forInt(i), null); - } return unique(graph, createPrimitive(Constant.forInt(i))); } @@ -316,18 +248,11 @@ public static ConstantNode forObject(Object o, MetaAccessProvider metaAccess, StructuredGraph graph) { assert !(o instanceof Constant) : "wrapping a Constant into a Constant"; Constant constant = Constant.forObject(o); - if (ConstantNodesAreExternal && !CacheExternalNodesInGraph) { - return graph.asConstantNode(constant, StampFactory.forConstant(constant, metaAccess)); - } return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess))); } private static ConstantNode unique(StructuredGraph graph, ConstantNode node) { - if (!ConstantNodesAreExternal) { - return graph.unique(node); - } - assert CacheExternalNodesInGraph; - return graph.uniqueExternal(node); + return graph.unique(node); } public static ConstantNode forIntegerKind(Kind kind, long value, StructuredGraph graph) { @@ -390,15 +315,4 @@ return super.toString(verbosity); } } - - static class ConstantNodeList extends NodeList { - - public ConstantNodeList(Collection nodes) { - super(nodes.toArray(new ConstantNode[nodes.size()])); - } - - @Override - protected void update(ConstantNode oldNode, ConstantNode newNode) { - } - } } diff -r 0393767ae0fc -r f17969ae4a35 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 Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Dec 16 08:20:36 2013 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /** @@ -82,38 +81,6 @@ private boolean isAfterFloatingReadPhase = false; /** - * Used to create canonical {@link ConstantNode}s for {@link Constant}s in this graph. - */ - private Map constants; - - /** - * Gets a node for a given constant that is unique/canonical within this graph. - * - * @param stamp the stamp for an {@link Kind#Object} constant (ignored otherwise) - */ - public ConstantNode asConstantNode(Constant constant, Stamp stamp) { - ConstantNode node; - if (constants == null) { - constants = new HashMap<>(); - node = null; - } else { - node = constants.get(constant); - } - if (node == null) { - node = new ConstantNode(constant, stamp == null ? StampFactory.forConstant(constant) : stamp); - constants.put(constant, node); - } - return node; - } - - @SuppressWarnings("unchecked") - @Override - public T uniqueExternal(T node) { - ConstantNode cn = (ConstantNode) node; - return (T) asConstantNode(cn.asConstant(), cn.stamp()); - } - - /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. */ diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -31,10 +30,9 @@ /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations. */ -public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider { +public class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider { @Input private ValueNode length; - private final boolean fillContents; @Override public ValueNode length() { @@ -49,16 +47,8 @@ * @param fillContents determines whether the array elements should be initialized to zero/null. */ protected AbstractNewArrayNode(Stamp stamp, ValueNode length, boolean fillContents) { - super(stamp); + super(stamp, fillContents); this.length = length; - this.fillContents = fillContents; - } - - /** - * @return true if the elements of the array will be initialized. - */ - public boolean fillContents() { - return fillContents; } /** @@ -77,23 +67,11 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (usages().isEmpty()) { - Stamp stamp = length.stamp(); - if (stamp instanceof IntegerStamp && ((IntegerStamp) stamp).isPositive()) { - return null; - } + public void simplify(SimplifierTool tool) { + Stamp stamp = length.stamp(); + if (stamp instanceof IntegerStamp && ((IntegerStamp) stamp).isPositive()) { + // otherwise, removing the allocation might swallow a NegativeArraySizeException + super.simplify(tool); } - return this; - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } - - @Override - public boolean canDeoptimize() { - return true; } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2009, 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.nodes.java; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes. + */ +public class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable { + + private final boolean fillContents; + + /** + * Constructs a new AbstractNewObjectNode. + * + * @param stamp the stamp of the newly created object + * @param fillContents determines if the object's contents should be initialized to zero/null. + */ + protected AbstractNewObjectNode(Stamp stamp, boolean fillContents) { + super(stamp); + this.fillContents = fillContents; + } + + /** + * @return true if the object's contents should be initialized to zero/null. + */ + public boolean fillContents() { + return fillContents; + } + + @Override + public void simplify(SimplifierTool tool) { + // poor man's escape analysis: check if the object can be trivially removed + for (Node usage : usages()) { + if (usage instanceof FixedValueAnchorNode) { + if (((FixedValueAnchorNode) usage).usages().isNotEmpty()) { + return; + } + } else if (usage instanceof WriteNode) { + if (((WriteNode) usage).object() != this || usage.usages().isNotEmpty()) { + // we would need to fix up the memory graph if the write has usages + return; + } + } else { + return; + } + } + for (Node usage : usages().snapshot()) { + List snapshot = usage.inputs().snapshot(); + graph().removeFixed((FixedWithNextNode) usage); + for (Node input : snapshot) { + tool.removeIfUnused(input); + } + } + List snapshot = inputs().snapshot(); + graph().removeFixed(this); + for (Node input : snapshot) { + tool.removeIfUnused(input); + } + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } + + @Override + public boolean canDeoptimize() { + return true; + } +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import java.lang.reflect.*; +import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -34,7 +35,7 @@ * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a * compile-time constant. */ -public class DynamicNewArrayNode extends AbstractNewArrayNode implements Canonicalizable { +public class DynamicNewArrayNode extends AbstractNewArrayNode { @Input private ValueNode elementType; @@ -52,15 +53,20 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (elementType.isConstant()) { + public void simplify(SimplifierTool tool) { + if (isAlive() && elementType.isConstant()) { Class elementClass = (Class) elementType.asConstant().asObject(); if (elementClass != null && !(elementClass.equals(void.class))) { ResolvedJavaType javaType = tool.getMetaAccess().lookupJavaType(elementClass); - return graph().add(new NewArrayNode(javaType, length(), fillContents())); + NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length(), fillContents())); + List snapshot = inputs().snapshot(); + graph().replaceFixedWithFixed(this, newArray); + for (Node input : snapshot) { + tool.removeIfUnused(input); + } + tool.addToWorkList(newArray); } } - return this; } @NodeIntrinsic diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -36,10 +35,9 @@ * The {@code NewInstanceNode} represents the allocation of an instance class object. */ @NodeInfo(nameTemplate = "New {p#instanceClass/s}") -public class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation { +public class NewInstanceNode extends AbstractNewObjectNode implements VirtualizableAllocation { private final ResolvedJavaType instanceClass; - private final boolean fillContents; /** * Constructs a NewInstanceNode. @@ -49,10 +47,9 @@ * zero/null. */ public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { - super(StampFactory.exactNonNull(type)); + super(StampFactory.exactNonNull(type), fillContents); assert !type.isArray(); this.instanceClass = type; - this.fillContents = fillContents; } /** @@ -64,27 +61,6 @@ return instanceClass; } - /** - * @return true if the fields of the new object will be initialized. - */ - public boolean fillContents() { - return fillContents; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (usages().isEmpty()) { - return null; - } else { - return this; - } - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } - @Override public void virtualize(VirtualizerTool tool) { /* @@ -107,9 +83,4 @@ protected ConstantNode defaultFieldValue(ResolvedJavaField field) { return ConstantNode.defaultForKind(field.getType().getKind(), graph()); } - - @Override - public boolean canDeoptimize() { - return true; - } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Dec 16 08:20:36 2013 +0100 @@ -123,7 +123,7 @@ } public static void killWithUnusedFloatingInputs(Node node) { - if (node.recordsUsages() && !node.isExternal()) { + if (node.recordsUsages()) { List floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); node.safeDelete(); @@ -354,14 +354,14 @@ * Process a node as part of this search. * * @param node the next node encountered in the search - * @param worklist if non-null and {@code node} is not external, {@code node} will be added - * to this list. Otherwise, {@code node} is treated as a candidate result. + * @param worklist if non-null, {@code node} will be added to this list. Otherwise, + * {@code node} is treated as a candidate result. * @return true if the search should continue, false if a definitive {@link #result} has * been found */ private boolean process(ValueNode node, NodeWorkList worklist) { if (node.isAlive()) { - if (node.isExternal() || worklist == null) { + if (worklist == null) { if (result == null) { // Initial candidate result: continue search result = node; diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Mon Dec 16 08:20:36 2013 +0100 @@ -112,17 +112,13 @@ for (Node node : graph.getNodes()) { if (flood.isMarked(node)) { for (Node input : node.inputs()) { - if (!input.isExternal()) { - flood.add(input); - } + flood.add(input); } } } for (Node current : flood) { for (Node input : current.inputs()) { - if (!input.isExternal()) { - flood.add(input); - } + flood.add(input); } } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Dec 16 08:20:36 2013 +0100 @@ -27,6 +27,7 @@ import java.util.*; import java.util.Map.Entry; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; @@ -34,7 +35,6 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; @@ -54,13 +54,6 @@ * does the actual control-flow expansion of the remaining {@link GuardNode GuardNodes}. */ public class GuardLoweringPhase extends BasePhase { - static class Options { - //@formatter:off - @Option(help = "") - public static final OptionValue UseGuardIdAsSpeculationId = new OptionValue<>(false); - //@formatter:on - } - private static class UseImplicitNullChecks extends ScheduledNodeIterator { private final IdentityHashMap nullGuarded = new IdentityHashMap<>(); @@ -134,9 +127,9 @@ private final Block block; private boolean useGuardIdAsSpeculationId; - public LowerGuards(Block block) { + public LowerGuards(Block block, boolean useGuardIdAsSpeculationId) { this.block = block; - this.useGuardIdAsSpeculationId = Options.UseGuardIdAsSpeculationId.getValue(); + this.useGuardIdAsSpeculationId = useGuardIdAsSpeculationId; } @Override @@ -203,6 +196,6 @@ if (OptImplicitNullChecks.getValue() && implicitNullCheckLimit > 0) { new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(block, schedule); } - new LowerGuards(block).processNodes(block, schedule); + new LowerGuards(block, Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()).processNodes(block, schedule); } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Dec 16 08:20:36 2013 +0100 @@ -40,7 +40,6 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; -import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -1433,12 +1432,7 @@ if (returnNode.result() instanceof LocalNode) { returnValue = localReplacement.replacement(returnNode.result()); } else if (returnNode.result() != null) { - returnValue = returnNode.result(); - if (!returnValue.isExternal()) { - returnValue = duplicates.get(returnValue); - } else if (returnValue instanceof ValueNumberable) { - returnValue = graph.uniqueExternal(returnValue); - } + returnValue = duplicates.get(returnNode.result()); } invoke.asNode().replaceAtUsages(returnValue); Node returnDuplicate = duplicates.get(returnNode); diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Dec 16 08:20:36 2013 +0100 @@ -324,7 +324,7 @@ assert (unscheduledUsages = getUnscheduledUsages(node)) != null; Mark preLoweringMark = node.graph().getMark(); ((Lowerable) node).lower(loweringTool); - if (node == startAnchor && node.isDeleted()) { + if (loweringTool.guardAnchor.asNode().isDeleted()) { loweringTool.guardAnchor = BeginNode.prevBegin(nextNode); } assert checkPostNodeLowering(node, loweringTool, preLoweringMark, unscheduledUsages); diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Mon Dec 16 08:20:36 2013 +0100 @@ -365,7 +365,7 @@ // stop iterating: fixed nodes within the given set are traversal roots // anyway, and all other // fixed nodes are known to be outside. - } else if (!node.isExternal() && !aboveBound.isMarked(node)) { + } else if (!aboveBound.isMarked(node)) { worklist.add(node); aboveBound.mark(node); } @@ -378,9 +378,7 @@ while (!worklist.isEmpty()) { Node current = worklist.remove(); for (Node input : current.inputs()) { - if (!input.isExternal()) { - aboveClosure.apply(current, input); - } + aboveClosure.apply(current, input); } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Dec 16 08:20:36 2013 +0100 @@ -759,10 +759,6 @@ * Determines the earliest block in which the given node can be scheduled. */ private Block earliestBlock(Node node) { - if (node.isExternal()) { - return cfg.getStartBlock(); - } - Block earliest = cfg.getNodeToBlock().get(node); if (earliest != null) { return earliest; @@ -1088,7 +1084,7 @@ for (Node input : state.inputs()) { if (input instanceof VirtualState) { addUnscheduledToLatestSorting(b, (VirtualState) input, sortedInstructions, visited, reads, beforeLastLocation); - } else if (!input.isExternal()) { + } else { addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); } } @@ -1105,7 +1101,7 @@ if (input instanceof FrameState) { assert state == null; state = (FrameState) input; - } else if (!input.isExternal()) { + } else { addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Dec 16 08:20:36 2013 +0100 @@ -105,7 +105,6 @@ } private final ConstantPool constantPool; - private final Map externalNodeIds; private final ByteBuffer buffer; private final WritableByteChannel channel; @@ -113,7 +112,6 @@ constantPool = new ConstantPool(); buffer = ByteBuffer.allocateDirect(256 * 1024); this.channel = channel; - this.externalNodeIds = new HashMap<>(); } public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException { @@ -389,25 +387,9 @@ } } - /** - * Should be higher than any internal {@link Node#getId() node id}. - */ - @SuppressWarnings("javadoc") private static final int FIRST_EXTERNAL_NODE_ID = Integer.getInteger("graal.binaryGraphPrinter.firstExternalNodeId", 10000000); - @SuppressWarnings("deprecation") - private int getNodeId(Node node) { - if (!node.isExternal()) { - assert node.getId() < FIRST_EXTERNAL_NODE_ID : "internal node ids exceeded lowest external node id (" + FIRST_EXTERNAL_NODE_ID + - ") - use graal.binaryGraphPrinter.firstExternalNodeId system property to increase the latter"; - return node.getId(); - } else { - Integer id = externalNodeIds.get(node); - if (id == null) { - id = FIRST_EXTERNAL_NODE_ID + externalNodeIds.size(); - externalNodeIds.put(node, id); - } - return id; - } + private static int getNodeId(Node node) { + return node.getId(); } private void writeNodes(Graph graph) throws IOException { @@ -419,16 +401,8 @@ } } Map props = new HashMap<>(); - Map externalNodes = new HashMap<>(); - for (Node node : graph.getNodes()) { - for (Node input : node.inputs()) { - if (input.isExternal()) { - externalNodes.put(input, getNodeId(input)); - } - } - } - writeInt(graph.getNodeCount() + externalNodes.size()); + writeInt(graph.getNodeCount()); for (Node node : graph.getNodes()) { NodeClass nodeClass = node.getNodeClass(); @@ -453,22 +427,6 @@ props.clear(); } - for (Map.Entry e : externalNodes.entrySet()) { - Node node = e.getKey(); - NodeClass nodeClass = node.getNodeClass(); - node.getDebugProperties(props); - writeInt(e.getValue()); - writePoolObject(nodeClass); - writeByte(0); - // properties - writeShort((char) props.size()); - for (Entry entry : props.entrySet()) { - String key = entry.getKey().toString(); - writePoolObject(key); - writePropertyObject(entry.getValue()); - } - props.clear(); - } } private void writeEdges(Node node, Collection positions) throws IOException { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Dec 16 08:20:36 2013 +0100 @@ -60,7 +60,7 @@ @Option(help = "") public static final OptionValue TruffleInliningMaxRecursiveDepth = new OptionValue<>(2); @Option(help = "") - public static final OptionValue TruffleInliningMaxCallerSize = new OptionValue<>(2500); + public static final OptionValue TruffleInliningMaxCallerSize = new OptionValue<>(2250); @Option(help = "") public static final OptionValue TruffleInliningMaxCalleeSize = new OptionValue<>(250); @Option(help = "") diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Mon Dec 16 08:20:36 2013 +0100 @@ -231,7 +231,7 @@ public ValueNode getScalarAlias(ValueNode node) { assert !(node instanceof VirtualObjectNode); - if (node == null || !node.isAlive() || node.isExternal() || aliases.isNew(node)) { + if (node == null || !node.isAlive() || aliases.isNew(node)) { return node; } ValueNode result = aliases.get(node); diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Dec 16 08:20:36 2013 +0100 @@ -611,7 +611,7 @@ } public ObjectState getObjectState(PartialEscapeBlockState state, ValueNode value) { - if (value == null || value.isExternal()) { + if (value == null) { return null; } if (value.isAlive() && !aliases.isNew(value)) { diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Mon Dec 16 08:20:36 2013 +0100 @@ -69,22 +69,18 @@ for (Node node : graph.getNodes()) { if (flood.isMarked(node)) { for (Node input : node.inputs()) { - if (!input.isExternal()) { - flood.add(input); - if (!path.containsKey(input)) { - path.put(input, node); - } + flood.add(input); + if (!path.containsKey(input)) { + path.put(input, node); } } } } for (Node current : flood) { for (Node input : current.inputs()) { - if (!input.isExternal()) { - flood.add(input); - if (!path.containsKey(input)) { - path.put(input, current); - } + flood.add(input); + if (!path.containsKey(input)) { + path.put(input, current); } } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013, 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.truffle.api.test.utilities; + +import static org.junit.Assert.*; +import org.junit.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; + +public class AlwaysValidAssumptionTest { + + @Test + public void testCheck() throws InvalidAssumptionException { + final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE; + assumption.check(); + } + + @Test + public void testIsValid() { + final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE; + assertTrue(assumption.isValid()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testCannotInvalidate() { + final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE; + assumption.invalidate(); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, 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.truffle.api.test.utilities; + +import static org.junit.Assert.*; +import org.junit.*; + +import com.oracle.truffle.api.utilities.*; + +public class AssumedValueTest { + + @Test + public void testGet() { + final AssumedValue assumedValue = new AssumedValue<>("assumed-value", "1"); + assertEquals("1", assumedValue.get()); + } + + @Test + public void testSet() { + final AssumedValue assumedValue = new AssumedValue<>("assumed-value", "1"); + assertEquals("1", assumedValue.get()); + assumedValue.set("2"); + assertEquals("2", assumedValue.get()); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.truffle.api.test.utilities; + +import org.junit.*; + +import com.oracle.truffle.api.utilities.*; + +public class BranchProfileTest { + + @Test + public void testEnter() { + BranchProfile profile = new BranchProfile(); + profile.enter(); + profile.enter(); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 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.truffle.api.test.utilities; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.utilities.*; + +public class CyclicAssumptionTest { + + @Test + public void testIsValid() { + final CyclicAssumption assumption = new CyclicAssumption("cyclic-assumption"); + assertTrue(assumption.getAssumption().isValid()); + } + + @Test + public void testInvalidate() { + final CyclicAssumption cyclicAssumption = new CyclicAssumption("cyclic-assumption"); + + final Assumption firstAssumption = cyclicAssumption.getAssumption(); + assertEquals("cyclic-assumption", firstAssumption.getName()); + assertTrue(firstAssumption.isValid()); + + cyclicAssumption.invalidate(); + + assertFalse(firstAssumption.isValid()); + + final Assumption secondAssumption = cyclicAssumption.getAssumption(); + assertEquals("cyclic-assumption", secondAssumption.getName()); + assertTrue(secondAssumption.isValid()); + + cyclicAssumption.invalidate(); + + assertFalse(firstAssumption.isValid()); + assertFalse(secondAssumption.isValid()); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013, 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.truffle.api.test.utilities; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; + +public class UnionAssumptionTest { + + @Test + public void testIsValid() { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + assertTrue(union.isValid()); + } + + @Test + public void testCheck() throws InvalidAssumptionException { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + union.check(); + } + + @Test + public void testFirstInvalidateIsValid() { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + first.invalidate(); + + assertFalse(union.isValid()); + } + + @Test(expected = InvalidAssumptionException.class) + public void testFirstInvalidateCheck() throws InvalidAssumptionException { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + first.invalidate(); + + union.check(); + } + + @Test + public void testSecondInvalidateIsValid() { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + second.invalidate(); + + assertFalse(union.isValid()); + } + + @Test(expected = InvalidAssumptionException.class) + public void testSecondInvalidateCheck() throws InvalidAssumptionException { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + second.invalidate(); + + union.check(); + } + + @Test + public void testBothInvalidateIsValid() { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + first.invalidate(); + second.invalidate(); + + assertFalse(union.isValid()); + } + + @Test(expected = InvalidAssumptionException.class) + public void testBothInvalidateCheck() throws InvalidAssumptionException { + final Assumption first = Truffle.getRuntime().createAssumption("first"); + final Assumption second = Truffle.getRuntime().createAssumption("second"); + final UnionAssumption union = new UnionAssumption(first, second); + + first.invalidate(); + second.invalidate(); + + union.check(); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java Mon Dec 16 08:20:36 2013 +0100 @@ -31,19 +31,21 @@ */ public class Truffle { - private static TruffleRuntime runtime; + private static final TruffleRuntime RUNTIME; private static native TruffleRuntime initializeRuntime(); public static TruffleRuntime getRuntime() { - return runtime; + return RUNTIME; } static { + TruffleRuntime runtime; try { runtime = initializeRuntime(); } catch (UnsatisfiedLinkError e) { runtime = new DefaultTruffleRuntime(); } + RUNTIME = runtime; } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Mon Dec 16 08:20:36 2013 +0100 @@ -50,6 +50,10 @@ return rootNode.execute(frame); } + public FrameDescriptor getFrameDescriptor() { + return frameDescriptor; + } + public RootNode getRootNode() { return rootNode; } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An assumption that is always valid. Used as a placeholder where an assumption is needed but never + * invalidated. + */ +public final class AlwaysValidAssumption implements Assumption { + + public static final AlwaysValidAssumption INSTANCE = new AlwaysValidAssumption(); + + private AlwaysValidAssumption() { + } + + @Override + public void check() throws InvalidAssumptionException { + } + + @Override + public void invalidate() { + throw new UnsupportedOperationException("Cannot invalidate this assumption - it is always valid"); + } + + @Override + public String getName() { + return getClass().getName(); + } + + @Override + public boolean isValid() { + return true; + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.*; + +/** + * A {@link CompilationFinal} value combined with an {@link Assumption} to notify when it changes. + * Note that you should be careful that modifications to this value do not cause deoptimization + * loops. This could be by using a value that is monotonic. + */ +public class AssumedValue { + + @CompilationFinal private T value; + private final CyclicAssumption assumption; + + public AssumedValue(String name, T initialValue) { + assumption = new CyclicAssumption(name); + value = initialValue; + } + + /** + * Get the current value, updating it if it has been {@link #set}. The compiler may be able to + * make this method return a constant value, but still accommodate mutation. + */ + public T get() { + try { + assumption.getAssumption().check(); + } catch (InvalidAssumptionException e) { + // No need to rewrite anything - just pick up the new value + } + + return value; + } + + /** + * Set a new value, which will be picked up the next time {@link #get} is called. + */ + public void set(T newValue) { + value = newValue; + assumption.invalidate(); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; + +/** + * Utility class to speculate on branches to be never visited. If the {@link #enter()} method is + * invoked first the optimized code is invalidated and the branch where {@link #enter()} is invoked + * is enabled for compilation. Otherwise if the {@link #enter()} method was never invoked the branch + * will not get compiled. + */ +public final class BranchProfile { + + @CompilationFinal private boolean visited; + + public void enter() { + if (!visited) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + visited = true; + } + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.*; + +/** + * Holds an {@link Assumption}, and knows how to recreate it with the same properties on + * invalidation. Used so that mutability is isolated in this class, and all other classes that need + * an assumption that may be recreated can have a final reference to an object of this class. Note + * that you should be careful that repeated invalidations do not cause a deoptimization loop in that + * same way that you would with any other assumption. + */ +public class CyclicAssumption { + + private final String name; + private Assumption assumption; + + public CyclicAssumption(String name) { + this.name = name; + invalidate(); + } + + public void invalidate() { + if (assumption != null) { + assumption.invalidate(); + } + + assumption = Truffle.getRuntime().createAssumption(name); + } + + public Assumption getAssumption() { + return assumption; + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java Mon Dec 16 08:20:36 2013 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An assumption that combines two other assumptions. A check on this assumption checks both of the + * child assumptions. + */ +public class UnionAssumption implements Assumption { + + private final String name; + private final Assumption first; + private final Assumption second; + + public UnionAssumption(String name, Assumption first, Assumption second) { + this.name = name; + this.first = first; + this.second = second; + } + + public UnionAssumption(Assumption first, Assumption second) { + this(null, first, second); + } + + @Override + public void check() throws InvalidAssumptionException { + first.check(); + second.check(); + } + + @Override + public void invalidate() { + first.invalidate(); + second.invalidate(); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isValid() { + return first.isValid() && second.isValid(); + } + +} diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -34,127 +34,126 @@ private static final int INLINE_CACHE_SIZE = 2; @Child protected TypedNode functionNode; - - private CallNode(TypedNode functionNode) { - this.functionNode = adoptChild(functionNode); - } + @Child protected ArgumentsNode argumentsNode; - private CallTarget executeCallTargetNode(VirtualFrame frame) { - try { - return functionNode.executeCallTarget(frame); - } catch (UnexpectedResultException e) { - throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported."); - } + public CallNode(TypedNode functionNode, ArgumentsNode argumentsNode) { + this.functionNode = adoptChild(functionNode); + this.argumentsNode = adoptChild(argumentsNode); } @Override public final Object executeGeneric(VirtualFrame frame) { - return executeGeneric(frame, executeCallTargetNode(frame)); + CallTarget function; + try { + function = functionNode.executeCallTarget(frame); + } catch (UnexpectedResultException e) { + throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported."); + } + Object[] arguments = argumentsNode.executeArray(frame); + return executeCall(frame, function, arguments); } - public abstract Object executeGeneric(VirtualFrame frame, CallTarget function); + public abstract Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments); public static CallNode create(TypedNode function, TypedNode[] arguments) { return new UninitializedCallNode(function, new ArgumentsNode(arguments), 0); } - private static final class CachedCallNode extends CallNode { - - @Child protected CallNode nextNode; - @Child protected TypedNode currentNode; - private final CallTarget cachedFunction; - - public CachedCallNode(TypedNode function, TypedNode current, CallNode next, CallTarget cachedFunction) { - super(function); - this.currentNode = adoptChild(current); - this.nextNode = adoptChild(next); - this.cachedFunction = cachedFunction; - } - - @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { - if (this.cachedFunction == function) { - return currentNode.executeGeneric(frame); - } - return nextNode.executeGeneric(frame, function); - } - } - private static final class UninitializedCallNode extends CallNode { - @Child protected ArgumentsNode uninitializedArgs; protected final int depth; UninitializedCallNode(TypedNode function, ArgumentsNode args, int depth) { - super(function); - this.uninitializedArgs = adoptChild(args); + super(function, args); this.depth = depth; } UninitializedCallNode(UninitializedCallNode copy) { - super(null); - this.uninitializedArgs = adoptChild(copy.uninitializedArgs); + super(null, null); this.depth = copy.depth + 1; } @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { CompilerDirectives.transferToInterpreter(); - return specialize(function).executeGeneric(frame, function); + return specialize(function).executeCall(frame, function, arguments); } private CallNode specialize(CallTarget function) { CompilerAsserts.neverPartOfCompilation(); if (depth < INLINE_CACHE_SIZE) { - TypedNode current = createCacheNode(function); + DefaultCallTarget callTarget = (DefaultCallTarget) function; + FunctionRootNode root = (FunctionRootNode) callTarget.getRootNode(); CallNode next = new UninitializedCallNode(this); - return replace(new CachedCallNode(this.functionNode, current, next, function)); + InlinableDirectCallNode directCall = new InlinableDirectCallNode(functionNode, argumentsNode, next, callTarget); + replace(directCall); + if (root.isInlineImmediatly()) { + return directCall.inlineImpl(); + } else { + return directCall; + } } else { - CallNode topMost = (CallNode) getTopNode(); - return topMost.replace(new GenericCallNode(topMost.functionNode, uninitializedArgs)); + CallNode topMost = (CallNode) NodeUtil.getNthParent(this, depth); + return topMost.replace(new GenericCallNode(topMost.functionNode, topMost.argumentsNode)); } } - protected Node getTopNode() { - Node parentNode = this; - for (int i = 0; i < depth; i++) { - parentNode = parentNode.getParent(); - } - return parentNode; + } + + private abstract static class DirectCallNode extends CallNode { + + protected final DefaultCallTarget cachedFunction; + + @Child protected CallNode nextNode; + + public DirectCallNode(TypedNode function, ArgumentsNode arguments, DefaultCallTarget cachedFunction, CallNode next) { + super(function, arguments); + this.cachedFunction = cachedFunction; + this.nextNode = adoptChild(next); } - protected TypedNode createCacheNode(CallTarget function) { - ArgumentsNode clonedArgs = NodeUtil.cloneNode(uninitializedArgs); + @Override + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { + if (this.cachedFunction == function) { + return executeCurrent(frame, arguments); + } + return nextNode.executeCall(frame, function, arguments); + } - if (function instanceof DefaultCallTarget) { - DefaultCallTarget defaultFunction = (DefaultCallTarget) function; - RootNode rootNode = defaultFunction.getRootNode(); - if (rootNode instanceof FunctionRootNode) { - FunctionRootNode root = (FunctionRootNode) rootNode; - if (root.isAlwaysInline()) { - TypedNode inlinedCall = root.inline(clonedArgs); - if (inlinedCall != null) { - return inlinedCall; - } - } - return new InlinableCallNode((DefaultCallTarget) function, clonedArgs); - } - // got a call target that is not inlinable (should not occur for SL) - return new DispatchedCallNode(defaultFunction, clonedArgs); - } else { - throw new AssertionError(); - } + protected abstract Object executeCurrent(VirtualFrame frame, Object[] arguments); - } } - private static final class InlinableCallNode extends DispatchedCallNode implements InlinableCallSite { + private static final class InlinableDirectCallNode extends DirectCallNode implements InlinableCallSite { @CompilationFinal private int callCount; - InlinableCallNode(DefaultCallTarget function, ArgumentsNode arguments) { - super(function, arguments); + InlinableDirectCallNode(TypedNode function, ArgumentsNode arguments, CallNode next, DefaultCallTarget cachedFunction) { + super(function, arguments, cachedFunction, next); + } + + @Override + public Object executeCurrent(VirtualFrame frame, Object[] arguments) { + if (CompilerDirectives.inInterpreter()) { + callCount++; + } + return cachedFunction.call(frame.pack(), new SLArguments(arguments)); + } + + InlinedDirectCallNode inlineImpl() { + CompilerAsserts.neverPartOfCompilation(); + RootNode root = cachedFunction.getRootNode(); + TypedNode inlinedNode = ((FunctionRootNode) root).inline(); + assert inlinedNode != null; + return replace(new InlinedDirectCallNode(this, inlinedNode), "Inlined " + root); + } + + @Override + public boolean inline(FrameFactory factory) { + inlineImpl(); + /* SL is always able to inline if required. */ + return true; } @Override @@ -169,7 +168,7 @@ @Override public Node getInlineTree() { - RootNode root = function.getRootNode(); + RootNode root = cachedFunction.getRootNode(); if (root instanceof FunctionRootNode) { return ((FunctionRootNode) root).getUninitializedBody(); } @@ -177,67 +176,46 @@ } @Override - public boolean inline(FrameFactory factory) { - CompilerAsserts.neverPartOfCompilation(); - TypedNode functionCall = null; - - RootNode root = function.getRootNode(); - if (root instanceof FunctionRootNode) { - functionCall = ((FunctionRootNode) root).inline(NodeUtil.cloneNode(args)); - } - if (functionCall != null) { - this.replace(functionCall); - return true; - } else { - return false; - } - } - - @Override - public Object executeGeneric(VirtualFrame frame) { - if (CompilerDirectives.inInterpreter()) { - callCount++; - } - return super.executeGeneric(frame); - } - - @Override public CallTarget getCallTarget() { - return function; + return cachedFunction; } } - private static class DispatchedCallNode extends TypedNode { + private static class InlinedDirectCallNode extends DirectCallNode implements InlinedCallSite { + + private final FrameDescriptor descriptor; + @Child private TypedNode inlinedBody; - @Child protected ArgumentsNode args; - protected final DefaultCallTarget function; - - DispatchedCallNode(DefaultCallTarget function, ArgumentsNode arguments) { - this.args = adoptChild(arguments); - this.function = function; + InlinedDirectCallNode(InlinableDirectCallNode prev, TypedNode inlinedBody) { + super(prev.functionNode, prev.argumentsNode, prev.cachedFunction, prev.nextNode); + this.descriptor = cachedFunction.getFrameDescriptor(); + this.inlinedBody = adoptChild(inlinedBody); } @Override - public Object executeGeneric(VirtualFrame frame) { - SLArguments argsObject = new SLArguments(args.executeArray(frame)); - return function.call(frame.pack(), argsObject); + public Object executeCurrent(VirtualFrame frame, Object[] arguments) { + SLArguments slArguments = new SLArguments(arguments); + VirtualFrame newFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), slArguments, descriptor); + return inlinedBody.executeGeneric(newFrame); } + + @Override + public CallTarget getCallTarget() { + return cachedFunction; + } + } private static final class GenericCallNode extends CallNode { - @Child protected ArgumentsNode args; - GenericCallNode(TypedNode functionNode, ArgumentsNode arguments) { - super(functionNode); - this.args = adoptChild(arguments); + super(functionNode, arguments); } @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { - SLArguments argsObject = new SLArguments(args.executeArray(frame)); - return function.call(frame.pack(), argsObject); + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { + return function.call(frame.pack(), new SLArguments(arguments)); } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -35,14 +35,14 @@ private final TypedNode uninitializedBody; private final String name; - private final boolean alwaysInline; + private final boolean inlineImmediatly; - private FunctionRootNode(TypedNode body, String name, boolean alwaysInline) { + private FunctionRootNode(TypedNode body, String name, boolean inlineImmediatly) { super(null); this.uninitializedBody = NodeUtil.cloneNode(body); this.body = adoptChild(body); this.name = name; - this.alwaysInline = alwaysInline; + this.inlineImmediatly = inlineImmediatly; } public static CallTarget createBuiltin(SLContext context, NodeFactory factory, String name) { @@ -67,36 +67,12 @@ return body.executeGeneric(frame); } - public boolean isAlwaysInline() { - return alwaysInline; - } - - public TypedNode inline(ArgumentsNode clonedArgs) { - TypedNode clonedBody = NodeUtil.cloneNode(uninitializedBody); - if (clonedBody instanceof BuiltinNode) { - return inlineBuiltin(clonedArgs, (BuiltinNode) clonedBody); - } else if (clonedBody instanceof FunctionBodyNode) { - return inlineFunction(clonedArgs, (FunctionBodyNode) clonedBody); - } else { - throw new UnsupportedOperationException(); - } + public boolean isInlineImmediatly() { + return inlineImmediatly; } - private InlinedFunctionNode inlineFunction(ArgumentsNode clonedArgs, FunctionBodyNode clonedBody) { - return new InlinedFunctionNode(getCallTarget(), clonedBody, clonedArgs); - } - - private static TypedNode inlineBuiltin(ArgumentsNode clonedArgs, BuiltinNode builtin) { - TypedNode[] callerArgs = clonedArgs.getArguments(); - TypedNode[] builtinArgs = builtin.getArguments(); - for (int i = 0; i < builtinArgs.length; i++) { - if (i < callerArgs.length) { - builtinArgs[i].replace(callerArgs[i]); - } else { - builtinArgs[i].replace(new NullLiteralNode()); - } - } - return builtin; + public TypedNode inline() { + return NodeUtil.cloneNode(uninitializedBody); } public Node getUninitializedBody() { @@ -108,34 +84,6 @@ return "function " + name; } - private static final class InlinedFunctionNode extends TypedNode implements InlinedCallSite { - - @Child private FunctionBodyNode body; - @Child private ArgumentsNode arguments; - - private final CallTarget callTarget; - private final FrameDescriptor frameDescriptor; - - public InlinedFunctionNode(CallTarget callTarget, FunctionBodyNode body, ArgumentsNode arguments) { - this.callTarget = callTarget; - this.body = adoptChild(body); - this.frameDescriptor = body.getFrameDescriptor(); - this.arguments = adoptChild(arguments); - } - - @Override - public Object executeGeneric(VirtualFrame frame) { - SLArguments args = new SLArguments(arguments.executeArray(frame)); - VirtualFrame childFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), args, frameDescriptor); - return body.executeGeneric(childFrame); - } - - public CallTarget getCallTarget() { - return callTarget; - } - - } - public String getName() { return name; } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -24,6 +24,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; @NodeChild(value = "conditionNode", type = ConditionNode.class) public abstract class IfNode extends StatementNode { @@ -31,6 +32,9 @@ @Child private StatementNode thenPartNode; @Child private StatementNode elsePartNode; + private final BranchProfile ifBranch = new BranchProfile(); + private final BranchProfile elseBranch = new BranchProfile(); + public IfNode(StatementNode thenPart, StatementNode elsePart) { this.thenPartNode = adoptChild(thenPart); this.elsePartNode = adoptChild(elsePart); @@ -43,9 +47,11 @@ @Specialization public void doVoid(VirtualFrame frame, boolean condition) { if (condition) { + ifBranch.enter(); thenPartNode.executeVoid(frame); } else { if (elsePartNode != null) { + elseBranch.enter(); elsePartNode.executeVoid(frame); } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadArgumentNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadArgumentNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadArgumentNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -23,12 +23,16 @@ package com.oracle.truffle.sl.nodes; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.sl.runtime.*; public class ReadArgumentNode extends TypedNode { private final int index; + private final BranchProfile outOfBounds = new BranchProfile(); + private final BranchProfile inBounds = new BranchProfile(); + public ReadArgumentNode(int index) { this.index = index; } @@ -37,8 +41,10 @@ public Object executeGeneric(VirtualFrame frame) { Object[] args = SLArguments.get(frame).arguments; if (index < args.length) { + inBounds.enter(); return args[index]; } else { + outOfBounds.enter(); return SLNull.INSTANCE; } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadFunctionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadFunctionNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadFunctionNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -23,16 +23,15 @@ package com.oracle.truffle.sl.nodes; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.sl.runtime.*; public final class ReadFunctionNode extends TypedNode { private final SLFunctionRegistry registry; private final String name; - - @CompilationFinal private boolean seenInvalidFunction; + private final BranchProfile invalidFunction = new BranchProfile(); public ReadFunctionNode(SLFunctionRegistry registry, String name) { this.registry = registry; @@ -50,14 +49,8 @@ if (target != null) { return target; } - if (!seenInvalidFunction) { - CompilerDirectives.transferToInterpreter(); - seenInvalidFunction = true; - } - if (seenInvalidFunction) { - throw new RuntimeException("Function with name '" + name + "' not found."); - } - return null; + invalidFunction.enter(); + throw new RuntimeException("Function with name '" + name + "' not found."); } } diff -r 0393767ae0fc -r f17969ae4a35 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WhileNode.java Fri Dec 13 16:40:41 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WhileNode.java Mon Dec 16 08:20:36 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.truffle.sl.nodes; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; public class WhileNode extends StatementNode { @@ -33,6 +34,11 @@ private final BreakException breakTarget; private final ContinueException continueTarget; + private final BranchProfile continueMismatch = new BranchProfile(); + private final BranchProfile continueMatch = new BranchProfile(); + private final BranchProfile breakMismatch = new BranchProfile(); + private final BranchProfile breakMatch = new BranchProfile(); + public WhileNode(ConditionNode condition, StatementNode body) { this.condition = adoptChild(condition); this.body = adoptChild(body); @@ -49,15 +55,19 @@ body.executeVoid(frame); } catch (ContinueException ex) { if (ex != continueTarget) { + continueMismatch.enter(); throw ex; } + continueMatch.enter(); // Fall through to next loop iteration. } } } catch (BreakException ex) { if (ex != breakTarget) { + breakMismatch.enter(); throw ex; } + breakMatch.enter(); // Done executing this loop, exit method to execute statement following the loop. } } diff -r 0393767ae0fc -r f17969ae4a35 mx/mx_graal.py --- a/mx/mx_graal.py Fri Dec 13 16:40:41 2013 +0100 +++ b/mx/mx_graal.py Mon Dec 16 08:20:36 2013 +0100 @@ -1452,7 +1452,7 @@ mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks) -def packagejar(classpath, outputFile, mainClass, annotationProcessor=None): +def packagejar(classpath, outputFile, mainClass=None, annotationProcessor=None, stripDebug=False): prefix = '' if mx.get_os() != 'windows' else '\\??\\' # long file name hack print "creating", outputFile filecount, totalsize = 0, 0 @@ -1483,5 +1483,5 @@ filecount += 1 totalsize += zi.file_size print "%d files (total size: %.2f kB, jar size: %.2f kB)" % (filecount, totalsize / 1e3, os.path.getsize(outputFile) / 1e3) - mx.run([mx.exe_suffix(join(mx.java().jdk, 'bin', 'pack200')), '-r', '-G', outputFile]) + mx.run([mx.exe_suffix(join(mx.java().jdk, 'bin', 'pack200')), '-r'] + (['-G'] if stripDebug else []) + [outputFile]) print "repacked jar size: %.2f kB" % (os.path.getsize(outputFile) / 1e3) diff -r 0393767ae0fc -r f17969ae4a35 src/share/vm/runtime/vframe.cpp --- a/src/share/vm/runtime/vframe.cpp Fri Dec 13 16:40:41 2013 +0100 +++ b/src/share/vm/runtime/vframe.cpp Mon Dec 16 08:20:36 2013 +0100 @@ -266,7 +266,7 @@ // Get oopmap describing oops and int for current bci InterpreterOopMap oop_mask; - if (TraceDeoptimization && Verbose) { + if ((TraceDeoptimization && Verbose) GRAAL_ONLY( || PrintDeoptimizationDetails)) { methodHandle m_h(thread(), method()); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else { @@ -333,7 +333,7 @@ InterpreterOopMap oop_mask; // Get oopmap describing oops and int for current bci - if (TraceDeoptimization && Verbose) { + if ((TraceDeoptimization && Verbose) GRAAL_ONLY( || PrintDeoptimizationDetails)) { methodHandle m_h(method()); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else {