# HG changeset patch # User Doug Simon # Date 1382657187 -7200 # Node ID 8fde330c11cd9f533f3fea6d4ff048e346364439 # Parent 7876c59a7a2f3bc49385b25f5445b8dc105a55d1# Parent 04e51b3026c07f4bf023454074a55565752bdae8 Merge. diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Oct 25 01:26:27 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.test; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import static org.junit.Assert.*; @@ -144,7 +145,9 @@ new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } } } @@ -176,7 +179,9 @@ new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Oct 25 01:26:27 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test; import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; @@ -116,12 +117,32 @@ assertEquals(expected, graph, false); } + protected int countUnusedConstants(StructuredGraph graph) { + int total = 0; + for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) { + if (!ConstantNodeRecordsUsages) { + if (node.gatherUsages().isEmpty()) { + total++; + } + } else { + if (node.usages().isEmpty()) { + total++; + } + } + } + return total; + } + + protected int getNodeCountExcludingUnusedConstants(StructuredGraph graph) { + return graph.getNodeCount() - countUnusedConstants(graph); + } + protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) { String expectedString = getCanonicalGraphString(expected, excludeVirtual); String actualString = getCanonicalGraphString(graph, excludeVirtual); String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString; - if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) { + if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { Debug.dump(expected, "Node count not matching - expected"); Debug.dump(graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); @@ -161,16 +182,18 @@ } result.append("\n"); for (Node node : schedule.getBlockToNodesMap().get(block)) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { - int id; - if (canonicalId.get(node) != null) { - id = canonicalId.get(node); - } else { - id = nextId++; - canonicalId.set(node, id); + if (node.recordsUsages()) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { + int id; + if (canonicalId.get(node) != null) { + id = canonicalId.get(node); + } else { + id = nextId++; + canonicalId.set(node, id); + } + String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); + result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.usages().count() + ")\n")); } - String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.usages().count() + ")\n")); } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Oct 25 01:26:27 2013 +0200 @@ -197,7 +197,7 @@ @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { - if (expected.getNodeCount() != graph.getNodeCount()) { + if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { outputGraph(expected, "expected"); outputGraph(graph, "actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); @@ -225,7 +225,7 @@ } private static void outputNode(Node node) { - TTY.print(" " + node + " (usage count: " + node.usages().count() + ") (inputs:"); + TTY.print(" " + node + " (usage count: " + (node.recordsUsages() ? node.usages().count() : "?") + ") (inputs:"); for (Node input : node.inputs()) { TTY.print(" " + input.toString(Verbosity.Id)); } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Oct 25 01:26:27 2013 +0200 @@ -63,7 +63,7 @@ if (node instanceof ConstantNode) { ConstantNode constant = (ConstantNode) node; if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("-", getMetaAccess(), graph)); + constant.replace(ConstantNode.forObject("-", getMetaAccess(), graph)); } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Oct 25 01:26:27 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 definedIn = new ArrayDeque<>(); + HashSet 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 definedIn = new ArrayDeque<>(); - HashSet 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(); } } diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Oct 25 01:26:27 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 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()); @@ -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) { diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Fri Oct 25 01:26:27 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; diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Oct 25 01:26:27 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 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"); diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Oct 25 01:26:27 2013 +0200 @@ -1315,7 +1315,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); } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Oct 25 01:26:27 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; diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Oct 25 01:26:27 2013 +0200 @@ -39,7 +39,9 @@ @Override protected boolean verify(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) { - assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node; + if (node.recordsUsages() || !node.gatherUsages().isEmpty()) { + assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node; + } } return true; } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Oct 25 01:26:27 2013 +0200 @@ -68,7 +68,7 @@ LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph)); FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); - graph.replaceFloating(node, freadNode); + node.replace(freadNode); } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Fri Oct 25 01:26:27 2013 +0200 @@ -174,6 +174,13 @@ StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 1), StampFactory.forInteger(Kind.Long, Integer.MIN_VALUE, Integer.MAX_VALUE))); assertEquals(StampFactory.forInteger(Kind.Int, -2147483647, 31 - 2147483647), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 31), StampFactory.forInteger(Kind.Int, -2147483647, -2147483647))); + + assertEquals(StampFactory.forInteger(Kind.Int, 0x8000007e, 0x8000007f, 0x8000007eL, 0x8000007fL), + StampTool.add(StampFactory.forInteger(Kind.Int, 0x7ffffffe, 0x7fffffff, 0x7ffffffeL, 0x7fffffffL), StampFactory.forInteger(Kind.Int, 128, 128))); + + assertEquals(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampTool.add(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL))); } @Test diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Oct 25 01:26:27 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 @@ -54,6 +65,35 @@ this.value = value; } + /** + * 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. + */ + public List gatherUsages() { + assert !ConstantNodeRecordsUsages; + List usages = new ArrayList<>(); + for (Node node : graph().getNodes()) { + for (Node input : node.inputs()) { + if (input == this) { + usages.add(node); + } + } + } + return usages; + } + + public void replace(Node replacement) { + if (!recordsUsages()) { + List usages = gatherUsages(); + for (Node usage : usages) { + usage.replaceFirstInput(this, replacement); + } + graph().removeFloating(this); + } else { + graph().replaceFloating(this, replacement); + } + } + @Override public void generate(LIRGeneratorTool gen) { if (gen.canInlineConstant(value) || onlyUsedInVirtualState()) { diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Oct 25 01:26:27 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); } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Oct 25 01:26:27 2013 +0200 @@ -114,13 +114,23 @@ return StampFactory.forKind(kind); } - private static boolean addOverflows(long x, long y, Kind kind) { + private static boolean addOverflowsPositively(long x, long y, Kind kind) { long result = x + y; if (kind == Kind.Long) { - return ((x ^ result) & (y ^ result)) < 0; + return (~x & ~y & result) < 0; } else { assert kind == Kind.Int; - return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE; + return result > Integer.MAX_VALUE; + } + } + + private static boolean addOverflowsNegatively(long x, long y, Kind kind) { + long result = x + y; + if (kind == Kind.Long) { + return (x & y & ~result) < 0; + } else { + assert kind == Kind.Int; + return result < Integer.MIN_VALUE; } } @@ -142,16 +152,22 @@ long lowerBound; long upperBound; - if (addOverflows(stamp1.lowerBound(), stamp2.lowerBound(), kind) || addOverflows(stamp1.upperBound(), stamp2.upperBound(), kind)) { + boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), kind); + boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), kind); + if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsNegatively && !lowerOverflowsPositively && upperOverflowsPositively)) { lowerBound = kind.getMinValue(); upperBound = kind.getMaxValue(); } else { - lowerBound = stamp1.lowerBound() + stamp2.lowerBound(); - upperBound = stamp1.upperBound() + stamp2.upperBound(); + lowerBound = signExtend(stamp1.lowerBound() + stamp2.lowerBound(), kind); + upperBound = signExtend(stamp1.upperBound() + stamp2.upperBound(), kind); } IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound); newUpMask &= limit.upMask(); - return new IntegerStamp(kind, lowerBound | newDownMask, signExtend(upperBound & newUpMask, kind), newDownMask, newUpMask); + upperBound = signExtend(upperBound & newUpMask, kind); + lowerBound |= newDownMask; + return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask); } catch (Throwable e) { throw new RuntimeException(stamp1 + " + " + stamp2, e); } @@ -239,14 +255,15 @@ long lowerBound; long upperBound; long downMask = value.downMask() >>> shiftCount; + long upMask = value.upMask() >>> shiftCount; if (value.lowerBound() < 0) { lowerBound = downMask; - upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; + upperBound = upMask; } else { lowerBound = value.lowerBound() >>> shiftCount; upperBound = value.upperBound() >>> shiftCount; } - return new IntegerStamp(kind, lowerBound, upperBound, downMask, value.upMask() >>> shiftCount); + return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask); } } long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound()); @@ -310,7 +327,7 @@ } private static long signExtend(long value, Kind valueKind) { - if (valueKind != Kind.Char && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { + if (valueKind != Kind.Char && valueKind != Kind.Long && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { return value | (-1L << valueKind.getBitCount()); } else { return value; diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Fri Oct 25 01:26:27 2013 +0200 @@ -123,13 +123,17 @@ } public static void killWithUnusedFloatingInputs(Node node) { - List floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); - node.safeDelete(); + if (node.recordsUsages()) { + List 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(); } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Oct 25 01:26:27 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; } diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Oct 25 01:26:27 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 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); + } } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Oct 25 01:26:27 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(" "); } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Fri Oct 25 01:26:27 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; diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Oct 25 01:26:27 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()) { diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Oct 25 01:26:27 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]; diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Oct 25 01:26:27 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() { diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Oct 25 01:26:27 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); diff -r 7876c59a7a2f -r 8fde330c11cd 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 Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Oct 25 01:26:27 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); + } } } } diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Oct 25 01:26:27 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"); diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Fri Oct 25 01:26:27 2013 +0200 @@ -306,7 +306,7 @@ case LONG: return "Long"; case DECLARED: - return ((DeclaredType) mirror).asElement().getSimpleName().toString(); + return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString()); case ARRAY: return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; case VOID: @@ -379,7 +379,7 @@ } private static String getDeclaredName(DeclaredType element) { - String simpleName = element.asElement().getSimpleName().toString(); + String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString()); if (element.getTypeArguments().size() == 0) { return simpleName; @@ -399,6 +399,14 @@ return b.toString(); } + public static String fixECJBinaryNameIssue(String name) { + if (name.contains("$")) { + int lastIndex = name.lastIndexOf('$'); + return name.substring(lastIndex + 1, name.length()); + } + return name; + } + public static String getQualifiedName(TypeElement element) { String qualifiedName = element.getQualifiedName().toString(); if (qualifiedName.contains("$")) { diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Fri Oct 25 01:26:27 2013 +0200 @@ -135,7 +135,7 @@ } private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { - String name = type.asElement().getSimpleName().toString(); + String name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString()); if (needsImport(enclosedElement, type)) { TypeMirror usedByType = simpleNamesUsed.get(name); diff -r 7876c59a7a2f -r 8fde330c11cd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Fri Oct 25 01:24:19 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Fri Oct 25 01:26:27 2013 +0200 @@ -964,16 +964,78 @@ for (CodeExecutableElement method : createImplicitChildrenAccessors()) { clazz.add(method); } - clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); clazz.add(createInfoMessage(node)); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(clazz.asType(), null)); + clazz.add(createCopyPolymorphicConstructor(clazz.asType())); + } + if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { clazz.add(createGenericExecute(node, rootGroup)); } } + protected boolean needsInvokeCopyConstructorMethod() { + return getModel().getNode().isPolymorphic(); + } + + protected CodeExecutableElement createInvokeCopyConstructor(TypeMirror baseType, SpecializationData specialization) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), baseType, "invokeCopyConstructor"); + if (specialization == null) { + method.getModifiers().add(ABSTRACT); + } else { + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startNew(getElement().asType()); + builder.string("this"); + for (ActualParameter param : getImplicitTypeParamters(specialization)) { + builder.string(implicitTypeName(param)); + } + builder.end().end(); + } + return method; + } + + protected CodeExecutableElement createCopyPolymorphicConstructor(TypeMirror baseType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), baseType, "copyPolymorphic"); + CodeTreeBuilder builder = method.createBuilder(); + CodeTreeBuilder nullBuilder = builder.create(); + CodeTreeBuilder oldBuilder = builder.create(); + CodeTreeBuilder resetBuilder = builder.create(); + + for (ActualParameter param : getModel().getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + + CodeTreeBuilder access = builder.create(); + access.string("this.").string(child.getName()); + if (child.getCardinality().isMany()) { + access.string("[").string(String.valueOf(param.getIndex())).string("]"); + } + + String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName()); + oldBuilder.declaration(child.getNodeData().getNodeType(), oldName, access); + nullBuilder.startStatement().tree(access.getRoot()).string(" = null").end(); + resetBuilder.startStatement().tree(access.getRoot()).string(" = ").string(oldName).end(); + } + + builder.tree(oldBuilder.getRoot()); + builder.tree(nullBuilder.getRoot()); + + builder.startStatement().type(baseType).string(" copy = "); + builder.startCall("invokeCopyConstructor").end(); + builder.end(); + + builder.tree(resetBuilder.getRoot()); + builder.startReturn().string("copy").end(); + return method; + } + private List createImplicitChildrenAccessors() { NodeData node = getModel().getNode(); // Map> expectTypes = new HashMap<>(); @@ -1795,27 +1857,14 @@ String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); CodeTreeBuilder builder = parent.create(); + builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyPolymorphic()"); builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end()); - - for (ActualParameter param : node.getGenericSpecialization().getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = node.findChild(param.getSpecification().getName()); - if (child != null) { - builder.startStatement().string(currentNode).string(".").string(child.getName()); - if (child.getCardinality().isMany()) { - builder.string("[").string(String.valueOf(param.getIndex())).string("]"); - } - builder.string(" = null").end(); - } - } builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end(); - builder.startStatement().startCall("polymorphic", "setNext0").string(currentNode).end().end(); - builder.startStatement().startCall(currentNode, "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); + builder.startStatement().startCall("polymorphic", "setNext0").string("currentCopy").end().end(); + builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); builder.startReturn(); - builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization())); + builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization())); addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null); builder.end(); builder.end(); @@ -1981,6 +2030,21 @@ } } + protected final List getImplicitTypeParamters(SpecializationData model) { + List parameter = new ArrayList<>(); + for (ActualParameter param : model.getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (types.size() > 1) { + parameter.add(param); + } + } + return parameter; + } + protected final TreeSet lookupPolymorphicTargetTypes(ActualParameter param) { SpecializationData specialization = getModel(); TreeSet possiblePolymorphicTypes = new TreeSet<>(); @@ -2529,6 +2593,10 @@ getElement().add(createUpdateType(parameter)); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization)); + } + createCachedExecuteMethods(specialization); } @@ -2607,6 +2675,9 @@ if (specialization.getNode().isPolymorphic()) { getElement().add(createUpdateTypes(nodeGen.asType())); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization)); + } } protected void createConstructors(CodeTypeElement clazz) { @@ -2636,20 +2707,13 @@ builder.statement("this.next0 = null"); } - for (ActualParameter param : getModel().getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); - superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); - - builder.startStatement(); - builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); - builder.end(); - } + for (ActualParameter param : getImplicitTypeParamters(getModel())) { + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); + superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); + + builder.startStatement(); + builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); + builder.end(); } clazz.add(superConstructor); diff -r 7876c59a7a2f -r 8fde330c11cd mxtool/mx.py --- a/mxtool/mx.py Fri Oct 25 01:24:19 2013 +0200 +++ b/mxtool/mx.py Fri Oct 25 01:26:27 2013 +0200 @@ -768,7 +768,7 @@ abort('Missing "suite=" 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') diff -r 7876c59a7a2f -r 8fde330c11cd src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Oct 25 01:24:19 2013 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Oct 25 01:26:27 2013 +0200 @@ -1430,7 +1430,7 @@ } else { tty->print(" (Graal: installed code has no name) "); } - } else { + } else if (nm->is_compiled_by_graal()) { tty->print(" (Graal: no installed code) "); } #endif //GRAAL