Mercurial > hg > graal-compiler
changeset 12572:388bb7650808
Merge.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 24 Oct 2013 16:21:25 +0200 |
parents | 693622f11dc3 (diff) 86c74ef1b6f5 (current diff) |
children | 6332050441eb |
files | |
diffstat | 20 files changed, 232 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Oct 24 16:21:25 2013 +0200 @@ -869,8 +869,7 @@ // check that the liveIn set of the first block is empty Block startBlock = ir.cfg.getStartBlock(); - BitSet liveInArgs = new BitSet(blockData.get(startBlock).liveIn.size()); - if (!blockData.get(startBlock).liveIn.equals(liveInArgs)) { + if (blockData.get(startBlock).liveIn.cardinality() != 0) { if (DetailedAsserts.getValue()) { reportFailure(numBlocks); } @@ -878,73 +877,76 @@ TTY.println("preds=" + startBlock.getPredecessorCount() + ", succs=" + startBlock.getSuccessorCount()); TTY.println("startBlock-ID: " + startBlock.getId()); - // bailout of if this occurs in product mode. - throw new GraalInternalError("liveIn set of first block must be empty"); + // bailout if this occurs in product mode. + throw new GraalInternalError("liveIn set of first block must be empty: " + blockData.get(startBlock).liveIn); } } private void reportFailure(int numBlocks) { TTY.println(gen.getGraph().toString()); - TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)"); - TTY.print("affected registers:"); - TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString()); + TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):"); + BitSet startBlockLiveIn = blockData.get(ir.cfg.getStartBlock()).liveIn; + for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { + Value operand = operandFor(operandNum); + TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand)); + } // print some additional information to simplify debugging - for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) { - if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) { - Value operand = operandFor(operandNum); - TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand)); + for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { + Value operand = operandFor(operandNum); + TTY.println("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand.toString(), gen.valueForOperand(operand)); + + Deque<Block> definedIn = new ArrayDeque<>(); + HashSet<Block> usedIn = new HashSet<>(); + for (Block block : sortedBlocks) { + if (blockData.get(block).liveGen.get(operandNum)) { + usedIn.add(block); + TTY.println("used in block B%d {", block.getId()); + for (LIRInstruction ins : ir.lir(block)) { + TTY.println(" " + ins.id() + ": " + ins.toString()); + ins.forEachState(new ValueProcedure() { - Deque<Block> definedIn = new ArrayDeque<>(); - HashSet<Block> usedIn = new HashSet<>(); - for (Block block : sortedBlocks) { - if (blockData.get(block).liveGen.get(operandNum)) { - usedIn.add(block); - TTY.println(" used in block B%d", block.getId()); - for (LIRInstruction ins : ir.lir(block)) { - TTY.println(ins.id() + ": " + ins.toString()); - ins.forEachState(new ValueProcedure() { + @Override + public Value doValue(Value liveStateOperand) { + TTY.println(" operand=" + liveStateOperand); + return liveStateOperand; + } + }); + } + TTY.println("}"); + } + if (blockData.get(block).liveKill.get(operandNum)) { + definedIn.add(block); + TTY.println("defined in block B%d {", block.getId()); + for (LIRInstruction ins : ir.lir(block)) { + TTY.println(" " + ins.id() + ": " + ins.toString()); + } + TTY.println("}"); + } + } - @Override - public Value doValue(Value liveStateOperand) { - TTY.println(" operand=" + liveStateOperand); - return liveStateOperand; - } - }); + int[] hitCount = new int[numBlocks]; + + while (!definedIn.isEmpty()) { + Block block = definedIn.removeFirst(); + usedIn.remove(block); + for (Block successor : block.getSuccessors()) { + if (successor.isLoopHeader()) { + if (!block.isLoopEnd()) { + definedIn.add(successor); } - } - if (blockData.get(block).liveKill.get(operandNum)) { - definedIn.add(block); - TTY.println(" defined in block B%d", block.getId()); - for (LIRInstruction ins : ir.lir(block)) { - TTY.println(ins.id() + ": " + ins.toString()); + } else { + if (++hitCount[successor.getId()] == successor.getPredecessorCount()) { + definedIn.add(successor); } } } - - int[] hitCount = new int[numBlocks]; - - while (!definedIn.isEmpty()) { - Block block = definedIn.removeFirst(); - usedIn.remove(block); - for (Block successor : block.getSuccessors()) { - if (successor.isLoopHeader()) { - if (!block.isLoopEnd()) { - definedIn.add(successor); - } - } else { - if (++hitCount[successor.getId()] == successor.getPredecessorCount()) { - definedIn.add(successor); - } - } - } - } - TTY.print(" offending usages are in: "); - for (Block block : usedIn) { - TTY.print("B%d ", block.getId()); - } - TTY.println(); } + TTY.print("**** offending usages are in: "); + for (Block block : usedIn) { + TTY.print("B%d ", block.getId()); + } + TTY.println(); } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Oct 24 16:21:25 2013 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.lir.LIRValueUtil.*; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -66,6 +67,13 @@ protected final DebugInfoBuilder debugInfoBuilder; protected Block currentBlock; + + /** + * Maps constants the variables within the scope of a single block to avoid loading a constant + * more than once per block. + */ + private Map<Constant, Variable> constantsLoadedInCurrentBlock; + private ValueNode currentInstruction; private ValueNode lastInstructionPrinted; // Debugging only @@ -151,7 +159,38 @@ if (nodeOperands == null) { return null; } - return nodeOperands.get(node); + Value operand = nodeOperands.get(node); + if (operand == null) { + return getConstantOperand(node); + } + return operand; + } + + private Value getConstantOperand(ValueNode node) { + if (!ConstantNodeRecordsUsages) { + Constant value = node.asConstant(); + if (value != null) { + if (canInlineConstant(value)) { + return setResult(node, value); + } else { + Variable loadedValue; + if (constantsLoadedInCurrentBlock == null) { + constantsLoadedInCurrentBlock = new HashMap<>(); + loadedValue = null; + } else { + loadedValue = constantsLoadedInCurrentBlock.get(value); + } + if (loadedValue == null) { + loadedValue = emitMove(value); + constantsLoadedInCurrentBlock.put(value, loadedValue); + } + return loadedValue; + } + } + } else { + // Constant is loaded by ConstantNode.generate() + } + return null; } public ValueNode valueForOperand(Value value) { @@ -188,7 +227,7 @@ @Override public Value setResult(ValueNode x, Value operand) { assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable()); - assert operand(x) == null : "operand cannot be set twice"; + assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; assert operand.getKind().getStackKind() == x.kind() || x.kind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.kind(); assert !(x instanceof VirtualObjectNode); @@ -296,6 +335,8 @@ } currentBlock = block; + resetLoadedConstants(); + // set up the list of LIR instructions assert lir.lir(block) == null : "LIR list already computed for this block"; lir.setLir(block, new ArrayList<LIRInstruction>()); @@ -319,7 +360,9 @@ if (TraceLIRGeneratorLevel.getValue() >= 3) { TTY.println("LIRGen for " + instr); } - if (instr instanceof ValueNode) { + if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) { + // Loading of constants is done lazily by operand() + } else if (instr instanceof ValueNode) { ValueNode valueNode = (ValueNode) instr; if (operand(valueNode) == null) { if (!peephole(valueNode)) { @@ -355,6 +398,12 @@ } } + private void resetLoadedConstants() { + if (constantsLoadedInCurrentBlock != null && !constantsLoadedInCurrentBlock.isEmpty()) { + constantsLoadedInCurrentBlock.clear(); + } + } + protected abstract boolean peephole(ValueNode valueNode); private boolean endsWithJump(Block block) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Oct 24 16:21:25 2013 +0200 @@ -361,7 +361,7 @@ int minCount = Integer.MAX_VALUE; Node minCountNode = null; for (Node input : node.inputs()) { - if (input != null) { + if (input != null && input.recordsUsages()) { int estimate = input.getUsageCountUpperBound(); if (estimate == 0) { return null;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Oct 24 16:21:25 2013 +0200 @@ -255,6 +255,7 @@ } int getUsageCountUpperBound() { + assert recordsUsages(); if (usage0 == null) { return 0; } @@ -265,13 +266,23 @@ } /** - * Gets the list of nodes that use this node (e.g., as an input). + * Gets the list of nodes that use this node (i.e., as an input). */ public final NodeIterable<Node> usages() { + assert recordsUsages() : this; return new NodeUsageIterable(); } /** + * Determines if this node records its usages (i.e. the nodes for which it is an input). All + * methods in {@link Node} that pertain to querying or updating usage information must not be + * called for a {@link Node} instance that returns false for this method. + */ + public boolean recordsUsages() { + return true; + } + + /** * 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. * @@ -311,6 +322,7 @@ * @param node the node to add */ private void addUsage(Node node) { + assert recordsUsages(); incUsageModCount(); if (usage0 == null) { usage0 = node; @@ -342,6 +354,7 @@ * @return whether or not {@code usage} was in the usage list */ private boolean removeUsage(Node node) { + assert recordsUsages(); // It is critical that this method maintains the invariant that // the usage list has no null element preceding a non-null element incUsageModCount(); @@ -392,6 +405,7 @@ } private void clearUsages() { + assert recordsUsages(); incUsageModCount(); usage0 = null; usage1 = null; @@ -443,16 +457,20 @@ protected void updateUsages(Node oldInput, Node newInput) { if (oldInput != newInput) { if (oldInput != null) { - boolean result = removeThisFromUsages(oldInput); - assert assertTrue(result, "not found in usages, old input: %s", oldInput); + if (oldInput.recordsUsages()) { + boolean result = removeThisFromUsages(oldInput); + assert assertTrue(result, "not found in usages, old input: %s", oldInput); + } } if (newInput != null) { - NodeChangedListener listener = graph.inputChangedListener; - if (listener != null) { - listener.nodeChanged(this); + if (newInput.recordsUsages()) { + NodeChangedListener listener = graph.inputChangedListener; + if (listener != null) { + listener.nodeChanged(this); + } + newInput.addUsage(this); } - newInput.addUsage(this); - } else if (oldInput != null && oldInput.usages().isEmpty()) { + } else if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { NodeChangedListener listener = graph.usagesDroppedToZeroListener; if (listener != null) { listener.nodeChanged(oldInput); @@ -513,7 +531,9 @@ if (listener != null) { listener.nodeChanged(usage); } - other.addUsage(usage); + if (other.recordsUsages()) { + other.addUsage(usage); + } } } clearUsages(); @@ -554,11 +574,13 @@ assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); for (Node input : inputs()) { - removeThisFromUsages(input); - if (input.usages().isEmpty()) { - NodeChangedListener listener = graph.usagesDroppedToZeroListener; - if (listener != null) { - listener.nodeChanged(input); + if (input.recordsUsages()) { + removeThisFromUsages(input); + if (input.usages().isEmpty()) { + NodeChangedListener listener = graph.usagesDroppedToZeroListener; + if (listener != null) { + listener.nodeChanged(input); + } } } } @@ -580,7 +602,9 @@ } private boolean checkDeletion() { - assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages()); + if (recordsUsages()) { + assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages()); + } assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor); return true; } @@ -603,7 +627,9 @@ NodeClass clazz = getNodeClass(); clazz.copyInputs(this, newNode); for (Node input : inputs()) { - input.addUsage(newNode); + if (input.recordsUsages()) { + input.addUsage(newNode); + } } return newNode; } @@ -676,16 +702,18 @@ assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); for (Node input : inputs()) { - assertTrue(input.usages().contains(this), "missing usage in input %s", input); + assertTrue(!input.recordsUsages() || input.usages().contains(this), "missing usage in input %s", input); assertTrue(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()); assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor); } - for (Node usage : usages()) { - assertFalse(usage.isDeleted(), "usage must never be deleted"); - assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage); + if (recordsUsages()) { + for (Node usage : usages()) { + assertFalse(usage.isDeleted(), "usage must never be deleted"); + assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage); + } } if (predecessor != null) { assertFalse(predecessor.isDeleted(), "predecessor must never be deleted");
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Oct 24 16:21:25 2013 +0200 @@ -1313,7 +1313,7 @@ newNodes.put(node, replacement); } else { Node newNode = node.clone(graph, false); - assert newNode.usages().count() == 0 || newNode.inputs().count() == 0; + assert newNode.inputs().count() == 0 || newNode.usages().count() == 0; assert newNode.getClass() == node.getClass(); newNodes.put(node, newNode); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Thu Oct 24 16:21:25 2013 +0200 @@ -174,7 +174,7 @@ if (value != null) { OptionValue<?> optionValue = desc.getOptionValue(); optionValue.setValue(value); - // Logger.info("Set option " + fieldName + " to " + value); + // Logger.info("Set option " + desc.getName() + " to " + value); } else { Logger.info("Wrong value \"" + valueString + "\" for option " + optionName); return false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Thu Oct 24 16:21:25 2013 +0200 @@ -45,6 +45,17 @@ } /** + * 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 = Boolean.getBoolean("graal.constantNodeRecordsUsages"); + + @Override + public boolean recordsUsages() { + return ConstantNodeRecordsUsages; + } + + /** * Constructs a new ConstantNode representing the specified constant. * * @param value the constant
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Thu Oct 24 16:21:25 2013 +0200 @@ -90,7 +90,7 @@ } ValueNode removedValue = phi.valueAt(predIndex); phi.removeInput(predIndex); - if (removedValue != null && removedValue.isAlive() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) { + if (removedValue != null && removedValue.isAlive() && removedValue.recordsUsages() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) { GraphUtil.killWithUnusedFloatingInputs(removedValue); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Oct 24 16:21:25 2013 +0200 @@ -123,13 +123,17 @@ } public static void killWithUnusedFloatingInputs(Node node) { - List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); - node.safeDelete(); + if (node.recordsUsages()) { + List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); + node.safeDelete(); - for (Node in : floatingInputs) { - if (in.isAlive() && in.usages().isEmpty()) { - killWithUnusedFloatingInputs(in); + for (Node in : floatingInputs) { + if (in.isAlive() && (!in.recordsUsages() || in.usages().isEmpty())) { + killWithUnusedFloatingInputs(in); + } } + } else { + assert node.inputs().isEmpty(); } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Thu Oct 24 16:21:25 2013 +0200 @@ -206,7 +206,7 @@ } private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(node); return true; }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Thu Oct 24 16:21:25 2013 +0200 @@ -631,8 +631,10 @@ cdbc.apply(cfg.getNodeToBlock().get(succ)); } ensureScheduledUsages(node, strategy); - for (Node usage : node.usages()) { - blocksForUsage(node, usage, cdbc, strategy); + if (node.recordsUsages()) { + for (Node usage : node.usages()) { + blocksForUsage(node, usage, cdbc, strategy); + } } List<FixedNode> usages = phantomUsages.get(node); if (usages != null) { @@ -808,8 +810,10 @@ } private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) { - for (Node usage : node.usages().filter(ScheduledNode.class)) { - assignBlockToNode((ScheduledNode) usage, strategy); + if (node.recordsUsages()) { + for (Node usage : node.usages().filter(ScheduledNode.class)) { + assignBlockToNode((ScheduledNode) usage, strategy); + } } // now true usages are ready } @@ -1057,14 +1061,16 @@ } visited.mark(instruction); - for (Node usage : instruction.usages()) { - if (usage instanceof VirtualState) { - // only fixed nodes can have VirtualState -> no need to schedule them - } else { - if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) { - // value proxies should be scheduled before the loopexit, not after + if (instruction.recordsUsages()) { + for (Node usage : instruction.usages()) { + if (usage instanceof VirtualState) { + // only fixed nodes can have VirtualState -> no need to schedule them } else { - addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited); + if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) { + // value proxies should be scheduled before the loopexit, not after + } else { + addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited); + } } } }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Oct 24 16:21:25 2013 +0200 @@ -327,7 +327,7 @@ out.println("=== Succesors ==="); printNamedNodes(node, node.successors().iterator(), "", "\n", null); out.println("=== Usages ==="); - if (!node.usages().isEmpty()) { + if (node.recordsUsages() && !node.usages().isEmpty()) { for (Node usage : node.usages()) { out.print(nodeToString(usage)).print(" "); }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Oct 24 16:21:25 2013 +0200 @@ -94,7 +94,7 @@ return false; } - if (method != curMethod || !curDecorators.equals(decorators)) { + if (!method.equals(curMethod) || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile); curMethod = method;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Thu Oct 24 16:21:25 2013 +0200 @@ -321,7 +321,8 @@ } public void cleanUpReturnCheckCast(Node newInstance) { - if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { + if (newInstance.recordsUsages() && newInstance instanceof ValueNode && + (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { StructuredGraph graph = (StructuredGraph) newInstance.graph(); for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) { for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Oct 24 16:21:25 2013 +0200 @@ -273,6 +273,20 @@ } } + static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider { + + final Varargs varargs; + + public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) { + super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass())); + this.varargs = varargs; + } + + public ValueNode length() { + return ConstantNode.forInt(varargs.length, graph()); + } + } + static class CacheKey { private final ResolvedJavaMethod method; @@ -411,7 +425,7 @@ assert checkTemplate(metaAccess, args, method, signature); int parameterCount = args.info.getParameterCount(); - ConstantNode[] placeholders = new ConstantNode[parameterCount]; + VarargsPlaceholderNode[] placeholders = new VarargsPlaceholderNode[parameterCount]; for (int i = 0; i < parameterCount; i++) { if (args.info.isConstantParameter(i)) { @@ -426,8 +440,7 @@ nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy)); } else if (args.info.isVarargsParameter(i)) { Varargs varargs = (Varargs) args.values[i]; - Object array = Array.newInstance(varargs.componentType, varargs.length); - ConstantNode placeholder = ConstantNode.forObject(array, metaAccess, snippetCopy); + VarargsPlaceholderNode placeholder = snippetCopy.unique(new VarargsPlaceholderNode(varargs, providers.getMetaAccess())); nodeReplacements.put(snippetGraph.getLocal(i), placeholder); placeholders[i] = placeholder; } @@ -461,7 +474,7 @@ } parameters[i] = locals; - ConstantNode placeholder = placeholders[i]; + VarargsPlaceholderNode placeholder = placeholders[i]; assert placeholder != null; for (Node usage : placeholder.usages().snapshot()) { if (usage instanceof LoadIndexedNode) { @@ -584,7 +597,7 @@ this.returnNode = retNode; } - private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) { + private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) { for (int i = 0; i < parameterCount; i++) { if (placeholders[i] != null) { assert placeholders[i].isDeleted() : placeholders[i];
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Oct 24 16:21:25 2013 +0200 @@ -237,13 +237,12 @@ ValueNode arg = arguments.get(local.index()); if (arg.isConstant()) { Constant constant = arg.asConstant(); - ConstantNode constantNode = ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy); - local.replaceAndDelete(constantNode); - for (Node usage : constantNode.usages()) { + for (Node usage : local.usages()) { if (usage instanceof Canonicalizable) { modifiedNodes.add(usage); } } + local.replaceAndDelete(ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy)); } } Debug.scope("TruffleUnrollLoop", targetMethod, new Runnable() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Oct 24 16:21:25 2013 +0200 @@ -156,7 +156,7 @@ int beforeInvokeMark = graph.getMark(); expandInvoke(methodCallTarget); for (Node arg : argumentSnapshot) { - if (arg != null) { + if (arg != null && arg.recordsUsages()) { for (Node argUsage : arg.usages()) { if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { canonicalizerUsages.add(argUsage);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu Oct 24 16:21:25 2013 +0200 @@ -531,8 +531,10 @@ void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node) { if (node.isAlive()) { aliases.set(node, virtual); - for (Node usage : node.usages()) { - markVirtualUsages(usage); + if (node.recordsUsages()) { + for (Node usage : node.usages()) { + markVirtualUsages(usage); + } } } }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Thu Oct 24 15:36:39 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Thu Oct 24 16:21:25 2013 +0200 @@ -61,6 +61,9 @@ wordAccess.inferStamps(graph); for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { + if (!node.recordsUsages()) { + continue; + } for (Node usage : node.usages()) { if (usage instanceof AccessMonitorNode) { verify(!isWord(node), node, usage, "word value has no monitor");
--- a/mxtool/mx.py Thu Oct 24 15:36:39 2013 +0200 +++ b/mxtool/mx.py Thu Oct 24 16:21:25 2013 +0200 @@ -768,7 +768,7 @@ abort('Missing "suite=<name>" in ' + projectsFile) def _commands_name(self): - return 'mx_' + self.name.replace('-','_') + return 'mx_' + self.name.replace('-', '_') def _find_commands(self, name): commandsPath = join(self.mxDir, name + '.py')