# HG changeset patch # User Michael Van De Vanter # Date 1400953698 25200 # Node ID 079229f002a32bf2f77ecd27937d13adad3dc44b # Parent 09ac9ac9c4fc88d31f79e10371079a4559cf003f# Parent f4510fd9e8b3ad6965b3162b27edb476baa7140d Merge with f4510fd9e8b3ad6965b3162b27edb476baa7140d diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Sat May 24 10:48:18 2014 -0700 @@ -45,6 +45,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java Sat May 24 10:48:18 2014 -0700 @@ -45,6 +45,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Sat May 24 10:48:18 2014 -0700 @@ -45,6 +45,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java Sat May 24 10:48:18 2014 -0700 @@ -45,6 +45,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java Sat May 24 10:48:18 2014 -0700 @@ -47,6 +47,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java Sat May 24 10:48:18 2014 -0700 @@ -46,6 +46,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java Sat May 24 10:48:18 2014 -0700 @@ -44,6 +44,11 @@ } @Override + protected boolean supportsRequiredCapabilities() { + return (canDeoptimize()); + } + + @Override public void runTest() { setupArrays(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java Sat May 24 10:48:18 2014 -0700 @@ -23,12 +23,13 @@ package com.oracle.graal.compiler.hsail.test.lambda; -import java.util.stream.IntStream; - +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static org.junit.Assert.*; -import org.junit.Test; -import java.util.Arrays; -import java.util.ArrayList; + +import java.util.*; +import java.util.stream.*; + +import org.junit.*; /** * Several tests for the Sumatra APIs. @@ -266,6 +267,10 @@ // Graal throws NYI @Test public void testForEachIntRangeNoCapturesUseEscapingNew() { + if (runtime().getConfig().useHSAILDeoptimization == false) { + return; + } + MyPoint[] dest = new MyPoint[size]; IntStream range = IntStream.range(0, dest.length).parallel(); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyDeoptTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyDeoptTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyDeoptTest.java Sat May 24 10:48:18 2014 -0700 @@ -122,7 +122,7 @@ @Override protected boolean supportsRequiredCapabilities() { - return (canHandleDeoptVirtualObjects()); + return (canHandleDeoptVirtualObjects() && canDeoptimize()); } @Test diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Sat May 24 10:48:18 2014 -0700 @@ -84,11 +84,11 @@ // structure changes significantly StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); - new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); new OptimizeGuardAnchorsPhase().apply(graph); - new ReadEliminationPhase().apply(graph); - new CanonicalizerPhase(true).apply(graph, context); + canonicalizer.apply(graph, context); Debug.dump(graph, "After lowering"); diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Sat May 24 10:48:18 2014 -0700 @@ -65,7 +65,7 @@ boolean callKillsRegisters; - private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32; + private static final int SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT = 1; public static class BlockData { @@ -147,13 +147,6 @@ BitMap2D intervalInLoop; /** - * The variable operands allocated from this pool. The {@linkplain #operandNumber(Value) number} - * of the first variable operand in this pool is one greater than the number of the last - * register operand in the pool. - */ - private final ArrayList variables; - - /** * The {@linkplain #operandNumber(Value) number} of the first variable operand allocated. */ private final int firstVariableNumber; @@ -167,7 +160,6 @@ this.registers = target.arch.getRegisters(); this.firstVariableNumber = registers.length; - this.variables = new ArrayList<>(ir.numVariables() * 3 / 2); this.blockData = new BlockMap<>(ir.getControlFlowGraph()); } @@ -204,20 +196,6 @@ } /** - * Gets the operand denoted by a given operand number. - */ - private AllocatableValue operandFor(int operandNumber) { - if (operandNumber < firstVariableNumber) { - assert operandNumber >= 0; - return registers[operandNumber].asValue(); - } - int index = operandNumber - firstVariableNumber; - Variable variable = variables.get(index); - assert variable.index == index; - return variable; - } - - /** * Gets the number of operands. This value will increase by 1 for new variable. */ private int operandSize() { @@ -304,12 +282,10 @@ firstDerivedIntervalIndex = intervalsSize; } if (intervalsSize == intervals.length) { - intervals = Arrays.copyOf(intervals, intervals.length * 2); + intervals = Arrays.copyOf(intervals, intervals.length + (intervals.length >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)); } intervalsSize++; Variable variable = new Variable(source.kind(), ir.nextVariable()); - assert variables.size() == variable.index; - variables.add(variable); Interval interval = createInterval(variable); assert intervals[intervalsSize - 1] == interval; @@ -342,6 +318,10 @@ return intervalInLoop.at(interval, loop); } + Interval intervalFor(int operandNumber) { + return intervals[operandNumber]; + } + Interval intervalFor(Value operand) { int operandNumber = operandNumber(operand); assert operandNumber < intervalsSize; @@ -609,16 +589,16 @@ * {@linkplain ComputeBlockOrder linear scan order}. */ void numberInstructions() { + + intervalsSize = operandSize(); + intervals = new Interval[intervalsSize + (intervalsSize >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)]; + ValueProcedure setVariableProc = new ValueProcedure() { @Override public Value doValue(Value value) { if (isVariable(value)) { - int variableIdx = asVariable(value).index; - while (variables.size() <= variableIdx) { - variables.add(null); - } - variables.set(variableIdx, asVariable(value)); + getOrCreateInterval(asVariable(value)); } return value; } @@ -659,13 +639,6 @@ } assert index == numInstructions : "must match"; assert (index << 1) == opId : "must match: " + (index << 1); - - if (DetailedAsserts.getValue()) { - for (int i = 0; i < variables.size(); i++) { - assert variables.get(i) != null && variables.get(i).index == i; - } - assert variables.size() == ir.numVariables(); - } } /** @@ -687,66 +660,66 @@ List instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); + ValueProcedure useProc = new ValueProcedure() { + + @Override + protected Value doValue(Value operand) { + if (isVariable(operand)) { + int operandNum = operandNumber(operand); + if (!liveKill.get(operandNum)) { + liveGen.set(operandNum); + Debug.log("liveGen for operand %d", operandNum); + } + if (block.getLoop() != null) { + intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); + } + } + + if (DetailedAsserts.getValue()) { + verifyInput(block, liveKill, operand); + } + return operand; + } + }; + ValueProcedure stateProc = new ValueProcedure() { + + @Override + public Value doValue(Value operand) { + int operandNum = operandNumber(operand); + if (!liveKill.get(operandNum)) { + liveGen.set(operandNum); + Debug.log("liveGen in state for operand %d", operandNum); + } + return operand; + } + }; + ValueProcedure defProc = new ValueProcedure() { + + @Override + public Value doValue(Value operand) { + if (isVariable(operand)) { + int varNum = operandNumber(operand); + liveKill.set(varNum); + Debug.log("liveKill for operand %d", varNum); + if (block.getLoop() != null) { + intervalInLoop.setBit(varNum, block.getLoop().getIndex()); + } + } + + if (DetailedAsserts.getValue()) { + // fixed intervals are never live at block boundaries, so + // they need not be processed in live sets + // process them only in debug mode so that this can be checked + verifyTemp(liveKill, operand); + } + return operand; + } + }; + // iterate all instructions of the block for (int j = 0; j < numInst; j++) { final LIRInstruction op = instructions.get(j); - ValueProcedure useProc = new ValueProcedure() { - - @Override - protected Value doValue(Value operand) { - if (isVariable(operand)) { - int operandNum = operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - Debug.log("liveGen for operand %d", operandNum); - } - if (block.getLoop() != null) { - intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); - } - } - - if (DetailedAsserts.getValue()) { - verifyInput(block, liveKill, operand); - } - return operand; - } - }; - ValueProcedure stateProc = new ValueProcedure() { - - @Override - public Value doValue(Value operand) { - int operandNum = operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - Debug.log("liveGen in state for operand %d", operandNum); - } - return operand; - } - }; - ValueProcedure defProc = new ValueProcedure() { - - @Override - public Value doValue(Value operand) { - if (isVariable(operand)) { - int varNum = operandNumber(operand); - liveKill.set(varNum); - Debug.log("liveKill for operand %d", varNum); - if (block.getLoop() != null) { - intervalInLoop.setBit(varNum, block.getLoop().getIndex()); - } - } - - if (DetailedAsserts.getValue()) { - // fixed intervals are never live at block boundaries, so - // they need not be processed in live sets - // process them only in debug mode so that this can be checked - verifyTemp(liveKill, operand); - } - return operand; - } - }; - try (Indent indent2 = Debug.logAndIndent("handle op %d", op.id())) { op.forEachInput(useProc); op.forEachAlive(useProc); @@ -824,14 +797,12 @@ // liveOut(block) is the union of liveIn(sux), for successors sux of block int n = block.getSuccessorCount(); if (n > 0) { + liveOut.clear(); // block has successors if (n > 0) { - liveOut.clear(); for (AbstractBlock successor : block.getSuccessors()) { liveOut.or(blockData.get(successor).liveIn); } - } else { - liveOut.clear(); } if (!blockSets.liveOut.equals(liveOut)) { @@ -908,14 +879,14 @@ BitSet startBlockLiveIn = blockData.get(ir.getControlFlowGraph().getStartBlock()).liveIn; try (Indent indent2 = Debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) { for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { - Value operand = operandFor(operandNum); + Value operand = intervalFor(operandNum).operand; Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getValueForOperandFromDebugContext(operand)); } } // print some additional information to simplify debugging for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { - Value operand = operandFor(operandNum); + Value operand = intervalFor(operandNum).operand; try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, getValueForOperandFromDebugContext(operand))) { Deque> definedIn = new ArrayDeque<>(); @@ -1153,9 +1124,6 @@ try (Indent indent = Debug.logAndIndent("build intervals")) { - intervalsSize = operandSize(); - intervals = new Interval[intervalsSize + INITIAL_SPLIT_INTERVALS_CAPACITY]; - // create a list with all caller-save registers (cpu, fpu, xmm) Register[] callerSaveRegs = frameMap.registerConfig.getCallerSaveRegisters(); @@ -1176,7 +1144,7 @@ BitSet live = blockData.get(block).liveOut; for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) { assert live.get(operandNum) : "should not stop here otherwise"; - AllocatableValue operand = operandFor(operandNum); + AllocatableValue operand = intervalFor(operandNum).operand; Debug.log("live in %d: %s", operandNum, operand); addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, Kind.Illegal); @@ -1186,7 +1154,7 @@ // that the block was part of a non-natural loop, so it might // have an invalid loop index. if (block.isLoopEnd() && block.getLoop() != null && isIntervalInLoop(operandNum, block.getLoop().getIndex())) { - intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd); + intervalFor(operandNum).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd); } } @@ -1398,7 +1366,7 @@ int newLen = newList.length; // conventional sort-algorithm for new intervals - Arrays.sort(newList, INTERVAL_COMPARATOR); + Arrays.sort(newList, (Interval a, Interval b) -> a.from() - b.from()); // merge old and new list (both already sorted) into one combined list Interval[] combinedList = new Interval[oldLen + newLen]; @@ -1418,25 +1386,6 @@ sortedIntervals = combinedList; } - private static final Comparator INTERVAL_COMPARATOR = new Comparator() { - - public int compare(Interval a, Interval b) { - if (a != null) { - if (b != null) { - return a.from() - b.from(); - } else { - return -1; - } - } else { - if (b != null) { - return 1; - } else { - return 0; - } - } - } - }; - public void allocateRegisters() { try (Indent indent = Debug.logAndIndent("allocate registers")) { Interval precoloredIntervals; @@ -1469,25 +1418,12 @@ throw new BailoutException("LinearScan: interval is null"); } - Interval intervalAtBlockBegin(AbstractBlock block, Value operand) { - assert isVariable(operand) : "register number out of bounds"; - assert intervalFor(operand) != null : "no interval found"; - - return splitChildAtOpId(intervalFor(operand), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); + Interval intervalAtBlockBegin(AbstractBlock block, int operandNumber) { + return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); } - Interval intervalAtBlockEnd(AbstractBlock block, Value operand) { - assert isVariable(operand) : "register number out of bounds"; - assert intervalFor(operand) != null : "no interval found"; - - return splitChildAtOpId(intervalFor(operand), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); - } - - Interval intervalAtOpId(Value operand, int opId) { - assert isVariable(operand) : "register number out of bounds"; - assert intervalFor(operand) != null : "no interval found"; - - return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.USE); + Interval intervalAtBlockEnd(AbstractBlock block, int operandNumber) { + return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); } void resolveCollectMappings(AbstractBlock fromBlock, AbstractBlock toBlock, MoveResolver moveResolver) { @@ -1501,9 +1437,8 @@ assert operandNum < numOperands : "live information set for not exisiting interval"; assert blockData.get(fromBlock).liveOut.get(operandNum) && blockData.get(toBlock).liveIn.get(operandNum) : "interval not live at this edge"; - Value liveOperand = operandFor(operandNum); - Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand); - Interval toInterval = intervalAtBlockBegin(toBlock, liveOperand); + Interval fromInterval = intervalAtBlockEnd(fromBlock, operandNum); + Interval toInterval = intervalAtBlockBegin(toBlock, operandNum); if (fromInterval != toInterval && !fromInterval.location().equals(toInterval.location())) { // need to insert move instruction @@ -1914,7 +1849,6 @@ } printLir("After register number assignment", true); - } } @@ -1946,10 +1880,6 @@ // (check that all intervals have a correct register and that no registers are overwritten) verifyIntervals(); - // verifyNoOopsInFixedIntervals(); - - verifyConstants(); - verifyRegisters(); Debug.log("no errors found"); @@ -2103,23 +2033,6 @@ } } - void verifyConstants() { - try (Indent indent = Debug.logAndIndent("verifying that unpinned constants are not alive across block boundaries")) { - for (AbstractBlock block : sortedBlocks) { - BitSet liveAtEdge = blockData.get(block).liveIn; - - // visit all operands where the liveAtEdge bit is set - for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) { - Debug.log("checking interval %d of block B%d", operandNum, block.getId()); - Value operand = operandFor(operandNum); - assert isVariable(operand) : "value must have variable operand"; - // TKR assert value.asConstant() == null || value.isPinned() : - // "only pinned constants can be alive accross block boundaries"; - } - } - } - } - /** * Returns a value for a interval definition, which can be used for re-materialization. * diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Sat May 24 10:48:18 2014 -0700 @@ -219,7 +219,7 @@ */ private static final boolean DEBUG = false; - private static final String MATCHPROCESSOR_LOG = "/tmp/matchprocessor.log"; + private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "matchprocessor.log").getPath(); private static PrintWriter log; @@ -230,7 +230,7 @@ private static synchronized PrintWriter getLog() { if (log == null) { try { - log = new PrintWriter(new FileWriter(MATCHPROCESSOR_LOG, true)); + log = new PrintWriter(new FileWriter(LOGFILE, true)); } catch (IOException e) { // Do nothing } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Sat May 24 10:48:18 2014 -0700 @@ -52,9 +52,6 @@ if (OptFloatingReads.getValue()) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); - if (OptReadElimination.getValue()) { - appendPhase(new ReadEliminationPhase()); - } } appendPhase(new RemoveValueProxyPhase()); @@ -78,7 +75,7 @@ appendPhase(canonicalizer); } - appendPhase(new LoopSafepointEliminationPhase()); + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopSafepointEliminationPhase())); appendPhase(new LoopSafepointInsertionPhase()); diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat May 24 10:48:18 2014 -0700 @@ -277,7 +277,11 @@ } public static Scope forceLog() { - return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD)); + ArrayList context = new ArrayList<>(); + for (Object obj : context()) { + context.add(obj); + } + return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD), context.toArray()); } /** diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Sat May 24 10:48:18 2014 -0700 @@ -748,11 +748,7 @@ } public NodeMap createNodeMap() { - return createNodeMap(false); - } - - public NodeMap createNodeMap(boolean autoGrow) { - return new NodeMap<>(this, autoGrow); + return new NodeMap<>(this); } public NodeFlood createNodeFlood() { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Sat May 24 10:48:18 2014 -0700 @@ -28,28 +28,21 @@ public class NodeMap extends NodeIdAccessor { - private final boolean autogrow; protected Object[] values; public NodeMap(Graph graph) { - this(graph, false); - } - - public NodeMap(Graph graph, boolean autogrow) { super(graph); this.values = new Object[graph.nodeIdCount()]; - this.autogrow = autogrow; } public NodeMap(NodeMap copyFrom) { super(copyFrom.graph); this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); - this.autogrow = copyFrom.autogrow; } @SuppressWarnings("unchecked") public T get(Node node) { - check(node); + assert check(node); return (T) values[getNodeId(node)]; } @@ -81,7 +74,7 @@ } public void set(Node node, T value) { - check(node); + assert check(node); values[getNodeId(node)] = value; } @@ -93,16 +86,10 @@ return getNodeId(node) >= size(); } - public void grow() { - this.values = Arrays.copyOf(values, graph.nodeIdCount()); - } - - private void check(Node node) { - if (autogrow && isNew(node)) { - grow(); - } + private boolean check(Node node) { assert node.graph() == graph : String.format("%s is not part of the graph", node); assert !isNew(node) : "this node was added to the graph after creating the node map : " + node; + return true; } public void clear() { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java Sat May 24 10:48:18 2014 -0700 @@ -27,7 +27,7 @@ public final class NodeNodeMap extends NodeMap implements Map { public NodeNodeMap(Graph graph) { - super(graph, true); + super(graph); } public NodeNodeMap(NodeNodeMap copyFrom) { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Sat May 24 10:48:18 2014 -0700 @@ -104,7 +104,7 @@ HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime); Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); HotSpotHostForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); - HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers); + HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); @@ -161,8 +161,9 @@ return new HotSpotSnippetReflectionProvider(); } - protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, + TargetDescription target) { + return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); } protected Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -35,8 +35,8 @@ private AMD64ConvertSnippets.Templates convertSnippets; - public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); } @Override diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Sat May 24 10:48:18 2014 -0700 @@ -59,7 +59,10 @@ private static ValueNode filterCompression(ValueNode node) { ValueNode result = node; - while (result instanceof CompressionNode) { + if (result instanceof PiNode) { + result = ((PiNode) result).getOriginalNode(); + } + if (result instanceof CompressionNode) { result = ((CompressionNode) result).getInput(); } return result; diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Sat May 24 10:48:18 2014 -0700 @@ -489,6 +489,10 @@ boolean useHSAILDeoptimization = config.useHSAILDeoptimization; boolean useHSAILSafepoints = config.useHSAILSafepoints; + if ((useHSAILSafepoints == true) && (useHSAILDeoptimization == false)) { + Debug.log("+UseHSAILSafepoints requires +UseHSAILDeoptimization"); + } + // see what graph nodes we have to see if we are using the thread register // if not, we don't have to emit the code that sets that up // maybe there is a better way to do this? diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Sat May 24 10:48:18 2014 -0700 @@ -36,8 +36,9 @@ @ServiceProvider(HotSpotBackendFactory.class) public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory { - protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, + TargetDescription target) { + return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); } @Override @@ -46,10 +47,11 @@ HotSpotRegisters registers = new HotSpotRegisters(HSAIL.threadRegister, Register.None, Register.None); HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); - HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget()); + TargetDescription target = createTarget(); + HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, target); ConstantReflectionProvider constantReflection = host.getConstantReflection(); HotSpotForeignCallsProvider foreignCalls = new HSAILHotSpotForeignCallsProvider(runtime, metaAccess, codeCache); - HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers); + HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Sat May 24 10:48:18 2014 -0700 @@ -180,7 +180,7 @@ * We need 64-bit and 32-bit scratch registers for the codegen $s0 can be live at this block. */ private void emitDeoptimizeInner(Value actionAndReason, LIRFrameState lirFrameState, String emitName) { - DeoptimizeOp deopt = new DeoptimizeOp(actionAndReason, lirFrameState, emitName, getMetaAccess()); + DeoptimizeOp deopt = new DeoptimizeOp(actionAndReason, lirFrameState, emitName, config.useHSAILDeoptimization, getMetaAccess()); ((HSAILHotSpotLIRGenerationResult) getResult()).addDeopt(deopt); append(deopt); } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -121,15 +121,14 @@ return strategyMap.get(n.getClass()); } - public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); initStrategyMap(); } @Override public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { super.initialize(providers, config); - TargetDescription target = providers.getCodeCache().getTarget(); hsailNewObjectSnippets = new HSAILNewObjectSnippets.Templates(providers, target); } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Sat May 24 10:48:18 2014 -0700 @@ -104,7 +104,7 @@ @Override public void visitSafepointNode(SafepointNode i) { HotSpotVMConfig config = getGen().config; - if (config.useHSAILSafepoints == true) { + if ((config.useHSAILSafepoints == true) && (config.useHSAILDeoptimization == true)) { LIRFrameState info = state(i); HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this); ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Sat May 24 10:48:18 2014 -0700 @@ -41,49 +41,54 @@ @State protected LIRFrameState frameState; protected int codeBufferPos = -1; final int offsetToNoticeSafepoints; + final HotSpotVMConfig config; public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) { actionAndReason = tool.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.None, DeoptimizationReason.None, 0); frameState = state; offsetToNoticeSafepoints = config.hsailNoticeSafepointsOffset; + this.config = config; } @Override public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + if (config.useHSAILDeoptimization) { + // get a unique codeBuffer position + // when we save our state, we will save this as well (it can be used as a key to get the + // debugInfo) + codeBufferPos = masm.position(); - // get a unique codeBuffer position - // when we save our state, we will save this as well (it can be used as a key to get the - // debugInfo) - codeBufferPos = masm.position(); + masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); + String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos; - masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); - String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos; + AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); + AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object); + AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); + masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64"); - AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); - AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object); - AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); - masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64"); + // Build address of noticeSafepoints field + HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress(); + masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr); - // Build address of noticeSafepoints field - HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress(); - masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr); - - // Load int value from that field - HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress(); - masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr); - masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false); - masm.cbr(afterSafepointLabel); + // Load int value from that field + HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress(); + masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr); + masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false); + masm.cbr(afterSafepointLabel); - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); - AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); - masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); - masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); - masm.emitJumpToLabelName(masm.getDeoptLabelName()); + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); + masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); + masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); + masm.emitJumpToLabelName(masm.getDeoptLabelName()); - masm.emitString0(afterSafepointLabel + ":\n"); + masm.emitString0(afterSafepointLabel + ":\n"); - // now record the debuginfo - crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT); + // now record the debuginfo + crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT); + } else { + masm.emitComment("/* HSAIL safepoint would have been here. */"); + } } public LIRFrameState getFrameState() { @@ -93,4 +98,4 @@ public int getCodeBufferPos() { return codeBufferPos; } -} \ No newline at end of file +} diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Sat May 24 10:48:18 2014 -0700 @@ -221,7 +221,7 @@ final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); // lowerer extends HotSpotLoweringProvider so we can just use that HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); + int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind)); Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Sat May 24 10:48:18 2014 -0700 @@ -55,7 +55,7 @@ HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime); Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); - LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -32,8 +32,8 @@ public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { - public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); } @Override diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Sat May 24 10:48:18 2014 -0700 @@ -20,103 +20,38 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*; import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*; -import static java.nio.file.Files.*; +import static java.lang.Double.*; -import java.io.*; import java.lang.reflect.*; -import java.nio.charset.*; -import java.nio.file.*; import java.util.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; -import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.common.inlining.*; /** - * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are - * (currently) distinguished by a {@code "-G:"} prefix. + * Called from {@code graalCompiler.cpp} to set Graal options from the HotSpot command line. Such + * options are (currently) distinguished by a {@code "-G:"} prefix. */ public class HotSpotOptions { - private static final Map options = new HashMap<>(); - /** - * Initializes {@link #options} from {@link Options} services. - */ - private static void initializeOptions() { - ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); - for (Options opts : sl) { - for (OptionDescriptor desc : opts) { - if (isHotSpotOption(desc)) { - String name = desc.getName(); - OptionDescriptor existing = options.put(name, desc); - assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); - } - } - } - } - - /** - * Determines if a given option is a HotSpot command line option. + * Parses the Graal specific options specified to HotSpot (e.g., on the command line). + * + * @return true if the CITime or CITimeEach HotSpot VM options are set */ - public static boolean isHotSpotOption(OptionDescriptor desc) { - return desc.getClass().getName().startsWith("com.oracle.graal"); - } - - /** - * Loads default option value overrides from a {@code graal.options} file if it exists. Each - * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal - * command line option without the leading {@code "-G:"} prefix. These option value are set - * prior to processing of any Graal options present on the command line. - */ - private static void loadOptionOverrides() throws InternalError { - String javaHome = System.getProperty("java.home"); - Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options"); - if (!exists(graalDotOptions)) { - graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options"); - } - if (exists(graalDotOptions)) { - try { - for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) { - if (!line.startsWith("#")) { - if (!parseOption(line, null)) { - throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions); - } - } - } - } catch (IOException e) { - throw (InternalError) new InternalError().initCause(e); - } - } - } - - /** - * Gets the Graal specific options specified to HotSpot (e.g., on the command line). - * - * @param timeCompilations (out) true if the CITime or CITimeEach HotSpot VM options are set - */ - private static native String[] getVMOptions(boolean[] timeCompilations); + private static native boolean parseVMOptions(); static { - initializeOptions(); - loadOptionOverrides(); - - boolean[] timeCompilations = {false}; - for (String option : getVMOptions(timeCompilations)) { - if (!parseOption(option, null)) { - throw new InternalError("Invalid Graal option \"-G:" + option + "\""); - } - } - - if (timeCompilations[0] || PrintCompRate.getValue() != 0) { + boolean timeCompilations = parseVMOptions(); + if (timeCompilations || PrintCompRate.getValue() != 0) { unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes"); unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime"); } @@ -138,6 +73,42 @@ } /** + * Helper for the VM code called by {@link #parseVMOptions()}. + * + * @param name the name of a parsed option + * @param option the object encapsulating the option + * @param spec specification of boolean option value, type of option value or action to take + */ + static void setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) { + switch (spec) { + case '+': + option.setValue(Boolean.TRUE); + break; + case '-': + option.setValue(Boolean.FALSE); + break; + case '?': + printFlags(); + break; + case ' ': + printNoMatchMessage(name); + break; + case 'i': + option.setValue((int) primitiveValue); + break; + case 'f': + option.setValue((float) longBitsToDouble(primitiveValue)); + break; + case 'd': + option.setValue(longBitsToDouble(primitiveValue)); + break; + case 's': + option.setValue(stringValue); + break; + } + } + + /** * Parses a given option value specification. * * @param option the specification of an option and its value @@ -176,15 +147,7 @@ OptionDescriptor desc = options.get(optionName); if (desc == null) { - Logger.info("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); - List matches = fuzzyMatch(optionName); - if (!matches.isEmpty()) { - Logger.info("Did you mean one of the following?"); - for (OptionDescriptor match : matches) { - boolean isBoolean = match.getType() == boolean.class; - Logger.info(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); - } - } + printNoMatchMessage(optionName); return false; } @@ -192,12 +155,12 @@ if (value == null) { if (optionType == Boolean.TYPE || optionType == Boolean.class) { - Logger.info("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format"); + System.err.println("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format"); return false; } if (valueString == null) { - Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); + System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); return false; } @@ -212,7 +175,7 @@ } } else { if (optionType != Boolean.class) { - Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); + System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); return false; } } @@ -223,16 +186,28 @@ } else { OptionValue optionValue = desc.getOptionValue(); optionValue.setValue(value); - // Logger.info("Set option " + desc.getName() + " to " + value); + // System.err.println("Set option " + desc.getName() + " to " + value); } } else { - Logger.info("Wrong value \"" + valueString + "\" for option " + optionName); + System.err.println("Wrong value \"" + valueString + "\" for option " + optionName); return false; } return true; } + protected static void printNoMatchMessage(String optionName) { + System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); + List matches = fuzzyMatch(optionName); + if (!matches.isEmpty()) { + System.err.println("Did you mean one of the following?"); + for (OptionDescriptor match : matches) { + boolean isBoolean = match.getType() == boolean.class; + System.err.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); + } + } + } + /** * Sets the relevant system property such that a {@link DebugTimer} or {@link DebugMetric} * associated with a field in a class will be unconditionally enabled when it is created. @@ -255,7 +230,7 @@ } String previous = System.setProperty(propertyName, "true"); if (previous != null) { - Logger.info("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\""); + System.err.println("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\""); } } catch (Exception e) { throw new GraalInternalError(e); @@ -305,16 +280,16 @@ } private static void printFlags() { - Logger.info("[Graal flags]"); - SortedMap sortedOptions = new TreeMap<>(options); + System.out.println("[Graal flags]"); + SortedMap sortedOptions = options; for (Map.Entry e : sortedOptions.entrySet()) { e.getKey(); OptionDescriptor desc = e.getValue(); Object value = desc.getOptionValue().getValue(); List helpLines = wrap(desc.getHelp(), 70); - Logger.info(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0))); + System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0))); for (int i = 1; i < helpLines.size(); i++) { - Logger.info(String.format("%67s %s", " ", helpLines.get(i))); + System.out.println(String.format("%67s %s", " ", helpLines.get(i))); } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Sat May 24 10:48:18 2014 -0700 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.options.*; + +/** + * Helper class for separating loading of options from option initialization at runtime. + */ +class HotSpotOptionsLoader { + static final SortedMap options = new TreeMap<>(); + + /** + * Initializes {@link #options} from {@link Options} services. + */ + static { + ServiceLoader sl = ServiceLoader.load(Options.class); + for (Options opts : sl) { + for (OptionDescriptor desc : opts) { + if (isHotSpotOption(desc)) { + String name = desc.getName(); + OptionDescriptor existing = options.put(name, desc); + assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); + } + } + } + } + + /** + * Determines if a given option is a HotSpot command line option. + */ + private static boolean isHotSpotOption(OptionDescriptor desc) { + return desc.getClass().getName().startsWith("com.oracle.graal"); + } + + /** + * Command line utility for generating the source code of GraalRuntime::set_option() which is + * written {@link System#out}. + */ + public static void main(String[] args) { + PrintStream out = System.out; + try { + Set lengths = new TreeSet<>(); + for (String s : options.keySet()) { + lengths.add(s.length()); + } + lengths.add("PrintFlags".length()); + + out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {"); + out.println(" if (value[0] == '+' || value[0] == '-') {"); + out.println(" // boolean options"); + genMatchers(out, lengths, true); + out.println(" } else {"); + out.println(" // non-boolean options"); + genMatchers(out, lengths, false); + out.println(" }"); + out.println(" return false;"); + out.println("}"); + } catch (Throwable t) { + t.printStackTrace(out); + } + out.flush(); + } + + protected static void genMatchers(PrintStream out, Set lengths, boolean isBoolean) throws Exception { + out.println(" switch (name_len) {"); + for (int len : lengths) { + boolean printedCase = false; + + // The use of strncmp is required (instead of strcmp) as the option name will not be + // null terminated for = style options. + if (len == "PrintFlags".length() && isBoolean) { + printedCase = true; + out.println(" case " + len + ":"); + out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {\n", len); + out.println(" if (value[0] == '+') {"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); + out.println(" }"); + out.println(" return true;"); + out.println(" }"); + } + for (Map.Entry e : options.entrySet()) { + OptionDescriptor desc = e.getValue(); + if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { + if (!printedCase) { + printedCase = true; + out.println(" case " + len + ":"); + } + out.printf(" if (strncmp(name, \"%s\", %d) == 0) {\n", e.getKey(), len); + Class declaringClass = desc.getDeclaringClass(); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));\n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + if (isBoolean) { + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); + } else if (desc.getType() == String.class) { + out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); + } else { + char spec = getPrimitiveSpecChar(desc); + out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); + } + out.println(" return true;"); + out.println(" }"); + } + } + } + out.println(" }"); + } + + private static Class getFieldType(OptionDescriptor desc) throws Exception { + return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType(); + } + + private static String toInternalName(Class c) { + return c.getName().replace('.', '/'); + } + + /** + * @see HotSpotOptions#setOption(String, OptionValue, char, String, long) + */ + private static char getPrimitiveSpecChar(OptionDescriptor desc) { + if (desc.getType() == Integer.class) { + return 'i'; + } + if (desc.getType() == Float.class) { + return 'f'; + } + if (desc.getType() == Double.class) { + return 'd'; + } + throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName()); + } +} \ No newline at end of file diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat May 24 10:48:18 2014 -0700 @@ -40,7 +40,7 @@ * @param metaspaceMethod the metaspace Method object * @return a new byte array containing the original bytecode */ - byte[] initializeBytecode(long metaspaceMethod); + byte[] getBytecode(long metaspaceMethod); int exceptionTableLength(long metaspaceMethod); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat May 24 10:48:18 2014 -0700 @@ -43,7 +43,7 @@ public native long getMetaspaceMethod(Class holder, int slot); @Override - public native byte[] initializeBytecode(long metaspaceMethod); + public native byte[] getBytecode(long metaspaceMethod); @Override public native int exceptionTableLength(long metaspaceMethod); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -22,22 +22,14 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.meta.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; -import static com.oracle.graal.nodes.java.ArrayLengthNode.*; - -import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -56,16 +48,14 @@ import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.replacements.*; /** * HotSpot implementation of {@link LoweringProvider}. */ -public class DefaultHotSpotLoweringProvider implements HotSpotLoweringProvider { +public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider { protected final HotSpotGraalRuntime runtime; - protected final MetaAccessProvider metaAccess; protected final ForeignCallsProvider foreignCalls; protected final HotSpotRegistersProvider registers; @@ -74,25 +64,25 @@ protected NewObjectSnippets.Templates newObjectSnippets; protected MonitorSnippets.Templates monitorSnippets; protected WriteBarrierSnippets.Templates writeBarrierSnippets; - protected BoxingSnippets.Templates boxingSnippets; protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; protected UnsafeLoadSnippets.Templates unsafeLoadSnippets; - public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { + public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(metaAccess, target); this.runtime = runtime; - this.metaAccess = metaAccess; this.foreignCalls = foreignCalls; this.registers = registers; } public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { - TargetDescription target = providers.getCodeCache().getTarget(); + super.initialize(providers, providers.getSnippetReflection()); + + assert target == providers.getCodeCache().getTarget(); checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target); instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); newObjectSnippets = new NewObjectSnippets.Templates(providers, target); monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - boxingSnippets = new BoxingSnippets.Templates(providers, providers.getSnippetReflection(), target); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); @@ -102,38 +92,12 @@ public void lower(Node n, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) n.graph(); - if (n instanceof ArrayLengthNode) { - lowerArrayLengthNode((ArrayLengthNode) n, tool); - } else if (n instanceof Invoke) { + if (n instanceof Invoke) { lowerInvoke((Invoke) n, tool, graph); - } else if (n instanceof LoadFieldNode) { - lowerLoadFieldNode((LoadFieldNode) n, tool); - } else if (n instanceof StoreFieldNode) { - lowerStoreFieldNode((StoreFieldNode) n, tool); - } else if (n instanceof CompareAndSwapNode) { - lowerCompareAndSwapNode((CompareAndSwapNode) n); - } else if (n instanceof AtomicReadAndWriteNode) { - lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); - } else if (n instanceof LoadIndexedNode) { - lowerLoadIndexedNode((LoadIndexedNode) n, tool); - } else if (n instanceof StoreIndexedNode) { - lowerStoreIndexedNode((StoreIndexedNode) n, tool); - } else if (n instanceof UnsafeLoadNode) { - lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); - } else if (n instanceof UnsafeStoreNode) { - lowerUnsafeStoreNode((UnsafeStoreNode) n); - } else if (n instanceof JavaReadNode) { - lowerJavaReadNode((JavaReadNode) n); - } else if (n instanceof JavaWriteNode) { - lowerJavaWriteNode((JavaWriteNode) n); - } else if (n instanceof LoadHubNode) { - lowerLoadHubNode((LoadHubNode) n); } else if (n instanceof LoadMethodNode) { lowerLoadMethodNode((LoadMethodNode) n); } else if (n instanceof StoreHubNode) { lowerStoreHubNode((StoreHubNode) n, graph); - } else if (n instanceof CommitAllocationNode) { - lowerCommitAllocationNode((CommitAllocationNode) n, tool); } else if (n instanceof OSRStartNode) { lowerOSRStartNode((OSRStartNode) n); } else if (n instanceof DynamicCounterNode) { @@ -197,26 +161,13 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof BoxNode) { - boxingSnippets.lower((BoxNode) n, tool); - } else if (n instanceof UnboxNode) { - boxingSnippets.lower((UnboxNode) n, tool); } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) { /* No lowering, we generate LIR directly for these nodes. */ } else { - throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + super.lower(n, tool); } } - private void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) { - StructuredGraph graph = arrayLengthNode.graph(); - ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, graph), - StampFactory.positiveInt(), BarrierType.NONE, false)); - arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); - graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); - } - private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) { if (invoke.callTarget() instanceof MethodCallTargetNode) { MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -236,7 +187,7 @@ ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { Kind wordKind = runtime.getTarget().wordKind; - ValueNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); + ValueNode hub = createReadHub(graph, receiver, receiverNullCheck); ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod, receiverType); // We use LocationNode.ANY_LOCATION for the reads that access the @@ -261,291 +212,54 @@ } } - private Stamp loadStamp(Stamp stamp, Kind kind) { - return loadStamp(stamp, kind, true); - } - - private Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { - switch (kind) { - case Boolean: - case Byte: - return StampTool.narrowingConversion(stamp, 8); - - case Char: - case Short: - return StampTool.narrowingConversion(stamp, 16); - - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); - } + @Override + protected Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); } - return stamp; - } - - public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) { - return implicitLoadConvert(graph, kind, value, true); - } - - private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { - switch (kind) { - case Byte: - case Short: - return graph.unique(new SignExtendNode(value, 32)); - - case Boolean: - case Char: - return graph.unique(new ZeroExtendNode(value, 32)); - - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); - } - } - return value; - } - - private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { - StructuredGraph graph = loadField.graph(); - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); - ValueNode object = loadField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : loadField.object(); - assert loadField.getKind() != Kind.Illegal; - BarrierType barrierType = getFieldLoadBarrierType(field); - - Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind()); - ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadStamp, barrierType, false)); - ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); - - loadField.replaceAtUsages(readValue); - graph.replaceFixed(loadField, memoryRead); - - memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); - - if (loadField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); - graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); - graph.addAfterFixed(memoryRead, postMembar); - } + return super.loadStamp(stamp, kind, compressible); } - public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) { - return implicitStoreConvert(graph, kind, value, true); - } - - private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { - switch (kind) { - case Boolean: - case Byte: - return graph.unique(new NarrowNode(value, 8)); - case Char: - case Short: - return graph.unique(new NarrowNode(value, 16)); - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); - } + @Override + protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); } - return value; + return super.implicitLoadConvert(graph, kind, value, compressible); } - private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { - StructuredGraph graph = storeField.graph(); - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); - ValueNode object = storeField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : storeField.object(); - BarrierType barrierType = getFieldStoreBarrierType(storeField); - - ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value()); - WriteNode memoryWrite = graph.add(new WriteNode(object, value, createFieldLocation(graph, field, false), barrierType, false)); - memoryWrite.setStateAfter(storeField.stateAfter()); - graph.replaceFixedWithFixed(storeField, memoryWrite); - memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); - FixedWithNextNode last = memoryWrite; - FixedWithNextNode first = memoryWrite; - - if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); - graph.addBeforeFixed(first, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); - graph.addAfterFixed(last, postMembar); - } - } - - private void lowerCompareAndSwapNode(CompareAndSwapNode cas) { - StructuredGraph graph = cas.graph(); - Kind valueKind = cas.getValueKind(); - LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1); - - ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true); - ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true); - - LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrierType(cas), false)); - atomicNode.setStateAfter(cas.stateAfter()); - graph.replaceFixedWithFixed(cas, atomicNode); - } - - private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { - StructuredGraph graph = n.graph(); - Kind valueKind = n.getValueKind(); - LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1); - - ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); - - LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false)); - memoryRead.setStateAfter(n.stateAfter()); - - ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); - - n.replaceAtUsages(readValue); - graph.replaceFixedWithFixed(n, memoryRead); + @Override + protected ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) { + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph); } - private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { - StructuredGraph graph = loadIndexed.graph(); - Kind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - - Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadStamp, BarrierType.NONE, false)); - ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); - - memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); - - loadIndexed.replaceAtUsages(readValue); - graph.replaceFixed(loadIndexed, memoryRead); - } - - private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { - StructuredGraph graph = storeIndexed.graph(); - GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); - Kind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); - - ValueNode value = storeIndexed.value(); - ValueNode array = storeIndexed.array(); - - CheckCastNode checkcastNode = null; - CheckCastDynamicNode checkcastDynamicNode = null; - if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) { - // Store check! - ResolvedJavaType arrayType = StampTool.typeOrNull(array); - if (arrayType != null && StampTool.isExactType(array)) { - ResolvedJavaType elementType = arrayType.getComponentType(); - if (!MetaUtil.isJavaLangObject(elementType)) { - checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); - graph.addBeforeFixed(storeIndexed, checkcastNode); - value = checkcastNode; - } - } else { - Kind wordKind = runtime.getTarget().wordKind; - ValueNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph); - /* - * Anchor the read of the element klass to the cfg, because it is only valid when - * arrayClass is an object class, which might not be the case in other parts of the - * compiled method. - */ - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); - checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); - graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); - value = checkcastDynamicNode; - } + @Override + protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); } - BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); - WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), arrayLocation, barrierType, false)); - memoryWrite.setGuard(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - - // Lower the associated checkcast node. - if (checkcastNode != null) { - checkcastNode.lower(tool); - } else if (checkcastDynamicNode != null) { - checkcastDynamicSnippets.lower(checkcastDynamicNode, tool); - } + return super.implicitStoreConvert(graph, kind, value, compressible); } - private ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - Kind readKind = load.accessKind(); - LocationNode location = createLocation(load); - Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false)); - ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); - load.replaceAtUsages(readValue); - return memoryRead; - } - - private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { - StructuredGraph graph = load.graph(); - if (load.getGuardingCondition() != null) { - ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); - ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); - graph.replaceFixedWithFixed(load, valueAnchorNode); - graph.addAfterFixed(valueAnchorNode, memoryRead); - } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { - assert load.getKind() != Kind.Illegal; - if (addReadBarrier(load)) { - unsafeLoadSnippets.lower(load, tool); - } else { - ReadNode memoryRead = createUnsafeRead(graph, load, null); - // An unsafe read must not float outside its block otherwise - // it may float above an explicit null check on its object. - memoryRead.setGuard(BeginNode.prevBegin(load)); - graph.replaceFixedWithFixed(load, memoryRead); - } - } + @Override + protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) { + Kind wordKind = runtime.getTarget().wordKind; + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph); + /* + * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass + * is an object class, which might not be the case in other parts of the compiled method. + */ + return graph.unique(new FloatingReadNode(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor))); } - private void lowerUnsafeStoreNode(UnsafeStoreNode store) { - StructuredGraph graph = store.graph(); - LocationNode location = createLocation(store); - ValueNode object = store.object(); - BarrierType barrierType = getUnsafeStoreBarrierType(store); - boolean compressible = store.value().getKind() == Kind.Object; - Kind valueKind = store.accessKind(); - ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); - WriteNode write = graph.add(new WriteNode(object, value, location, barrierType, false)); - write.setStateAfter(store.stateAfter()); - graph.replaceFixedWithFixed(store, write); - } - - private void lowerJavaReadNode(JavaReadNode read) { - StructuredGraph graph = read.graph(); - - Kind valueKind = read.location().getValueKind(); - Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); - ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false)); - ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); - - memoryRead.setGuard(read.getGuard()); - - read.replaceAtUsages(readValue); - graph.replaceFixed(read, memoryRead); - } - - private void lowerJavaWriteNode(JavaWriteNode write) { - StructuredGraph graph = write.graph(); - - Kind valueKind = write.location().getValueKind(); - ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); - - WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization())); - memoryWrite.setStateAfter(write.stateAfter()); - graph.replaceFixedWithFixed(write, memoryWrite); - - memoryWrite.setGuard(write.getGuard()); - } - - private void lowerLoadHubNode(LoadHubNode loadHub) { - StructuredGraph graph = loadHub.graph(); - if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { - Kind wordKind = runtime.getTarget().wordKind; - assert loadHub.getKind() == wordKind; - ValueNode object = loadHub.object(); - GuardingNode guard = loadHub.getGuard(); - ValueNode hub = createReadHub(graph, wordKind, object, guard); - graph.replaceFloating(loadHub, hub); + @Override + protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + StructuredGraph graph = load.graph(); + if (load.getGuardingCondition() == null && graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal() && addReadBarrier(load)) { + unsafeLoadSnippets.lower(load, tool); + } else { + super.lowerUnsafeLoadNode(load, tool); } } @@ -561,88 +275,14 @@ graph.replaceFixed(storeHub, hub); } - private void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) { - StructuredGraph graph = commit.graph(); - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; - BitSet omittedValues = new BitSet(); - int valuePos = 0; - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - FixedWithNextNode newObject; - if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true)); - } else { - newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); - } - graph.addBeforeFixed(commit, newObject); - allocations[objIndex] = newObject; - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos); - if (value instanceof VirtualObjectNode) { - value = allocations[commit.getVirtualObjects().indexOf(value)]; - } - if (value == null) { - omittedValues.set(valuePos); - } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - // Constant.illegal is always the defaultForKind, so it is skipped - Kind valueKind = value.getKind(); - Kind entryKind = virtual.entryKind(i); + @Override + protected BarrierType fieldInitializationBarrier(Kind entryKind) { + return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; + } - // Truffle requires some leniency in terms of what can be put where: - Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; - assert valueKind.getStackKind() == entryKind.getStackKind() || - (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); - ConstantLocationNode location; - BarrierType barrierType; - if (virtual instanceof VirtualInstanceNode) { - ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, ((HotSpotResolvedJavaField) field).offset(), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; - } else { - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; - } - WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false); - graph.addAfterFixed(newObject, graph.add(write)); - } - valuePos++; - - } - } - valuePos = 0; - - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - ValueNode newObject = allocations[objIndex]; - for (int i = 0; i < entryCount; i++) { - if (omittedValues.get(valuePos)) { - ValueNode value = commit.getValues().get(valuePos); - assert value instanceof VirtualObjectNode; - ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; - if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { - assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object; - WriteNode write; - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), - true), BarrierType.IMPRECISE, false); - } else { - write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), - true), BarrierType.PRECISE, false); - } - graph.addBeforeFixed(commit, graph.add(write)); - } - } - valuePos++; - } - } - - finishAllocatedObjects(tool, commit, allocations); - graph.removeFixed(commit); - } + @Override + protected BarrierType arrayInitializationBarrier(Kind entryKind) { + return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; } private void lowerOSRStartNode(OSRStartNode osrStart) { @@ -729,79 +369,6 @@ } } - public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { - StructuredGraph graph = commit.graph(); - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); - allocations[objIndex] = anchor; - graph.addBeforeFixed(commit, anchor); - } - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { - MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId)); - graph.addBeforeFixed(commit, enter); - enter.lower(tool); - } - } - for (Node usage : commit.usages().snapshot()) { - AllocatedObjectNode addObject = (AllocatedObjectNode) usage; - int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); - graph.replaceFloating(addObject, allocations[index]); - } - } - - private static LocationNode createLocation(UnsafeAccessNode access) { - return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); - } - - private static LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { - ValueNode offset = offsetNode; - if (offset.isConstant()) { - long offsetValue = offset.asConstant().asLong(); - return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph()); - } - - long displacement = 0; - int indexScaling = 1; - boolean signExtend = false; - if (offset instanceof SignExtendNode) { - SignExtendNode extend = (SignExtendNode) offset; - if (extend.getResultBits() == 64) { - signExtend = true; - offset = extend.getInput(); - } - } - if (offset instanceof IntegerAddNode) { - IntegerAddNode integerAddNode = (IntegerAddNode) offset; - if (integerAddNode.y() instanceof ConstantNode) { - displacement = integerAddNode.y().asConstant().asLong(); - offset = integerAddNode.x(); - } - } - - if (offset instanceof LeftShiftNode) { - LeftShiftNode leftShiftNode = (LeftShiftNode) offset; - if (leftShiftNode.y() instanceof ConstantNode) { - long shift = leftShiftNode.y().asConstant().asLong(); - if (shift >= 1 && shift <= 3) { - if (shift == 1) { - indexScaling = 2; - } else if (shift == 2) { - indexScaling = 4; - } else { - indexScaling = 8; - } - offset = leftShiftNode.x(); - } - } - } - if (signExtend) { - // If we were using sign extended values before restore the sign extension. - offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64)); - } - return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); - } - private static boolean addReadBarrier(UnsafeLoadNode load) { if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object && !StampTool.isObjectAlwaysNull(load.object())) { @@ -825,7 +392,9 @@ return metaspaceMethod; } - private ValueNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) { + @Override + protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) { + Kind wordKind = target.wordKind; HotSpotVMConfig config = runtime.getConfig(); LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); @@ -858,7 +427,9 @@ return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE, false)); } - private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { + @Override + protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) { + HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f; BarrierType barrierType = BarrierType.NONE; if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) { barrierType = BarrierType.PRECISE; @@ -866,144 +437,32 @@ return barrierType; } - private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { - if (storeField.field().getKind() == Kind.Object) { - return BarrierType.IMPRECISE; - } - return BarrierType.NONE; - } - - private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) { - if (store.elementKind() == Kind.Object) { - return BarrierType.PRECISE; - } - return BarrierType.NONE; - } - - private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { - if (store.value().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(store.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) { - if (cas.expected().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(cas.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) { - if (n.newValue().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(n.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : field; - return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph); - } - - public int getScalingFactor(Kind kind) { - if (useCompressedOops() && kind == Kind.Object) { - return this.runtime.getTarget().getSizeInBytes(Kind.Int); - } else { - return this.runtime.getTarget().getSizeInBytes(kind); - } + @Override + protected int fieldOffset(ResolvedJavaField f) { + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; + return field.offset(); } @Override - public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind); - int scale = getScalingFactor(elementKind); - return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale); + public int arrayScalingFactor(Kind kind) { + if (useCompressedOops() && kind == Kind.Object) { + return this.runtime.getTarget().getSizeInBytes(Kind.Int); + } + return super.arrayScalingFactor(kind); } @Override - public ValueNode reconstructArrayIndex(LocationNode location) { - Kind elementKind = location.getValueKind(); - assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); - - long base; - ValueNode index; - int scale = getScalingFactor(elementKind); - - if (location instanceof ConstantLocationNode) { - base = ((ConstantLocationNode) location).getDisplacement(); - index = null; - } else if (location instanceof IndexedLocationNode) { - IndexedLocationNode indexedLocation = (IndexedLocationNode) location; - assert indexedLocation.getIndexScaling() == scale; - base = indexedLocation.getDisplacement(); - index = indexedLocation.getIndex(); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - - base -= getArrayBaseOffset(elementKind); - assert base >= 0 && base % scale == 0; - - base /= scale; - assert NumUtil.isInt(base); - - StructuredGraph graph = location.graph(); - if (index == null) { - return ConstantNode.forInt((int) base, graph); - } else { - if (base == 0) { - return index; - } else { - return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); - } - } + protected int arrayBaseOffset(Kind kind) { + return HotSpotGraalRuntime.getArrayBaseOffset(kind); } - private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { - StructuredGraph g = n.graph(); - ValueNode array = n.array(); - ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); - if (arrayLength == null) { - Stamp stamp = StampFactory.positiveInt(); - ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); - g.addBeforeFixed(n, readArrayLength); - readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); - arrayLength = readArrayLength; - } - - if (arrayLength.isConstant() && n.index().isConstant()) { - int l = arrayLength.asConstant().asInt(); - int i = n.index().asConstant().asInt(); - if (i >= 0 && i < l) { - // unneeded range check - return null; - } - } - - return tool.createGuard(n, g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + @Override + protected int arrayLengthOffset() { + return config().arrayLengthOffset; } - private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { - if (StampTool.isObjectNonNull(object)) { - return null; - } - return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + @Override + protected LocationIdentity initLocationIdentity() { + return INIT_LOCATION; } - } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -36,7 +36,7 @@ void initialize(HotSpotProviders providers, HotSpotVMConfig config); - int getScalingFactor(Kind kind); + int arrayScalingFactor(Kind kind); IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat May 24 10:48:18 2014 -0700 @@ -196,7 +196,7 @@ return null; } if (code == null && holder.isLinked()) { - code = runtime().getCompilerToVM().initializeBytecode(metaspaceMethod); + code = runtime().getCompilerToVM().getBytecode(metaspaceMethod); assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length; } return code; diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat May 24 10:48:18 2014 -0700 @@ -416,7 +416,7 @@ ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), providers.getMetaAccess(), graph); final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); + int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind)); Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java --- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Sat May 24 10:48:18 2014 -0700 @@ -54,7 +54,7 @@ */ private static final boolean DEBUG = true; - private static final String LOGFILE = "/tmp/hotspotvmconfigprocessor.log"; + private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "hotspotvmconfigprocessor.log").getPath(); private static PrintWriter log; @@ -109,7 +109,7 @@ //@formatter:off String[] prologue = new String[]{ - "// The normal wrappers boolAt and intxAt skip constant flags", + "// The normal wrappers CommandLineFlags::boolAt and CommandLineFlags::intxAt skip constant flags", "static bool boolAt(char* name, bool* value) {", " Flag* result = Flag::find_flag(name, strlen(name), true, true);", " if (result == NULL) return false;", @@ -157,12 +157,12 @@ out.println(); Set fieldTypes = new HashSet<>(); - for (String key : annotations.keySet()) { - fieldTypes.add(annotations.get(key).getType()); + for (VMConfigField key : annotations.values()) { + fieldTypes.add(key.getType()); } // For each type of field, generate a switch on the length of the symbol and then do a // direct compare. In general this reduces each operation to 2 tests plus a string - // compare. Being more prefect than that is probably not worth it. + // compare. Being more perfect than that is probably not worth it. for (String type : fieldTypes) { String sigtype = type.equals("boolean") ? "bool" : type; out.println(" if (fs.signature() == vmSymbols::" + sigtype + "_signature()) {"); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Sat May 24 10:48:18 2014 -0700 @@ -141,13 +141,15 @@ protected MetaAccessProvider metaAccessProvider; protected String emitName; protected int codeBufferPos = -1; + private final boolean emitInfopoint; - public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, MetaAccessProvider metaAccessProvider) { + public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, boolean emitInfopoint, MetaAccessProvider metaAccessProvider) { super(Value.ILLEGAL); // return with no ret value this.actionAndReason = actionAndReason; this.frameState = frameState; this.emitName = emitName; this.metaAccessProvider = metaAccessProvider; + this.emitInfopoint = emitInfopoint; } @Override @@ -181,8 +183,12 @@ masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); - // now record the debuginfo - crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.IMPLICIT_EXCEPTION); + // Now record the debuginfo. If HSAIL deoptimization is off, + // no debuginfo is emitted and the kernel will return without + // a deoptimization. + if (emitInfopoint) { + crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.IMPLICIT_EXCEPTION); + } } public LIRFrameState getFrameState() { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat May 24 10:48:18 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; @@ -481,30 +482,23 @@ AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next(); AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next(); MergeNode merge = trueEnd.merge(); - if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { + if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { Iterator phis = merge.phis().iterator(); if (!phis.hasNext()) { - // empty if construct with no phis: remove it - removeEmptyIf(tool); + tool.addToWorkList(condition()); + removeThroughFalseBranch(tool); return true; } else { PhiNode singlePhi = phis.next(); if (!phis.hasNext()) { // one phi at the merge of an otherwise empty if construct: try to convert // into a MaterializeNode - boolean inverted = trueEnd == merge.forwardEndAt(1); - ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0); - ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1); - if (trueValue.getKind() != falseValue.getKind()) { - return false; - } - if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { - return false; - } + ValueNode trueValue = singlePhi.valueAt(trueEnd); + ValueNode falseValue = singlePhi.valueAt(falseEnd); ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); if (conditional != null) { - graph().replaceFloating(singlePhi, conditional); - removeEmptyIf(tool); + singlePhi.setValueAt(trueEnd, conditional); + removeThroughFalseBranch(tool); return true; } } @@ -518,12 +512,6 @@ ValueNode falseValue = falseEnd.result(); ConditionalNode conditional = null; if (trueValue != null) { - if (trueValue.getKind() != falseValue.getKind()) { - return false; - } - if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { - return false; - } conditional = canonicalizeConditionalCascade(trueValue, falseValue); if (conditional == null) { return false; @@ -537,7 +525,19 @@ return false; } + protected void removeThroughFalseBranch(SimplifierTool tool) { + BeginNode trueBegin = trueSuccessor(); + graph().removeSplitPropagate(this, trueBegin, tool); + tool.addToWorkList(trueBegin); + } + private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) { + if (trueValue.getKind() != falseValue.getKind()) { + return null; + } + if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { + return null; + } if (trueValue.isConstant() && falseValue.isConstant()) { return graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); } else { @@ -703,6 +703,18 @@ connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool); connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool); + if (this.trueSuccessorProbability == 0.0) { + for (AbstractEndNode endNode : trueEnds) { + propagateZeroProbability(endNode); + } + } + + if (this.trueSuccessorProbability == 1.0) { + for (AbstractEndNode endNode : falseEnds) { + propagateZeroProbability(endNode); + } + } + /* * Remove obsolete ends only after processing all ends, otherwise oldTrueSuccessor or * oldFalseSuccessor might have been removed if it is a LoopExitNode. @@ -724,6 +736,42 @@ return true; } + private void propagateZeroProbability(FixedNode startNode) { + Node prev = null; + for (FixedNode node : GraphUtil.predecessorIterable(startNode)) { + if (node instanceof IfNode) { + IfNode ifNode = (IfNode) node; + if (ifNode.trueSuccessor() == prev) { + if (ifNode.trueSuccessorProbability == 0.0) { + return; + } else if (ifNode.trueSuccessorProbability == 1.0) { + continue; + } else { + ifNode.setTrueSuccessorProbability(0.0); + return; + } + } else if (ifNode.falseSuccessor() == prev) { + if (ifNode.trueSuccessorProbability == 1.0) { + return; + } else if (ifNode.trueSuccessorProbability == 0.0) { + continue; + } else { + ifNode.setTrueSuccessorProbability(1.0); + return; + } + } else { + throw new GraalInternalError("Illegal state"); + } + } else if (node instanceof MergeNode && !(node instanceof LoopBeginNode)) { + for (AbstractEndNode endNode : ((MergeNode) node).cfgPredecessors()) { + propagateZeroProbability(endNode); + } + return; + } + prev = node; + } + } + private static boolean checkFrameState(FixedNode start) { FixedNode node = start; while (true) { @@ -835,38 +883,4 @@ return null; } - - private void removeEmptyIf(SimplifierTool tool) { - BeginNode originalTrueSuccessor = trueSuccessor(); - BeginNode originalFalseSuccessor = falseSuccessor(); - assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode; - - AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next(); - AbstractEndNode falseEnd = (AbstractEndNode) originalFalseSuccessor.next(); - assert trueEnd.merge() == falseEnd.merge(); - - FixedWithNextNode pred = (FixedWithNextNode) predecessor(); - MergeNode merge = trueEnd.merge(); - merge.prepareDelete(pred); - assert merge.usages().isEmpty(); - originalTrueSuccessor.prepareDelete(); - originalFalseSuccessor.prepareDelete(); - - FixedNode next = merge.next(); - FrameState state = merge.stateAfter(); - merge.setNext(null); - setTrueSuccessor(null); - setFalseSuccessor(null); - pred.setNext(next); - safeDelete(); - originalTrueSuccessor.safeDelete(); - originalFalseSuccessor.safeDelete(); - merge.safeDelete(); - trueEnd.safeDelete(); - falseEnd.safeDelete(); - if (state != null) { - tool.removeIfUnused(state); - } - tool.addToWorkList(next); - } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat May 24 10:48:18 2014 -0700 @@ -82,6 +82,10 @@ values().set(i, x); } + public void setValueAt(AbstractEndNode end, ValueNode x) { + setValueAt(merge().phiPredecessorIndex(end), x); + } + public ValueNode valueAt(AbstractEndNode pred) { return valueAt(merge().phiPredecessorIndex(pred)); } diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Sat May 24 10:48:18 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; @@ -303,6 +304,10 @@ } public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) { + removeSplitPropagate(node, survivingSuccessor, null); + } + + public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor, SimplifierTool tool) { assert node != null; assert node.usages().isEmpty(); assert survivingSuccessor != null; @@ -313,7 +318,7 @@ for (Node successor : snapshot) { if (successor != null && successor.isAlive()) { if (successor != survivingSuccessor) { - GraphUtil.killCFG(successor); + GraphUtil.killCFG(successor, tool); } } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Sat May 24 10:48:18 2014 -0700 @@ -61,7 +61,7 @@ protected ControlFlowGraph(StructuredGraph graph) { this.graph = graph; - this.nodeToBlock = graph.createNodeMap(true); + this.nodeToBlock = graph.createNodeMap(); } public List getBlocks() { diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat May 24 10:48:18 2014 -0700 @@ -189,7 +189,9 @@ GraphUtil.tryKillUnused(valueNode); } else if (improvedStamp) { // the improved stamp may enable additional canonicalization - tryCanonicalize(valueNode, nodeClass); + if (!tryCanonicalize(valueNode, nodeClass)) { + valueNode.usages().forEach(workList::add); + } } } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Sat May 24 10:48:18 2014 -0700 @@ -710,7 +710,9 @@ if (nonNull) { replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type); } - replacementAnchor = BeginNode.prevBegin(checkCast); + if (replacementAnchor == null) { + replacementAnchor = BeginNode.prevBegin(checkCast); + } PiNode piNode; if (isNull) { ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Sat May 24 10:34:43 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.*; - -public class ReadEliminationPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) { - if (isReadEliminable(n)) { - NodeMap nodeMap = n.graph().createNodeMap(); - ValueNode value = getValue(n, n.getLastLocationAccess(), nodeMap); - Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value); - graph.replaceFloating(n, value); - } - } - } - - private static boolean isReadEliminable(FloatingReadNode n) { - return isWrites(n, n.getLastLocationAccess(), n.graph().createNodeBitMap()); - } - - private static boolean isWrites(FloatingReadNode n, MemoryNode lastLocationAccess, NodeBitMap visited) { - if (lastLocationAccess == null) { - return false; - } - if (visited.isMarked(ValueNodeUtil.asNode(lastLocationAccess))) { - return true; // dataflow loops must come from Phis assume them ok until proven wrong - } - if (lastLocationAccess instanceof ProxyNode) { - return isWrites(n, (MemoryNode) ((ProxyNode) lastLocationAccess).value(), visited); - } - if (lastLocationAccess instanceof WriteNode) { - WriteNode other = (WriteNode) lastLocationAccess; - return other.object() == n.object() && other.location() == n.location(); - } - if (lastLocationAccess instanceof MemoryPhiNode) { - visited.mark(ValueNodeUtil.asNode(lastLocationAccess)); - for (ValueNode value : ((MemoryPhiNode) lastLocationAccess).values()) { - if (!isWrites(n, (MemoryNode) value, visited)) { - return false; - } - } - return true; - } - return false; - } - - private static ValueNode getValue(FloatingReadNode n, MemoryNode lastLocationAccess, NodeMap nodeMap) { - ValueNode exisiting = nodeMap.get(ValueNodeUtil.asNode(lastLocationAccess)); - if (exisiting != null) { - return exisiting; - } - if (lastLocationAccess instanceof MemoryProxyNode) { - MemoryProxyNode proxy = (MemoryProxyNode) lastLocationAccess; - ValueNode value = getValue(n, proxy.getOriginalMemoryNode(), nodeMap); - return ProxyNode.forValue(value, proxy.proxyPoint(), proxy.graph()); - } - if (lastLocationAccess instanceof WriteNode) { - return ((WriteNode) lastLocationAccess).value(); - } - if (lastLocationAccess instanceof MemoryPhiNode) { - MemoryPhiNode phi = (MemoryPhiNode) lastLocationAccess; - ValuePhiNode newPhi = phi.graph().addWithoutUnique(new ValuePhiNode(n.stamp().unrestricted(), phi.merge())); - nodeMap.set(phi, newPhi); - for (ValueNode value : phi.values()) { - newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap)); - } - return newPhi; - } - throw GraalInternalError.shouldNotReachHere(); - } -} diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Sat May 24 10:48:18 2014 -0700 @@ -332,13 +332,13 @@ assert concretes.size() > 0; Debug.log("Method check cascade with %d methods", concretes.size()); - ValueNode[] constantMethods = new ValueNode[concretes.size()]; + ConstantNode[] constantMethods = new ConstantNode[concretes.size()]; double[] probability = new double[concretes.size()]; for (int i = 0; i < concretes.size(); ++i) { ResolvedJavaMethod firstMethod = concretes.get(i); Constant firstMethodConstant = firstMethod.getEncoding(); - ValueNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph); + ConstantNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph); constantMethods[i] = firstMethodConstantNode; double concretesProbability = concretesProbabilities.get(i); assert concretesProbability >= 0.0; diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Sat May 24 10:48:18 2014 -0700 @@ -51,23 +51,23 @@ public CallsiteHolder(StructuredGraph graph, double probability, double relevance) { this.graph = graph; - if (graph == null) { - this.remainingInvokes = new LinkedList<>(); - } else { - LinkedList invokes = new InliningIterator(graph).apply(); - assert invokes.size() == count(graph.getInvokes()); - this.remainingInvokes = invokes; - } this.probability = probability; this.relevance = relevance; - - if (graph != null && !remainingInvokes.isEmpty()) { - probabilities = new FixedNodeProbabilityCache(); - computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); - computeProbabilities(); - } else { + if (graph == null) { + remainingInvokes = new LinkedList<>(); probabilities = null; computeInliningRelevance = null; + } else { + remainingInvokes = new InliningIterator(graph).apply(); + assert remainingInvokes.size() == count(graph.getInvokes()); + if (remainingInvokes.isEmpty()) { + probabilities = null; + computeInliningRelevance = null; + } else { + probabilities = new FixedNodeProbabilityCache(); + computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); + computeProbabilities(); + } } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat May 24 10:48:18 2014 -0700 @@ -264,11 +264,6 @@ } } - if (concreteMethods.size() > maxMethodPerInlining) { - InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining); - return null; - } - // Clear methods that fall below the threshold. if (notRecordedTypeProbability > 0) { ArrayList newConcreteMethods = new ArrayList<>(); @@ -280,7 +275,7 @@ } } - if (newConcreteMethods.size() == 0) { + if (newConcreteMethods.isEmpty()) { // No method left that is worth inlining. InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)", concreteMethods.size()); @@ -291,6 +286,11 @@ concreteMethodsProbabilities = newConcreteMethodsProbabilities; } + if (concreteMethods.size() > maxMethodPerInlining) { + InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining); + return null; + } + // Clean out types whose methods are no longer available. ArrayList usedTypes = new ArrayList<>(); ArrayList typesToConcretes = new ArrayList<>(); @@ -306,7 +306,7 @@ } } - if (usedTypes.size() == 0) { + if (usedTypes.isEmpty()) { // No type left that is worth checking for. InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length); return null; @@ -410,17 +410,7 @@ double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance); - pushInvocation(methodInvocation); - - for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = info.inlineableElementAt(i); - if (elem instanceof InlineableGraph) { - pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); - } else { - assert elem instanceof InlineableMacroNode; - pushDummyGraph(); - } - } + pushInvocationAndGraphs(methodInvocation); } } @@ -449,6 +439,7 @@ private void pushDummyGraph() { graphQueue.push(DUMMY_CALLSITE_HOLDER); + assert graphQueue.size() <= maxGraphs; } public boolean hasUnprocessedGraphs() { @@ -492,10 +483,22 @@ return invocationQueue.peekFirst(); } - private void pushInvocation(MethodInvocation methodInvocation) { + private void pushInvocationAndGraphs(MethodInvocation methodInvocation) { invocationQueue.addFirst(methodInvocation); - maxGraphs += methodInvocation.callee().numberOfMethods(); + InlineInfo info = methodInvocation.callee(); + maxGraphs += info.numberOfMethods(); assert graphQueue.size() <= maxGraphs; + double invokeProbability = methodInvocation.probability(); + double invokeRelevance = methodInvocation.relevance(); + for (int i = 0; i < info.numberOfMethods(); i++) { + Inlineable elem = info.inlineableElementAt(i); + if (elem instanceof InlineableGraph) { + pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); + } else { + assert elem instanceof InlineableMacroNode; + pushDummyGraph(); + } + } } private void popInvocation() { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Sat May 24 10:48:18 2014 -0700 @@ -42,10 +42,14 @@ private final Map cache = newIdentityMap(); public double applyAsDouble(FixedNode node) { + assert node != null; metricComputeNodeProbability.increment(); FixedNode current = node; while (true) { + if (current == null) { + return 1D; + } Node predecessor = current.predecessor(); if (current instanceof BeginNode) { if (predecessor == null) { @@ -54,6 +58,9 @@ assert predecessor instanceof ControlSplitNode : "a FixedNode with multiple successors needs to be a ControlSplitNode: " + current + " / " + predecessor; break; } + } else if (predecessor == null) { + // this should only appear for dead code + return 1D; } current = (FixedNode) predecessor; } @@ -70,10 +77,8 @@ if (current instanceof LoopBeginNode) { probability *= ((LoopBeginNode) current).loopFrequency(); } - } else if (current instanceof StartNode) { - probability = 1D; } else { - // this should only appear for dead code + assert current instanceof StartNode; probability = 1D; } } else { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Sat May 24 10:48:18 2014 -0700 @@ -34,8 +34,13 @@ public static class LoopInfo { - public final List endStates = new ArrayList<>(); - public final List exitStates = new ArrayList<>(); + public final List endStates; + public final List exitStates; + + public LoopInfo(int endCount, int exitCount) { + endStates = new ArrayList<>(endCount); + exitStates = new ArrayList<>(exitCount); + } } public abstract static class BlockIteratorClosure { @@ -58,8 +63,8 @@ public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { Map blockEndStates = apply(closure, loop.getHeader(), initialState, new HashSet<>(loop.getBlocks())); - LoopInfo info = new LoopInfo<>(); List predecessors = loop.getHeader().getPredecessors(); + LoopInfo info = new LoopInfo<>(predecessors.size() - 1, loop.getExits().size()); for (int i = 1; i < predecessors.size(); i++) { StateT endState = blockEndStates.get(predecessors.get(i).getEndNode()); // make sure all end states are unique objects @@ -67,7 +72,7 @@ } for (Block loopExit : loop.getExits()) { assert loopExit.getPredecessorCount() == 1; - assert blockEndStates.containsKey(loopExit.getBeginNode()); + assert blockEndStates.containsKey(loopExit.getBeginNode()) : loopExit.getBeginNode() + " " + blockEndStates; StateT exitState = blockEndStates.get(loopExit.getBeginNode()); // make sure all exit states are unique objects info.exitStates.add(closure.cloneState(exitState)); @@ -90,7 +95,9 @@ Block current = start; while (true) { - if (boundary == null || boundary.contains(current)) { + if (boundary != null && !boundary.contains(current)) { + states.put(current.getBeginNode(), state); + } else { state = closure.processBlock(current, state); if (current.getSuccessors().isEmpty()) { @@ -117,45 +124,47 @@ blockQueue.addFirst(exit); } } - } else { - if (successor.getBeginNode() instanceof LoopExitNode) { - assert successor.getPredecessors().size() == 1; - states.put(successor.getBeginNode(), state); + } else if (current.getEndNode() instanceof AbstractEndNode) { + assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); + AbstractEndNode end = (AbstractEndNode) current.getEndNode(); + + // add the end node and see if the merge is ready for processing + MergeNode merge = end.merge(); + boolean endsVisited = true; + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { + if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) { + endsVisited = false; + break; + } + } + if (endsVisited) { + ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); + for (Block predecessor : successor.getPredecessors()) { + assert predecessor == current || states.containsKey(predecessor.getEndNode()); + StateT endState = predecessor == current ? state : states.remove(predecessor.getEndNode()); + mergedStates.add(endState); + } + state = closure.merge(successor, mergedStates); current = successor; continue; } else { - if (current.getEndNode() instanceof AbstractEndNode) { - assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); - AbstractEndNode end = (AbstractEndNode) current.getEndNode(); - - // add the end node and see if the merge is ready for processing - assert !states.containsKey(end); - states.put(end, state); - MergeNode merge = end.merge(); - boolean endsVisited = true; - for (AbstractEndNode forwardEnd : merge.forwardEnds()) { - if (!states.containsKey(forwardEnd)) { - endsVisited = false; - break; - } - } - if (endsVisited) { - blockQueue.addFirst(successor); - } - } else { - assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); - current = successor; - continue; - } + assert !states.containsKey(end); + states.put(end, state); } + } else { + assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); + current = successor; + continue; } } else { assert current.getSuccessors().size() > 1; - for (int i = 0; i < current.getSuccessors().size(); i++) { + for (int i = 1; i < current.getSuccessors().size(); i++) { Block successor = current.getSuccessors().get(i); blockQueue.addFirst(successor); - states.put(successor.getBeginNode(), i == 0 ? state : closure.cloneState(state)); + states.put(successor.getBeginNode(), closure.cloneState(state)); } + current = current.getSuccessors().get(0); + continue; } } @@ -164,20 +173,9 @@ return states; } else { current = blockQueue.removeFirst(); - if (current.getPredecessors().size() == 1) { - assert states.containsKey(current.getBeginNode()); - state = states.get(current.getBeginNode()); - } else { - assert current.getPredecessors().size() > 1; - MergeNode merge = (MergeNode) current.getBeginNode(); - ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); - for (Block predecessor : current.getPredecessors()) { - AbstractEndNode end = (AbstractEndNode) predecessor.getEndNode(); - mergedStates.add(states.get(end)); - } - state = closure.merge(current, mergedStates); - states.put(merge, state); - } + assert current.getPredecessorCount() == 1; + assert states.containsKey(current.getBeginNode()); + state = states.remove(current.getBeginNode()); } } } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Sat May 24 10:48:18 2014 -0700 @@ -33,8 +33,13 @@ public static class LoopInfo { - public final Map endStates = newNodeIdentityMap(4); - public final Map exitStates = newNodeIdentityMap(2); + public final Map endStates; + public final Map exitStates; + + public LoopInfo(int endCount, int exitCount) { + endStates = newNodeIdentityMap(endCount); + exitStates = newNodeIdentityMap(exitCount); + } } public abstract static class NodeIteratorClosure { @@ -64,7 +69,7 @@ public static LoopInfo processLoop(NodeIteratorClosure closure, LoopBeginNode loop, StateT initialState) { Map blockEndStates = apply(closure, loop, initialState, loop); - LoopInfo info = new LoopInfo<>(); + LoopInfo info = new LoopInfo<>(loop.loopEnds().count(), loop.loopExits().count()); for (LoopEndNode end : loop.loopEnds()) { if (blockEndStates.containsKey(end)) { info.endStates.put(end, blockEndStates.get(end)); @@ -119,11 +124,9 @@ nodeQueue.add(entry.getKey()); } } else { - assert !blockEndStates.containsKey(current); - blockEndStates.put(current, state); boolean endsVisited = true; for (AbstractEndNode forwardEnd : merge.forwardEnds()) { - if (!blockEndStates.containsKey(forwardEnd)) { + if (forwardEnd != current && !blockEndStates.containsKey(forwardEnd)) { endsVisited = false; break; } @@ -132,13 +135,16 @@ ArrayList states = new ArrayList<>(merge.forwardEndCount()); for (int i = 0; i < merge.forwardEndCount(); i++) { AbstractEndNode forwardEnd = merge.forwardEndAt(i); - assert blockEndStates.containsKey(forwardEnd); - StateT other = blockEndStates.get(forwardEnd); + assert forwardEnd == current || blockEndStates.containsKey(forwardEnd); + StateT other = forwardEnd == current ? state : blockEndStates.remove(forwardEnd); states.add(other); } state = closure.merge(merge, states); current = closure.continueIteration(state) ? merge : null; continue; + } else { + assert !blockEndStates.containsKey(current); + blockEndStates.put(current, state); } } } @@ -148,14 +154,15 @@ current = firstSuccessor; continue; } else { - while (successors.hasNext()) { + do { BeginNode successor = (BeginNode) successors.next(); StateT successorState = closure.afterSplit(successor, state); if (closure.continueIteration(successorState)) { blockEndStates.put(successor, successorState); nodeQueue.add(successor); } - } + } while (successors.hasNext()); + state = closure.afterSplit((BeginNode) firstSuccessor, state); current = closure.continueIteration(state) ? firstSuccessor : null; continue; @@ -169,7 +176,8 @@ return blockEndStates; } else { current = nodeQueue.removeFirst(); - state = blockEndStates.get(current); + assert blockEndStates.containsKey(current); + state = blockEndStates.remove(current); assert !(current instanceof MergeNode) && current instanceof BeginNode; } } while (true); diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Sat May 24 10:48:18 2014 -0700 @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2011, 2014, 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.replacements; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.nodes.java.ArrayLengthNode.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.util.*; + +/** + * VM-independent lowerings for standard Java nodes. VM-specific methods are abstract and must be + * implemented by VM-specific subclasses. + */ +public abstract class DefaultJavaLoweringProvider implements LoweringProvider { + + protected final MetaAccessProvider metaAccess; + protected final TargetDescription target; + + private BoxingSnippets.Templates boxingSnippets; + + public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, TargetDescription target) { + this.metaAccess = metaAccess; + this.target = target; + } + + public void initialize(Providers providers, SnippetReflectionProvider snippetReflection) { + boxingSnippets = new BoxingSnippets.Templates(providers, snippetReflection, target); + } + + @Override + public void lower(Node n, LoweringTool tool) { + if (n instanceof LoadFieldNode) { + lowerLoadFieldNode((LoadFieldNode) n, tool); + } else if (n instanceof StoreFieldNode) { + lowerStoreFieldNode((StoreFieldNode) n, tool); + } else if (n instanceof LoadIndexedNode) { + lowerLoadIndexedNode((LoadIndexedNode) n, tool); + } else if (n instanceof StoreIndexedNode) { + lowerStoreIndexedNode((StoreIndexedNode) n, tool); + } else if (n instanceof ArrayLengthNode) { + lowerArrayLengthNode((ArrayLengthNode) n, tool); + } else if (n instanceof LoadHubNode) { + lowerLoadHubNode((LoadHubNode) n); + } else if (n instanceof CompareAndSwapNode) { + lowerCompareAndSwapNode((CompareAndSwapNode) n); + } else if (n instanceof AtomicReadAndWriteNode) { + lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); + } else if (n instanceof UnsafeLoadNode) { + lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); + } else if (n instanceof UnsafeStoreNode) { + lowerUnsafeStoreNode((UnsafeStoreNode) n); + } else if (n instanceof JavaReadNode) { + lowerJavaReadNode((JavaReadNode) n); + } else if (n instanceof JavaWriteNode) { + lowerJavaWriteNode((JavaWriteNode) n); + } else if (n instanceof CommitAllocationNode) { + lowerCommitAllocationNode((CommitAllocationNode) n, tool); + } else if (n instanceof BoxNode) { + boxingSnippets.lower((BoxNode) n, tool); + } else if (n instanceof UnboxNode) { + boxingSnippets.lower((UnboxNode) n, tool); + } else { + throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + } + } + + protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { + assert loadField.getKind() != Kind.Illegal; + StructuredGraph graph = loadField.graph(); + ResolvedJavaField field = loadField.field(); + ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object(); + Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind(), true); + ConstantLocationNode location = createFieldLocation(graph, field, false); + assert location != null : "Field that is loaded must not be eliminated"; + + ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field), false)); + ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); + loadField.replaceAtUsages(readValue); + graph.replaceFixed(loadField, memoryRead); + + memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); + + if (loadField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(memoryRead, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(memoryRead, postMembar); + } + } + + protected void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { + StructuredGraph graph = storeField.graph(); + ResolvedJavaField field = storeField.field(); + ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object(); + ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value()); + ConstantLocationNode location = createFieldLocation(graph, field, false); + + if (location == null) { + /* Field has been eliminated, so no write necessary. */ + assert !storeField.isVolatile() : "missing memory barriers"; + graph.removeFixed(storeField); + return; + } + WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field()), false)); + memoryWrite.setStateAfter(storeField.stateAfter()); + graph.replaceFixedWithFixed(storeField, memoryWrite); + memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); + + if (storeField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(memoryWrite, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(memoryWrite, postMembar); + } + } + + protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { + StructuredGraph graph = loadIndexed.graph(); + Kind elementKind = loadIndexed.elementKind(); + LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false); + Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind, true); + + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); + + memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); + + loadIndexed.replaceAtUsages(readValue); + graph.replaceFixed(loadIndexed, memoryRead); + } + + protected void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { + StructuredGraph graph = storeIndexed.graph(); + GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); + Kind elementKind = storeIndexed.elementKind(); + LocationNode location = createArrayLocation(graph, elementKind, storeIndexed.index(), false); + + ValueNode value = storeIndexed.value(); + ValueNode array = storeIndexed.array(); + FixedWithNextNode checkCastNode = null; + if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) { + /* Array store check. */ + ResolvedJavaType arrayType = StampTool.typeOrNull(array); + if (arrayType != null && StampTool.isExactType(array)) { + ResolvedJavaType elementType = arrayType.getComponentType(); + if (!MetaUtil.isJavaLangObject(elementType)) { + checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + graph.addBeforeFixed(storeIndexed, checkCastNode); + value = checkCastNode; + } + } else { + ValueNode arrayClass = createReadHub(graph, array, boundsCheck); + ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed); + checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true)); + graph.addBeforeFixed(storeIndexed, checkCastNode); + value = checkCastNode; + } + } + + WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind()), false)); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + + if (checkCastNode instanceof Lowerable) { + /* Recursive lowering of the store check node. */ + ((Lowerable) checkCastNode).lower(tool); + } + } + + protected void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) { + StructuredGraph graph = arrayLengthNode.graph(); + ValueNode array = arrayLengthNode.array(); + ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph); + + ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE, false)); + arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); + graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); + } + + protected void lowerLoadHubNode(LoadHubNode loadHub) { + StructuredGraph graph = loadHub.graph(); + if (graph.getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { + return; + } + ValueNode hub = createReadHub(graph, loadHub.object(), loadHub.getGuard()); + graph.replaceFloating(loadHub, hub); + } + + protected void lowerCompareAndSwapNode(CompareAndSwapNode cas) { + StructuredGraph graph = cas.graph(); + Kind valueKind = cas.getValueKind(); + LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1); + + ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected()); + ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); + + LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas), false)); + atomicNode.setStateAfter(cas.stateAfter()); + graph.replaceFixedWithFixed(cas, atomicNode); + } + + protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { + StructuredGraph graph = n.graph(); + Kind valueKind = n.getValueKind(); + LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1); + + ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); + + LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n), false)); + memoryRead.setStateAfter(n.stateAfter()); + + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); + n.replaceAtUsages(readValue); + graph.replaceFixedWithFixed(n, memoryRead); + } + + protected void lowerUnsafeLoadNode(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) { + StructuredGraph graph = load.graph(); + if (load.getGuardingCondition() != null) { + ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); + ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); + graph.replaceFixedWithFixed(load, valueAnchorNode); + graph.addAfterFixed(valueAnchorNode, memoryRead); + } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { + assert load.getKind() != Kind.Illegal; + ReadNode memoryRead = createUnsafeRead(graph, load, null); + // An unsafe read must not float outside its block otherwise + // it may float above an explicit null check on its object. + memoryRead.setGuard(BeginNode.prevBegin(load)); + graph.replaceFixedWithFixed(load, memoryRead); + } + } + + protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + Kind readKind = load.accessKind(); + LocationNode location = createLocation(load); + Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); + load.replaceAtUsages(readValue); + return memoryRead; + } + + protected void lowerUnsafeStoreNode(UnsafeStoreNode store) { + StructuredGraph graph = store.graph(); + LocationNode location = createLocation(store); + ValueNode object = store.object(); + boolean compressible = store.value().getKind() == Kind.Object; + Kind valueKind = store.accessKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); + WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store), false)); + write.setStateAfter(store.stateAfter()); + graph.replaceFixedWithFixed(store, write); + } + + protected void lowerJavaReadNode(JavaReadNode read) { + StructuredGraph graph = read.graph(); + Kind valueKind = read.location().getValueKind(); + Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); + + ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false)); + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); + memoryRead.setGuard(read.getGuard()); + read.replaceAtUsages(readValue); + graph.replaceFixed(read, memoryRead); + } + + protected void lowerJavaWriteNode(JavaWriteNode write) { + StructuredGraph graph = write.graph(); + Kind valueKind = write.location().getValueKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); + + WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization())); + memoryWrite.setStateAfter(write.stateAfter()); + graph.replaceFixedWithFixed(write, memoryWrite); + memoryWrite.setGuard(write.getGuard()); + } + + protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) { + StructuredGraph graph = commit.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + List recursiveLowerings = new ArrayList<>(); + + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; + BitSet omittedValues = new BitSet(); + int valuePos = 0; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + AbstractNewObjectNode newObject; + if (virtual instanceof VirtualInstanceNode) { + newObject = graph.add(new NewInstanceNode(virtual.type(), true)); + } else { + newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); + } + recursiveLowerings.add(newObject); + graph.addBeforeFixed(commit, newObject); + allocations[objIndex] = newObject; + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos); + if (value instanceof VirtualObjectNode) { + value = allocations[commit.getVirtualObjects().indexOf(value)]; + } + if (value == null) { + omittedValues.set(valuePos); + } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + // Constant.illegal is always the defaultForKind, so it is skipped + Kind valueKind = value.getKind(); + Kind entryKind = virtual.entryKind(i); + + // Truffle requires some leniency in terms of what can be put where: + Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; + assert valueKind.getStackKind() == entryKind.getStackKind() || + (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); + ConstantLocationNode location = null; + BarrierType barrierType = null; + if (virtual instanceof VirtualInstanceNode) { + ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); + long offset = fieldOffset(field); + if (offset >= 0) { + location = ConstantLocationNode.create(initLocationIdentity(), accessKind, offset, graph); + barrierType = fieldInitializationBarrier(entryKind); + } + } else { + location = ConstantLocationNode.create(initLocationIdentity(), accessKind, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind), graph); + barrierType = arrayInitializationBarrier(entryKind); + } + if (location != null) { + WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false); + graph.addAfterFixed(newObject, graph.add(write)); + } + } + valuePos++; + + } + } + valuePos = 0; + + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + ValueNode newObject = allocations[objIndex]; + for (int i = 0; i < entryCount; i++) { + if (omittedValues.get(valuePos)) { + ValueNode value = commit.getValues().get(valuePos); + assert value instanceof VirtualObjectNode; + ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; + if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { + assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object; + LocationNode location; + BarrierType barrierType; + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; + location = createFieldLocation(graph, virtualInstance.field(i), true); + barrierType = BarrierType.IMPRECISE; + } else { + location = createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true); + barrierType = BarrierType.PRECISE; + } + if (location != null) { + WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType, false); + graph.addBeforeFixed(commit, graph.add(write)); + } + } + } + valuePos++; + } + } + + finishAllocatedObjects(tool, commit, allocations); + graph.removeFixed(commit); + + for (AbstractNewObjectNode recursiveLowering : recursiveLowerings) { + recursiveLowering.lower(tool); + } + } + } + + public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { + StructuredGraph graph = commit.graph(); + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); + allocations[objIndex] = anchor; + graph.addBeforeFixed(commit, anchor); + } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { + MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId)); + graph.addBeforeFixed(commit, enter); + enter.lower(tool); + } + } + for (Node usage : commit.usages().snapshot()) { + AllocatedObjectNode addObject = (AllocatedObjectNode) usage; + int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); + graph.replaceFloating(addObject, allocations[index]); + } + } + + protected BarrierType fieldLoadBarrierType(@SuppressWarnings("unused") ResolvedJavaField field) { + return BarrierType.NONE; + } + + protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) { + if (field.getKind() == Kind.Object) { + return BarrierType.IMPRECISE; + } + return BarrierType.NONE; + } + + protected BarrierType arrayStoreBarrierType(Kind elementKind) { + if (elementKind == Kind.Object) { + return BarrierType.PRECISE; + } + return BarrierType.NONE; + } + + protected BarrierType fieldInitializationBarrier(Kind entryKind) { + return entryKind == Kind.Object ? BarrierType.IMPRECISE : BarrierType.NONE; + } + + protected BarrierType arrayInitializationBarrier(Kind entryKind) { + return entryKind == Kind.Object ? BarrierType.PRECISE : BarrierType.NONE; + } + + protected BarrierType unsafeStoreBarrierType(UnsafeStoreNode store) { + return storeBarrierType(store.object(), store.value()); + } + + protected BarrierType compareAndSwapBarrierType(CompareAndSwapNode cas) { + return storeBarrierType(cas.object(), cas.expected()); + } + + protected BarrierType atomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) { + return storeBarrierType(n.object(), n.newValue()); + } + + protected BarrierType storeBarrierType(ValueNode object, ValueNode value) { + if (value.getKind() == Kind.Object) { + ResolvedJavaType type = StampTool.typeOrNull(object); + if (type != null && !type.isArray()) { + return BarrierType.IMPRECISE; + } else { + return BarrierType.PRECISE; + } + } + return BarrierType.NONE; + } + + protected abstract int fieldOffset(ResolvedJavaField field); + + protected abstract ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField field); + + protected abstract int arrayLengthOffset(); + + protected abstract int arrayBaseOffset(Kind elementKind); + + public int arrayScalingFactor(Kind elementKind) { + return target.getSizeInBytes(elementKind); + } + + protected abstract LocationIdentity initLocationIdentity(); + + protected Stamp loadStamp(Stamp stamp, Kind kind, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return StampTool.narrowingConversion(stamp, 8); + case Char: + case Short: + return StampTool.narrowingConversion(stamp, 16); + } + return stamp; + } + + public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitLoadConvert(graph, kind, value, true); + + } + + protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Byte: + case Short: + return graph.unique(new SignExtendNode(value, 32)); + case Boolean: + case Char: + return graph.unique(new ZeroExtendNode(value, 32)); + } + return value; + } + + public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitStoreConvert(graph, kind, value, true); + } + + protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return graph.unique(new NarrowNode(value, 8)); + case Char: + case Short: + return graph.unique(new NarrowNode(value, 16)); + } + return value; + } + + protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard); + + protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor); + + protected ConstantLocationNode createFieldLocation(StructuredGraph graph, ResolvedJavaField field, boolean initialization) { + int offset = fieldOffset(field); + if (offset >= 0) { + LocationIdentity loc = initialization ? initLocationIdentity() : field; + return ConstantLocationNode.create(loc, field.getKind(), offset, graph); + } else { + return null; + } + } + + protected LocationNode createLocation(UnsafeAccessNode access) { + return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); + } + + protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { + ValueNode offset = offsetNode; + if (offset.isConstant()) { + long offsetValue = offset.asConstant().asLong(); + return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph()); + } + + long displacement = 0; + int indexScaling = 1; + boolean signExtend = false; + if (offset instanceof SignExtendNode) { + SignExtendNode extend = (SignExtendNode) offset; + if (extend.getResultBits() == 64) { + signExtend = true; + offset = extend.getInput(); + } + } + if (offset instanceof IntegerAddNode) { + IntegerAddNode integerAddNode = (IntegerAddNode) offset; + if (integerAddNode.y() instanceof ConstantNode) { + displacement = integerAddNode.y().asConstant().asLong(); + offset = integerAddNode.x(); + } + } + + if (offset instanceof LeftShiftNode) { + LeftShiftNode leftShiftNode = (LeftShiftNode) offset; + if (leftShiftNode.y() instanceof ConstantNode) { + long shift = leftShiftNode.y().asConstant().asLong(); + if (shift >= 1 && shift <= 3) { + if (shift == 1) { + indexScaling = 2; + } else if (shift == 2) { + indexScaling = 4; + } else { + indexScaling = 8; + } + offset = leftShiftNode.x(); + } + } + } + if (signExtend) { + // If we were using sign extended values before restore the sign extension. + offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64)); + } + return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); + } + + public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { + LocationIdentity loc = initialization ? initLocationIdentity() : NamedLocationIdentity.getArrayLocation(elementKind); + return IndexedLocationNode.create(loc, elementKind, arrayBaseOffset(elementKind), index, graph, arrayScalingFactor(elementKind)); + } + + protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { + StructuredGraph graph = n.graph(); + ValueNode array = n.array(); + ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); + if (arrayLength == null) { + Stamp stamp = StampFactory.positiveInt(); + ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE, false)); + graph.addBeforeFixed(n, readArrayLength); + readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); + arrayLength = readArrayLength; + } + + if (arrayLength.isConstant() && n.index().isConstant()) { + int l = arrayLength.asConstant().asInt(); + int i = n.index().asConstant().asInt(); + if (i >= 0 && i < l) { + // unneeded range check + return null; + } + } + + return tool.createGuard(n, graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + } + + protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { + if (StampTool.isObjectNonNull(object)) { + return null; + } + return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + } + + @Override + public ValueNode reconstructArrayIndex(LocationNode location) { + Kind elementKind = location.getValueKind(); + assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); + + long base; + ValueNode index; + int scale = arrayScalingFactor(elementKind); + + if (location instanceof ConstantLocationNode) { + base = ((ConstantLocationNode) location).getDisplacement(); + index = null; + } else if (location instanceof IndexedLocationNode) { + IndexedLocationNode indexedLocation = (IndexedLocationNode) location; + assert indexedLocation.getIndexScaling() == scale; + base = indexedLocation.getDisplacement(); + index = indexedLocation.getIndex(); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + + base -= arrayBaseOffset(elementKind); + assert base >= 0 && base % scale == 0; + + base /= scale; + assert NumUtil.isInt(base); + + StructuredGraph graph = location.graph(); + if (index == null) { + return ConstantNode.forInt((int) base, graph); + } else { + if (base == 0) { + return index; + } else { + return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); + } + } + } +} diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Sat May 24 10:48:18 2014 -0700 @@ -57,7 +57,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (object.isConstant() && !object.isNullConstant() && offset.isConstant()) { + if (object.isConstant() && !object.isNullConstant() && offset.isConstant() && condition.isConstant() && condition.asConstant().asInt() == 1) { Constant constant = tool.getConstantReflection().readUnsafeConstant(accessKind, object.asConstant(), offset.asConstant().asLong()); return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()); } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Sat May 24 10:48:18 2014 -0700 @@ -25,6 +25,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; @@ -32,7 +33,7 @@ public class EarlyReadEliminationPhase extends EffectsPhase { public EarlyReadEliminationPhase(CanonicalizerPhase canonicalizer) { - super(1, canonicalizer); + super(1, canonicalizer, true); } @Override @@ -43,7 +44,8 @@ } @Override - protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule) { - return new ReadEliminationClosure(schedule); + protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) { + assert schedule == null; + return new ReadEliminationClosure(cfg); } } diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Sat May 24 10:48:18 2014 -0700 @@ -42,6 +42,7 @@ public abstract class EffectsClosure> extends EffectsPhase.Closure { + private final ControlFlowGraph cfg; private final SchedulePhase schedule; protected final NodeMap aliases; @@ -51,11 +52,12 @@ private boolean changed; - public EffectsClosure(SchedulePhase schedule) { + public EffectsClosure(SchedulePhase schedule, ControlFlowGraph cfg) { this.schedule = schedule; - this.aliases = schedule.getCFG().graph.createNodeMap(); - this.blockEffects = new BlockMap<>(schedule.getCFG()); - for (Block block : schedule.getCFG().getBlocks()) { + this.cfg = cfg; + this.aliases = cfg.graph.createNodeMap(); + this.blockEffects = new BlockMap<>(cfg); + for (Block block : cfg.getBlocks()) { blockEffects.put(block, new GraphEffectList()); } } @@ -67,7 +69,7 @@ @Override public void applyEffects() { - final StructuredGraph graph = schedule.getCFG().graph; + final StructuredGraph graph = cfg.graph; final ArrayList obsoleteNodes = new ArrayList<>(0); BlockIteratorClosure closure = new BlockIteratorClosure() { @@ -114,7 +116,7 @@ return info.exitStates; } }; - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); } @@ -124,7 +126,8 @@ GraphEffectList effects = blockEffects.get(block); FixedWithNextNode lastFixedNode = null; - for (Node node : schedule.getBlockToNodesMap().get(block)) { + Iterable nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes(); + for (Node node : nodes) { aliases.set(node, null); if (node instanceof LoopExitNode) { LoopExitNode loopExit = (LoopExitNode) node; diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Sat May 24 10:48:18 2014 -0700 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.util.*; @@ -49,10 +50,16 @@ private final int maxIterations; protected final CanonicalizerPhase canonicalizer; + private final boolean unscheduled; - public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { + protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { + this(maxIterations, canonicalizer, false); + } + + protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer, boolean unscheduled) { this.maxIterations = maxIterations; this.canonicalizer = canonicalizer; + this.unscheduled = unscheduled; } @Override @@ -64,10 +71,19 @@ boolean changed = false; for (int iteration = 0; iteration < maxIterations; iteration++) { try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph, false); - Closure closure = createEffectsClosure(context, schedule); - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + SchedulePhase schedule; + ControlFlowGraph cfg; + if (unscheduled) { + schedule = null; + cfg = ControlFlowGraph.compute(graph, true, true, false, false); + } else { + schedule = new SchedulePhase(); + schedule.apply(graph, false); + cfg = schedule.getCFG(); + } + + Closure closure = createEffectsClosure(context, schedule, cfg); + ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); if (!closure.hasChanged()) { break; @@ -106,5 +122,5 @@ } } - protected abstract Closure createEffectsClosure(PhaseContextT context, SchedulePhase schedule); + protected abstract Closure createEffectsClosure(PhaseContextT context, SchedulePhase schedule, ControlFlowGraph cfg); } diff -r 09ac9ac9c4fc -r 079229f002a3 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 Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat May 24 10:48:18 2014 -0700 @@ -79,7 +79,7 @@ } public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) { - super(schedule); + super(schedule, schedule.getCFG()); this.usages = schedule.getCFG().graph.createNodeBitMap(); this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, assumptions, this); } diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Sat May 24 10:48:18 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; @@ -84,7 +85,8 @@ } @Override - protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule) { + protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) { + assert schedule != null; if (readElimination) { return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions()); } else { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Sat May 24 10:48:18 2014 -0700 @@ -132,13 +132,7 @@ } public void killReadCache(LocationIdentity identity) { - Iterator, ValueNode>> iter = readCache.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry, ValueNode> entry = iter.next(); - if (entry.getKey().conflicts(identity)) { - iter.remove(); - } - } + readCache.entrySet().removeIf(entry -> entry.getKey().conflicts(identity)); } public Map, ValueNode> getReadCache() { diff -r 09ac9ac9c4fc -r 079229f002a3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Sat May 24 10:34:43 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Sat May 24 10:48:18 2014 -0700 @@ -34,15 +34,14 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry; public class ReadEliminationClosure extends EffectsClosure { - public ReadEliminationClosure(SchedulePhase schedule) { - super(schedule); + public ReadEliminationClosure(ControlFlowGraph cfg) { + super(null, cfg); } @Override @@ -53,104 +52,104 @@ @Override protected boolean processNode(Node node, ReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) { boolean deleted = false; - if (node instanceof LoadFieldNode) { - LoadFieldNode load = (LoadFieldNode) node; - if (!load.isVolatile()) { - ValueNode object = GraphUtil.unproxify(load.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, load.field()); + if (node instanceof AccessFieldNode) { + AccessFieldNode access = (AccessFieldNode) node; + if (access.isVolatile()) { + processIdentity(state, ANY_LOCATION); + } else { + ValueNode object = GraphUtil.unproxify(access.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, access.field()); ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - effects.replaceAtUsages(load, cachedValue); - addScalarAlias(load, cachedValue); - deleted = true; + if (node instanceof LoadFieldNode) { + if (cachedValue != null) { + effects.replaceAtUsages(access, cachedValue); + addScalarAlias(access, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, access); + } } else { - state.addCacheEntry(identifier, load); + assert node instanceof StoreFieldNode; + StoreFieldNode store = (StoreFieldNode) node; + ValueNode value = getScalarAlias(store.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(store); + deleted = true; + } + state.killReadCache(store.field()); + state.addCacheEntry(identifier, value); + } + } + } else if (node instanceof FixedAccessNode) { + if (node instanceof ReadNode) { + ReadNode read = (ReadNode) node; + if (read.location() instanceof ConstantLocationNode) { + ValueNode object = GraphUtil.unproxify(read.object()); + ReadCacheEntry identifier = new ReadCacheEntry(object, read.location()); + ValueNode cachedValue = state.getCacheEntry(identifier); + if (cachedValue != null) { + if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) { + effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read); + } + effects.replaceAtUsages(read, cachedValue); + addScalarAlias(read, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, read); + } + } + } else if (node instanceof WriteNode) { + WriteNode write = (WriteNode) node; + if (write.location() instanceof ConstantLocationNode) { + ValueNode object = GraphUtil.unproxify(write.object()); + ReadCacheEntry identifier = new ReadCacheEntry(object, write.location()); + ValueNode cachedValue = state.getCacheEntry(identifier); + + ValueNode value = getScalarAlias(write.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(write); + deleted = true; + } + processIdentity(state, write.location().getLocationIdentity()); + state.addCacheEntry(identifier, value); + } else { + processIdentity(state, write.location().getLocationIdentity()); + } + } + } else if (node instanceof UnsafeAccessNode) { + if (node instanceof UnsafeLoadNode) { + UnsafeLoadNode load = (UnsafeLoadNode) node; + if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { + ValueNode object = GraphUtil.unproxify(load.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity()); + ValueNode cachedValue = state.getCacheEntry(identifier); + if (cachedValue != null) { + effects.replaceAtUsages(load, cachedValue); + addScalarAlias(load, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, load); + } } } else { - processIdentity(state, ANY_LOCATION); - } - } else if (node instanceof StoreFieldNode) { - StoreFieldNode store = (StoreFieldNode) node; - if (!store.isVolatile()) { - ValueNode object = GraphUtil.unproxify(store.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, store.field()); - ValueNode cachedValue = state.getCacheEntry(identifier); + assert node instanceof UnsafeStoreNode; + UnsafeStoreNode write = (UnsafeStoreNode) node; + if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { + ValueNode object = GraphUtil.unproxify(write.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); + ValueNode cachedValue = state.getCacheEntry(identifier); - ValueNode value = getScalarAlias(store.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); - deleted = true; - } - state.killReadCache(store.field()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, ANY_LOCATION); - } - } else if (node instanceof ReadNode) { - ReadNode read = (ReadNode) node; - if (read.location() instanceof ConstantLocationNode) { - ValueNode object = GraphUtil.unproxify(read.object()); - ReadCacheEntry identifier = new ReadCacheEntry(object, read.location()); - ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) { - effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read); + ValueNode value = getScalarAlias(write.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(write); + deleted = true; } - effects.replaceAtUsages(read, cachedValue); - addScalarAlias(read, cachedValue); - deleted = true; + processIdentity(state, write.getLocationIdentity()); + state.addCacheEntry(identifier, value); } else { - state.addCacheEntry(identifier, read); + processIdentity(state, write.getLocationIdentity()); } } - } else if (node instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) node; - if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { - ValueNode object = GraphUtil.unproxify(load.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity()); - ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - effects.replaceAtUsages(load, cachedValue); - addScalarAlias(load, cachedValue); - deleted = true; - } else { - state.addCacheEntry(identifier, load); - } - } - } else if (node instanceof WriteNode) { - WriteNode write = (WriteNode) node; - if (write.location() instanceof ConstantLocationNode) { - ValueNode object = GraphUtil.unproxify(write.object()); - ReadCacheEntry identifier = new ReadCacheEntry(object, write.location()); - ValueNode cachedValue = state.getCacheEntry(identifier); - - ValueNode value = getScalarAlias(write.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); - deleted = true; - } - processIdentity(state, write.location().getLocationIdentity()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, write.location().getLocationIdentity()); - } - } else if (node instanceof UnsafeStoreNode) { - UnsafeStoreNode write = (UnsafeStoreNode) node; - if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { - ValueNode object = GraphUtil.unproxify(write.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); - ValueNode cachedValue = state.getCacheEntry(identifier); - - ValueNode value = getScalarAlias(write.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); - deleted = true; - } - processIdentity(state, write.getLocationIdentity()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, write.getLocationIdentity()); - } } else if (node instanceof MemoryCheckpoint.Single) { LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); processIdentity(state, identity); diff -r 09ac9ac9c4fc -r 079229f002a3 mx/mx_graal.py --- a/mx/mx_graal.py Sat May 24 10:34:43 2014 -0700 +++ b/mx/mx_graal.py Sat May 24 10:48:18 2014 -0700 @@ -46,8 +46,8 @@ """ The VMs that can be built and run along with an optional description. Only VMs with a description are listed in the dialogue for setting the default VM (see _get_vm()). """ _vmChoices = { - 'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.', - 'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', + 'graal' : 'Normal compilation is performed with a tiered system (C1 + Graal), Truffle compilation is performed with Graal.', + 'server' : 'Normal compilation is performed with a tiered system (C1 + C2), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', 'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal 'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted 'client-nograal' : None, # all compilation with client compiler, Graal omitted @@ -154,7 +154,7 @@ def handleRemoveReadonly(func, path, exc): excvalue = exc[1] if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 func(path) else: raise @@ -212,7 +212,7 @@ def _genFileName(archivtype, middle): idPrefix = infos['revision'] + '_' idSuffix = '.tar.gz' - return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) + return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) def _genFileArchPlatformName(archivtype, middle): return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle) @@ -484,8 +484,27 @@ if exists(toDelete): os.unlink(toDelete) +def _update_HotSpotOptions_inline_hpp(graalJar): + p = mx.project('com.oracle.graal.hotspot') + mainClass = 'com.oracle.graal.hotspot.HotSpotOptionsLoader' + assert exists(join(p.source_dirs()[0], mainClass.replace('.', os.sep) + '.java')) + hsSrcGenDir = join(p.source_gen_dir(), 'hotspot') + if not exists(hsSrcGenDir): + os.makedirs(hsSrcGenDir) + tmp = StringIO.StringIO() + retcode = mx.run_java(['-cp', graalJar, mainClass], out=tmp.write, nonZeroIsFatal=False) + if retcode != 0: + # Suppress the error if it's because the utility class isn't compiled yet + with zipfile.ZipFile(graalJar, 'r') as zf: + mainClassFile = mainClass.replace('.', '/') + '.class' + if mainClassFile not in zf.namelist(): + return + mx.abort(retcode) + mx.update_file(join(hsSrcGenDir, 'HotSpotOptions.inline.hpp'), tmp.getvalue()) + def _installGraalJarInJdks(graalDist): graalJar = graalDist.path + _update_HotSpotOptions_inline_hpp(graalJar) jdks = _jdksDir() if exists(jdks): @@ -690,7 +709,7 @@ mustBuild = False timestamp = os.path.getmtime(timestampFile) sources = [] - for d in ['src', 'make', 'graal/com.oracle.graal.hotspot/src_gen/hotspot']: + for d in ['src', 'make', join('graal', 'com.oracle.graal.hotspot', 'src_gen', 'hotspot')]: for root, dirnames, files in os.walk(join(_graal_home, d)): # ignore /src/share/tools if root == join(_graal_home, 'src', 'share'): diff -r 09ac9ac9c4fc -r 079229f002a3 mxtool/mx.py --- a/mxtool/mx.py Sat May 24 10:34:43 2014 -0700 +++ b/mxtool/mx.py Sat May 24 10:48:18 2014 -0700 @@ -1514,14 +1514,19 @@ stderr = err if not callable(err) else subprocess.PIPE p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env) sub = _addSubprocess(p, args) + joiners = [] if callable(out): t = Thread(target=redirect, args=(p.stdout, out)) # Don't make the reader thread a daemon otherwise output can be droppped t.start() + joiners.append(t) if callable(err): t = Thread(target=redirect, args=(p.stderr, err)) # Don't make the reader thread a daemon otherwise output can be droppped t.start() + joiners.append(t) + for t in joiners: + t.join() if timeout is None or timeout == 0: retcode = waitOn(p) else: @@ -1673,6 +1678,7 @@ self.javac = exe_suffix(join(self.jdk, 'bin', 'javac')) self.javap = exe_suffix(join(self.jdk, 'bin', 'javap')) self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc')) + self.pack200 = exe_suffix(join(self.jdk, 'bin', 'pack200')) self.toolsjar = join(self.jdk, 'lib', 'tools.jar') self._bootclasspath = None self._extdirs = None @@ -1847,7 +1853,7 @@ def is_alive(p): if isinstance(p, subprocess.Popen): - return p.poll() is not None + return p.poll() is None assert isinstance(p, multiprocessing.Process), p return p.is_alive() @@ -3398,13 +3404,12 @@ for ap in p.annotation_processors(): for dep in dependency(ap).all_deps([], True): if dep.isLibrary(): - if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'): - # Relative paths for "lib" class path entries have various semantics depending on the Eclipse - # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's - # safest to simply use absolute paths. - path = _make_absolute(dep.get_path(resolve=True), p.suite.dir) - out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) - files.append(path) + # Relative paths for "lib" class path entries have various semantics depending on the Eclipse + # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's + # safest to simply use absolute paths. + path = _make_absolute(dep.get_path(resolve=True), p.suite.dir) + out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) + files.append(path) elif dep.isProject(): out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) out.close('factorypath') diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Sat May 24 10:48:18 2014 -0700 @@ -89,12 +89,12 @@ VMStructs::initHotSpotVMConfig(JNIHandles::resolve(config)); C2V_END -C2V_VMENTRY(jbyteArray, initializeBytecode, (JNIEnv *, jobject, jlong metaspace_method)) +C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jlong metaspace_method)) methodHandle method = asMethod(metaspace_method); ResourceMark rm; int code_size = method->code_size(); - jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); + typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL); guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten"); // iterate over all bytecodes and replace non-Java bytecodes @@ -106,9 +106,9 @@ int len = s.instruction_size(); // Restore original byte code. - reconstituted_code[bci] = (jbyte) (s.is_wide()? Bytecodes::_wide : code); + reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code)); if (len > 1) { - memcpy(&reconstituted_code[bci+1], s.bcp()+1, len-1); + memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1); } if (len > 1) { @@ -124,41 +124,39 @@ case Bytecodes::_invokestatic: case Bytecodes::_invokeinterface: case Bytecodes::_invokehandle: { - int cp_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); - Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); + int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1)); + Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index); break; } case Bytecodes::_invokedynamic: - int cp_index = Bytes::get_native_u4((address) &reconstituted_code[bci + 1]); - Bytes::put_Java_u4((address) &reconstituted_code[bci + 1], (u4) cp_index); + int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1)); + Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index); break; } // Not all ldc byte code are rewritten. switch (raw_code) { case Bytecodes::_fast_aldc: { - int cpc_index = reconstituted_code[bci + 1] & 0xff; + int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff; int cp_index = method->constants()->object_to_cp_index(cpc_index); assert(cp_index < method->constants()->length(), "sanity check"); - reconstituted_code[bci + 1] = (jbyte) cp_index; + reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index); break; } case Bytecodes::_fast_aldc_w: { - int cpc_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]); + int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1)); int cp_index = method->constants()->object_to_cp_index(cpc_index); assert(cp_index < method->constants()->length(), "sanity check"); - Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index); + Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index); break; } } } } - typeArrayOop result_array = oopFactory::new_byteArray(code_size, CHECK_NULL); - memcpy(result_array->byte_at_addr(0), reconstituted_code, code_size); - return (jbyteArray) JNIHandles::make_local(result_array); + return (jbyteArray) JNIHandles::make_local(reconstituted_code); C2V_END C2V_VMENTRY(jint, exceptionTableLength, (JNIEnv *, jobject, jlong metaspace_method)) @@ -1004,7 +1002,7 @@ #define METASPACE_SYMBOL "J" JNINativeMethod CompilerToVM_methods[] = { - {CC"initializeBytecode", CC"("METASPACE_METHOD")[B", FN_PTR(initializeBytecode)}, + {CC"getBytecode", CC"("METASPACE_METHOD")[B", FN_PTR(getBytecode)}, {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)}, {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)}, {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.cpp Sat May 24 10:48:18 2014 -0700 @@ -651,17 +651,166 @@ GraalRuntime::initialize_natives(env, c2vmClass); JVM_END -// private static String[] HotSpotOptions.getVMOptions(boolean[] timeCompilations) -JVM_ENTRY(jobject, JVM_GetGraalOptions(JNIEnv *env, jclass c, jobject timeCompilations)) +// private static boolean HotSpotOptions.parseVMOptions() +JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c)) HandleMark hm; + KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c))); + return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); +JVM_END + +bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { + ResourceMark rm(THREAD); + + // Process option overrides from graal.options first + parse_graal_options_file(hotSpotOptionsClass, CHECK_false); + + // Now process options on the command line int numOptions = Arguments::num_graal_args(); - objArrayOop options = oopFactory::new_objArray(SystemDictionary::String_klass(), - numOptions, CHECK_NULL); - objArrayHandle optionsHandle(THREAD, options); for (int i = 0; i < numOptions; i++) { - Handle option = java_lang_String::create_from_str(Arguments::graal_args_array()[i], CHECK_NULL); - optionsHandle->obj_at_put(i, option()); + char* arg = Arguments::graal_args_array()[i]; + parse_argument(hotSpotOptionsClass, arg, CHECK_false); + } + return CITime || CITimeEach; +} + +void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { + char first = arg[0]; + char* name; + size_t name_len; + Handle name_handle; + bool valid = true; + if (first == '+' || first == '-') { + name = arg + 1; + name_len = strlen(name); + name_handle = java_lang_String::create_from_str(name, CHECK); + valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, arg, CHECK); + } else { + char* sep = strchr(arg, '='); + if (sep != NULL) { + name = arg; + name_len = sep - name; + // Temporarily replace '=' with NULL to create the Java string for the option name + *sep = '\0'; + name_handle = java_lang_String::create_from_str(arg, THREAD); + *sep = '='; + if (HAS_PENDING_EXCEPTION) { + return; + } + valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, sep + 1, CHECK); + } else { + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=' format", arg, arg); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + } + } + + if (!valid) { + VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); } - ((typeArrayOop) JNIHandles::resolve(timeCompilations))->bool_at_put(0, CITime || CITimeEach); - return JNIHandles::make_local(THREAD, optionsHandle()); -JVM_END +} + +void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { + const char* home = Arguments::get_java_home(); + int path_len = strlen(home) + strlen("/lib/graal.options") + 1; + char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); + char sep = os::file_separator()[0]; + sprintf(path, "%s%clib%cgraal.options", home, sep, sep); + + struct stat st; + if (os::stat(path, &st) == 0) { + int file_handle = os::open(path, 0, 0); + if (file_handle != -1) { + char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size); + int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); + if (num_read == -1) { + warning("Error reading file %s due to %s", path, strerror(errno)); + } else if (num_read != st.st_size) { + warning("Only read %d of %d bytes from %s", num_read, st.st_size, path); + } + os::close(file_handle); + if (num_read == st.st_size) { + char* line = buffer; + int lineNo = 1; + while (line - buffer < num_read) { + char* nl = strchr(line, '\n'); + if (nl != NULL) { + *nl = '\0'; + } + parse_argument(hotSpotOptionsClass, line, THREAD); + if (HAS_PENDING_EXCEPTION) { + warning("Error in %s:%d", path, lineNo); + return; + } + if (nl != NULL) { + line = nl + 1; + lineNo++; + } else { + // File without newline at the end + break; + } + } + } + } else { + warning("Error opening file %s due to %s", path, strerror(errno)); + } + } +} + +jlong GraalRuntime::parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS) { + union { + jint i; + jlong l; + double d; + } uu; + uu.l = 0L; + char dummy; + switch (spec) { + case 'd': + case 'f': { + if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) { + return uu.l; + } + break; + } + case 'i': { + if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) { + return uu.l; + } + break; + } + default: + ShouldNotReachHere(); + } + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %s: %s", (spec == 'i' ? "numeric" : "float/double"), java_lang_String::as_utf8_string(name()), value); + THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); +} + +Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { + TempNewSymbol name = SymbolTable::new_symbol(declaringClass, THREAD); + Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); + + // The class has been loaded so the field and signature should already be in the symbol + // table. If they're not there, the field doesn't exist. + TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); + TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig)); + if (fieldname == NULL || signame == NULL) { + THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); + } + // Make sure class is initialized before handing id's out to fields + klass->initialize(CHECK_NH); + + fieldDescriptor fd; + if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { + THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); + } + + Handle ret = klass->java_mirror()->obj_field(fd.offset()); + return ret; +} + +#include "HotSpotOptions.inline.hpp" diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.hpp Sat May 24 10:48:18 2014 -0700 @@ -31,12 +31,55 @@ class GraalRuntime: public CHeapObj { private: - static address _external_deopt_i2c_entry; + static address _external_deopt_i2c_entry; + + /** + * Reads the OptionValue object from a specified static field. + * + * @throws LinkageError if the field could not be resolved + */ + static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS); + + /** + * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles). + * + * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption()) + * @param name name option option + * @param value string value to parse + * @throws InternalError if value could not be parsed according to spec + */ + static jlong parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS); + + /** + * Loads default option value overrides from a /lib/graal.options if it exists. Each + * line in this file must have the format of a Graal command line option without the + * leading "-G:" prefix. These option values are set prior to processing of any Graal + * options present on the command line. + */ + static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS); + + /** + * Parses a given argument and sets the denoted Graal option. + * + * @throws InternalError if there was a problem parsing or setting the option + */ + static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS); + + /** + * Searches for a Graal option denoted by a given name and sets it value. + * + * @returns true if the option was found + * @throws InternalError if there was a problem setting the option's value + */ + static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS); public: static void initialize_natives(JNIEnv *env, jclass c2vmClass); static BufferBlob* initialize_buffer_blob(); + + static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); + static BasicType kindToBasicType(jchar ch); static address create_external_deopt_i2c(); static address get_external_deopt_i2c_entry() {return _external_deopt_i2c_entry;} diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Sat May 24 10:48:18 2014 -0700 @@ -94,48 +94,20 @@ return Handle(JNIHandles::resolve_non_null(_VMToCompiler_instance)); } -void VMToCompiler::initOptions() { +void VMToCompiler::setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { + assert(!option.is_null(), "npe"); Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); - KlassHandle optionsKlass = loadClass(name); - optionsKlass->initialize(THREAD); - check_pending_exception("Error while calling initOptions"); -} - -jboolean VMToCompiler::setOption(Handle option) { - assert(!option.is_null(), ""); - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD); - KlassHandle optionsKlass = loadClass(name); - JavaValue result(T_BOOLEAN); - JavaCalls::call_static(&result, optionsKlass, setOption, sig, option, THREAD); - check_pending_exception("Error while calling setOption"); - return result.get_jboolean(); -} - -void VMToCompiler::finalizeOptions(jboolean ciTime) { - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); - TempNewSymbol finalizeOptions = SymbolTable::new_symbol("finalizeOptions", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD); - KlassHandle optionsKlass = loadClass(name); + TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD); JavaValue result(T_VOID); JavaCallArguments args; - args.push_int(ciTime); - JavaCalls::call_static(&result, optionsKlass, finalizeOptions, vmSymbols::bool_void_signature(), &args, THREAD); - check_pending_exception("Error while calling finalizeOptions"); -} - -void VMToCompiler::startRuntime() { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - TempNewSymbol startRuntime = SymbolTable::new_symbol("startRuntime", THREAD); - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), startRuntime, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling startRuntime"); + args.push_oop(name()); + args.push_oop(option()); + args.push_int(spec); + args.push_oop(stringValue()); + args.push_long(primitiveValue); + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD); + check_pending_exception("Error while calling setOption"); } #ifdef COMPILERGRAAL diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Sat May 24 10:48:18 2014 -0700 @@ -55,17 +55,8 @@ return _HotSpotGraalRuntime_instance; } - // public static boolean HotSpotOptions.(); - static void initOptions(); - - // public static boolean HotSpotOptions.setOption(String option); - static jboolean setOption(Handle option); - - // public static void HotSpotOptions.finalizeOptions(boolean ciTime); - static void finalizeOptions(jboolean ciTime); - - // public abstract void startRuntime(); - static void startRuntime(); + // public static void HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue); + static void setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); #ifdef COMPILERGRAAL // public abstract void startCompiler(boolean bootstrapEnabled); diff -r 09ac9ac9c4fc -r 079229f002a3 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Sat May 24 10:34:43 2014 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Sat May 24 10:48:18 2014 -0700 @@ -124,10 +124,10 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL - void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); - jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); - jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); - jobject JNICALL JVM_GetGraalOptions(JNIEnv *env, jclass hotspotOptionsClass, jobject timeCompilations); + void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); + jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); + jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); + jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); #endif } @@ -140,10 +140,10 @@ { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL - { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, - { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_getVMOptions", NULL, FN_PTR(JVM_GetGraalOptions) }, + { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, + { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, #endif };