# HG changeset patch # User Thomas Wuerthinger # Date 1382657994 -7200 # Node ID faded4a83d6369d24a553d61932c942c19f839d7 # Parent cf6cfa79593dcb705eab6d8414a8e0c70c852c7f# Parent 04e51b3026c07f4bf023454074a55565752bdae8 Merge. diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Fri Oct 25 01:39:54 2013 +0200 @@ -42,6 +42,16 @@ InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult); /** + * Sets the given compilation result as the default implementation of the given method. + * + * @param method a method to which the executable code is begin added + * @param compResult the compilation result to be added + * @return a reference to the compiled and ready-to-run code or null if the code installation + * failed + */ + InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult); + + /** * Returns a disassembly of some compiled code. * * @param compResult some compiled code diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Oct 25 01:39:54 2013 +0200 @@ -326,6 +326,8 @@ private int customStackAreaOffset = -1; private int registerRestoreEpilogueOffset = -1; + private final String name; + /** * The buffer containing the emitted machine code. */ @@ -347,6 +349,14 @@ */ private long[] leafGraphIds; + public CompilationResult() { + this(null); + } + + public CompilationResult(String name) { + this.name = name; + } + public void setAssumptions(Assumptions assumptions) { this.assumptions = assumptions; } @@ -620,4 +630,8 @@ } return unmodifiableList(marks); } + + public String getName() { + return name; + } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Fri Oct 25 01:39:54 2013 +0200 @@ -360,18 +360,18 @@ assert var instanceof Variable; assert val instanceof Constant; Constant constant = (Constant) val; - return ("[" + emitRegister((Variable) var, false) + " + " + constant.asBoxedValue() + "]"); + return ("[" + ((space == PTXStateSpace.Parameter) ? emitParameter((Variable) var) : emitRegister((Variable) var, false)) + " + " + constant.asBoxedValue() + "]"); } @Override public String emitRegister(Variable var, boolean comma) { - /* - * if (space == Parameter) { return ("param" + var.index); } else { return ("%r" + - * var.index); } - */ return ("%r" + var.index); } + public String emitParameter(Variable v) { + return ("param" + v.index); + } + public String emit(boolean isLoad) { if (isLoad) { return (space.getStateName() + "." + typeForKind(valueKind) + " " + emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";"); @@ -671,7 +671,7 @@ } public String emitParameter(Variable v) { - return (" %r" + v.index); + return (" param" + v.index); } public void emit(PTXAssembler asm) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.test; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import static org.junit.Assert.*; @@ -144,7 +145,9 @@ new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } } } @@ -176,7 +179,9 @@ new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test; import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; @@ -116,12 +117,32 @@ assertEquals(expected, graph, false); } + protected int countUnusedConstants(StructuredGraph graph) { + int total = 0; + for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) { + if (!ConstantNodeRecordsUsages) { + if (node.gatherUsages().isEmpty()) { + total++; + } + } else { + if (node.usages().isEmpty()) { + total++; + } + } + } + return total; + } + + protected int getNodeCountExcludingUnusedConstants(StructuredGraph graph) { + return graph.getNodeCount() - countUnusedConstants(graph); + } + protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) { String expectedString = getCanonicalGraphString(expected, excludeVirtual); String actualString = getCanonicalGraphString(graph, excludeVirtual); String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString; - if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) { + if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { Debug.dump(expected, "Node count not matching - expected"); Debug.dump(graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); @@ -161,16 +182,18 @@ } result.append("\n"); for (Node node : schedule.getBlockToNodesMap().get(block)) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { - int id; - if (canonicalId.get(node) != null) { - id = canonicalId.get(node); - } else { - id = nextId++; - canonicalId.set(node, id); + if (node.recordsUsages()) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { + int id; + if (canonicalId.get(node) != null) { + id = canonicalId.get(node); + } else { + id = nextId++; + canonicalId.set(node, id); + } + String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); + result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.usages().count() + ")\n")); } - String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.usages().count() + ")\n")); } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -197,7 +197,7 @@ @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { - if (expected.getNodeCount() != graph.getNodeCount()) { + if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { outputGraph(expected, "expected"); outputGraph(graph, "actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); @@ -225,7 +225,7 @@ } private static void outputNode(Node node) { - TTY.print(" " + node + " (usage count: " + node.usages().count() + ") (inputs:"); + TTY.print(" " + node + " (usage count: " + (node.recordsUsages() ? node.usages().count() : "?") + ") (inputs:"); for (Node input : node.inputs()) { TTY.print(" " + input.toString(Verbosity.Id)); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -63,7 +63,7 @@ if (node instanceof ConstantNode) { ConstantNode constant = (ConstantNode) node; if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("-", getMetaAccess(), graph)); + constant.replace(ConstantNode.forObject("-", getMetaAccess(), graph)); } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Oct 25 01:39:54 2013 +0200 @@ -138,32 +138,44 @@ Debug.scope("GraalCompiler", new Object[]{graph, providers.getCodeCache()}, new Runnable() { public void run() { - final Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); - final LIR lir = Debug.scope("FrontEnd", new Callable() { + compileGraphNoScope(graph, cc, installedCodeOwner, providers, backend, target, cache, plan, optimisticOpts, speculationLog, suites, compilationResult); + } + }); - public LIR call() { - try (TimerCloseable a = FrontEnd.start()) { - return emitHIR(providers, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog, suites); - } - } - }); - try (TimerCloseable a = BackEnd.start()) { - final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable() { + return compilationResult; + } - public LIRGenerator call() { - return emitLIR(backend, target, lir, graph, cc); - } - }); - Debug.scope("CodeGen", lirGen, new Runnable() { + /** + * Same as {@link #compileGraph} but without entering a + * {@linkplain Debug#scope(String, Object[], Runnable) debug scope}. + */ + public static T compileGraphNoScope(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final Providers providers, + final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, + final SpeculationLog speculationLog, final Suites suites, final T compilationResult) { + final Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); + final LIR lir = Debug.scope("FrontEnd", new Callable() { - public void run() { - emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner); - } - - }); + public LIR call() { + try (TimerCloseable a = FrontEnd.start()) { + return emitHIR(providers, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog, suites); } } }); + try (TimerCloseable a = BackEnd.start()) { + final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable() { + + public LIRGenerator call() { + return emitLIR(backend, target, lir, graph, cc); + } + }); + Debug.scope("CodeGen", lirGen, new Runnable() { + + public void run() { + emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner); + } + + }); + } return compilationResult; } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri Oct 25 01:39:54 2013 +0200 @@ -69,7 +69,11 @@ // @formatter:on public static boolean areDebugScopePatternsEnabled() { - return DumpOnError.getValue() || Dump.getValue() != null || Meter.getValue() != null || Time.getValue() != null || Log.getValue() != null; + return DumpOnError.getValue() || Dump.getValue() != null || Log.getValue() != null || areMetricsOrTimersEnabled(); + } + + public static boolean areMetricsOrTimersEnabled() { + return Meter.getValue() != null || Time.getValue() != null; } private final DebugFilter logFilter; diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Oct 25 01:39:54 2013 +0200 @@ -869,8 +869,7 @@ // check that the liveIn set of the first block is empty Block startBlock = ir.cfg.getStartBlock(); - BitSet liveInArgs = new BitSet(blockData.get(startBlock).liveIn.size()); - if (!blockData.get(startBlock).liveIn.equals(liveInArgs)) { + if (blockData.get(startBlock).liveIn.cardinality() != 0) { if (DetailedAsserts.getValue()) { reportFailure(numBlocks); } @@ -878,73 +877,76 @@ TTY.println("preds=" + startBlock.getPredecessorCount() + ", succs=" + startBlock.getSuccessorCount()); TTY.println("startBlock-ID: " + startBlock.getId()); - // bailout of if this occurs in product mode. - throw new GraalInternalError("liveIn set of first block must be empty"); + // bailout if this occurs in product mode. + throw new GraalInternalError("liveIn set of first block must be empty: " + blockData.get(startBlock).liveIn); } } private void reportFailure(int numBlocks) { TTY.println(gen.getGraph().toString()); - TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)"); - TTY.print("affected registers:"); - TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString()); + TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):"); + BitSet startBlockLiveIn = blockData.get(ir.cfg.getStartBlock()).liveIn; + for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { + Value operand = operandFor(operandNum); + TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand)); + } // print some additional information to simplify debugging - for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) { - if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) { - Value operand = operandFor(operandNum); - TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand)); + for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { + Value operand = operandFor(operandNum); + TTY.println("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand.toString(), gen.valueForOperand(operand)); + + Deque definedIn = new ArrayDeque<>(); + HashSet usedIn = new HashSet<>(); + for (Block block : sortedBlocks) { + if (blockData.get(block).liveGen.get(operandNum)) { + usedIn.add(block); + TTY.println("used in block B%d {", block.getId()); + for (LIRInstruction ins : ir.lir(block)) { + TTY.println(" " + ins.id() + ": " + ins.toString()); + ins.forEachState(new ValueProcedure() { - Deque definedIn = new ArrayDeque<>(); - HashSet usedIn = new HashSet<>(); - for (Block block : sortedBlocks) { - if (blockData.get(block).liveGen.get(operandNum)) { - usedIn.add(block); - TTY.println(" used in block B%d", block.getId()); - for (LIRInstruction ins : ir.lir(block)) { - TTY.println(ins.id() + ": " + ins.toString()); - ins.forEachState(new ValueProcedure() { + @Override + public Value doValue(Value liveStateOperand) { + TTY.println(" operand=" + liveStateOperand); + return liveStateOperand; + } + }); + } + TTY.println("}"); + } + if (blockData.get(block).liveKill.get(operandNum)) { + definedIn.add(block); + TTY.println("defined in block B%d {", block.getId()); + for (LIRInstruction ins : ir.lir(block)) { + TTY.println(" " + ins.id() + ": " + ins.toString()); + } + TTY.println("}"); + } + } - @Override - public Value doValue(Value liveStateOperand) { - TTY.println(" operand=" + liveStateOperand); - return liveStateOperand; - } - }); + int[] hitCount = new int[numBlocks]; + + while (!definedIn.isEmpty()) { + Block block = definedIn.removeFirst(); + usedIn.remove(block); + for (Block successor : block.getSuccessors()) { + if (successor.isLoopHeader()) { + if (!block.isLoopEnd()) { + definedIn.add(successor); } - } - if (blockData.get(block).liveKill.get(operandNum)) { - definedIn.add(block); - TTY.println(" defined in block B%d", block.getId()); - for (LIRInstruction ins : ir.lir(block)) { - TTY.println(ins.id() + ": " + ins.toString()); + } else { + if (++hitCount[successor.getId()] == successor.getPredecessorCount()) { + definedIn.add(successor); } } } - - int[] hitCount = new int[numBlocks]; - - while (!definedIn.isEmpty()) { - Block block = definedIn.removeFirst(); - usedIn.remove(block); - for (Block successor : block.getSuccessors()) { - if (successor.isLoopHeader()) { - if (!block.isLoopEnd()) { - definedIn.add(successor); - } - } else { - if (++hitCount[successor.getId()] == successor.getPredecessorCount()) { - definedIn.add(successor); - } - } - } - } - TTY.print(" offending usages are in: "); - for (Block block : usedIn) { - TTY.print("B%d ", block.getId()); - } - TTY.println(); } + TTY.print("**** offending usages are in: "); + for (Block block : usedIn) { + TTY.print("B%d ", block.getId()); + } + TTY.println(); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Oct 25 01:39:54 2013 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.lir.LIRValueUtil.*; +import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -66,6 +67,13 @@ protected final DebugInfoBuilder debugInfoBuilder; protected Block currentBlock; + + /** + * Maps constants the variables within the scope of a single block to avoid loading a constant + * more than once per block. + */ + private Map constantsLoadedInCurrentBlock; + private ValueNode currentInstruction; private ValueNode lastInstructionPrinted; // Debugging only @@ -151,7 +159,38 @@ if (nodeOperands == null) { return null; } - return nodeOperands.get(node); + Value operand = nodeOperands.get(node); + if (operand == null) { + return getConstantOperand(node); + } + return operand; + } + + private Value getConstantOperand(ValueNode node) { + if (!ConstantNodeRecordsUsages) { + Constant value = node.asConstant(); + if (value != null) { + if (canInlineConstant(value)) { + return setResult(node, value); + } else { + Variable loadedValue; + if (constantsLoadedInCurrentBlock == null) { + constantsLoadedInCurrentBlock = new HashMap<>(); + loadedValue = null; + } else { + loadedValue = constantsLoadedInCurrentBlock.get(value); + } + if (loadedValue == null) { + loadedValue = emitMove(value); + constantsLoadedInCurrentBlock.put(value, loadedValue); + } + return loadedValue; + } + } + } else { + // Constant is loaded by ConstantNode.generate() + } + return null; } public ValueNode valueForOperand(Value value) { @@ -188,7 +227,7 @@ @Override public Value setResult(ValueNode x, Value operand) { assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable()); - assert operand(x) == null : "operand cannot be set twice"; + assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; assert operand.getKind().getStackKind() == x.kind() || x.kind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.kind(); assert !(x instanceof VirtualObjectNode); @@ -296,6 +335,8 @@ } currentBlock = block; + resetLoadedConstants(); + // set up the list of LIR instructions assert lir.lir(block) == null : "LIR list already computed for this block"; lir.setLir(block, new ArrayList()); @@ -319,7 +360,9 @@ if (TraceLIRGeneratorLevel.getValue() >= 3) { TTY.println("LIRGen for " + instr); } - if (instr instanceof ValueNode) { + if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) { + // Loading of constants is done lazily by operand() + } else if (instr instanceof ValueNode) { ValueNode valueNode = (ValueNode) instr; if (operand(valueNode) == null) { if (!peephole(valueNode)) { @@ -355,6 +398,12 @@ } } + private void resetLoadedConstants() { + if (constantsLoadedInCurrentBlock != null && !constantsLoadedInCurrentBlock.isEmpty()) { + constantsLoadedInCurrentBlock.clear(); + } + } + protected abstract boolean peephole(ValueNode valueNode); private boolean endsWithJump(Block block) { diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Fri Oct 25 01:39:54 2013 +0200 @@ -361,7 +361,7 @@ int minCount = Integer.MAX_VALUE; Node minCountNode = null; for (Node input : node.inputs()) { - if (input != null) { + if (input != null && input.recordsUsages()) { int estimate = input.getUsageCountUpperBound(); if (estimate == 0) { return null; diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Oct 25 01:39:54 2013 +0200 @@ -255,6 +255,7 @@ } int getUsageCountUpperBound() { + assert recordsUsages(); if (usage0 == null) { return 0; } @@ -265,13 +266,23 @@ } /** - * Gets the list of nodes that use this node (e.g., as an input). + * Gets the list of nodes that use this node (i.e., as an input). */ public final NodeIterable usages() { + assert recordsUsages() : this; return new NodeUsageIterable(); } /** + * Determines if this node records its usages (i.e. the nodes for which it is an input). All + * methods in {@link Node} that pertain to querying or updating usage information must not be + * called for a {@link Node} instance that returns false for this method. + */ + public boolean recordsUsages() { + return true; + } + + /** * Finds the index of the last non-null entry in a node array. The search assumes that all * non-null entries precede the first null entry in the array. * @@ -311,6 +322,7 @@ * @param node the node to add */ private void addUsage(Node node) { + assert recordsUsages(); incUsageModCount(); if (usage0 == null) { usage0 = node; @@ -342,6 +354,7 @@ * @return whether or not {@code usage} was in the usage list */ private boolean removeUsage(Node node) { + assert recordsUsages(); // It is critical that this method maintains the invariant that // the usage list has no null element preceding a non-null element incUsageModCount(); @@ -392,6 +405,7 @@ } private void clearUsages() { + assert recordsUsages(); incUsageModCount(); usage0 = null; usage1 = null; @@ -443,16 +457,20 @@ protected void updateUsages(Node oldInput, Node newInput) { if (oldInput != newInput) { if (oldInput != null) { - boolean result = removeThisFromUsages(oldInput); - assert assertTrue(result, "not found in usages, old input: %s", oldInput); + if (oldInput.recordsUsages()) { + boolean result = removeThisFromUsages(oldInput); + assert assertTrue(result, "not found in usages, old input: %s", oldInput); + } } if (newInput != null) { - NodeChangedListener listener = graph.inputChangedListener; - if (listener != null) { - listener.nodeChanged(this); + if (newInput.recordsUsages()) { + NodeChangedListener listener = graph.inputChangedListener; + if (listener != null) { + listener.nodeChanged(this); + } + newInput.addUsage(this); } - newInput.addUsage(this); - } else if (oldInput != null && oldInput.usages().isEmpty()) { + } else if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { NodeChangedListener listener = graph.usagesDroppedToZeroListener; if (listener != null) { listener.nodeChanged(oldInput); @@ -513,7 +531,9 @@ if (listener != null) { listener.nodeChanged(usage); } - other.addUsage(usage); + if (other.recordsUsages()) { + other.addUsage(usage); + } } } clearUsages(); @@ -554,11 +574,13 @@ assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); for (Node input : inputs()) { - removeThisFromUsages(input); - if (input.usages().isEmpty()) { - NodeChangedListener listener = graph.usagesDroppedToZeroListener; - if (listener != null) { - listener.nodeChanged(input); + if (input.recordsUsages()) { + removeThisFromUsages(input); + if (input.usages().isEmpty()) { + NodeChangedListener listener = graph.usagesDroppedToZeroListener; + if (listener != null) { + listener.nodeChanged(input); + } } } } @@ -580,7 +602,9 @@ } private boolean checkDeletion() { - assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages()); + if (recordsUsages()) { + assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages()); + } assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor); return true; } @@ -603,7 +627,9 @@ NodeClass clazz = getNodeClass(); clazz.copyInputs(this, newNode); for (Node input : inputs()) { - input.addUsage(newNode); + if (input.recordsUsages()) { + input.addUsage(newNode); + } } return newNode; } @@ -676,16 +702,18 @@ assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); for (Node input : inputs()) { - assertTrue(input.usages().contains(this), "missing usage in input %s", input); + assertTrue(!input.recordsUsages() || input.usages().contains(this), "missing usage in input %s", input); assertTrue(input.graph() == graph(), "mismatching graph in input %s", input); } for (Node successor : successors()) { assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor()); assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor); } - for (Node usage : usages()) { - assertFalse(usage.isDeleted(), "usage must never be deleted"); - assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage); + if (recordsUsages()) { + for (Node usage : usages()) { + assertFalse(usage.isDeleted(), "usage must never be deleted"); + assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage); + } } if (predecessor != null) { assertFalse(predecessor.isDeleted(), "predecessor must never be deleted"); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Oct 25 01:39:54 2013 +0200 @@ -1189,6 +1189,7 @@ return new Iterator() { int i = 0; + @Override public void remove() { throw new UnsupportedOperationException(); } @@ -1219,6 +1220,7 @@ return new Iterator() { int i = 0; + @Override public void remove() { throw new UnsupportedOperationException(); } @@ -1313,7 +1315,7 @@ newNodes.put(node, replacement); } else { Node newNode = node.clone(graph, false); - assert newNode.usages().count() == 0 || newNode.inputs().count() == 0; + assert newNode.inputs().count() == 0 || newNode.usages().count() == 0; assert newNode.getClass() == node.getClass(); newNodes.put(node, newNode); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Oct 25 01:39:54 2013 +0200 @@ -252,7 +252,7 @@ /** * @param installedCodeOwner see {@link Backend#emitCode} */ - protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) { + public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) { HotSpotProviders providers = getProviders(); if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); @@ -282,14 +282,14 @@ /** * @param installedCodeOwner see {@link Backend#emitCode} */ - protected void emitCodeBody(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen) { + public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen) { lirGen.lir.emitCode(tasm); } /** * @param installedCodeOwner see {@link Backend#emitCode} */ - protected void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen, AMD64MacroAssembler asm, FrameMap frameMap) { + public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen, AMD64MacroAssembler asm, FrameMap frameMap) { HotSpotProviders providers = getProviders(); HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext; if (frameContext != null && !frameContext.isStub) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Oct 25 01:39:54 2013 +0200 @@ -265,9 +265,9 @@ if (linkage.canDeoptimize()) { assert info != null || stub != null; Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread)); + append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); result = super.emitForeignCall(linkage, info, args); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaFpOffset, thread)); + append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); } else { result = super.emitForeignCall(linkage, null, args); } @@ -521,7 +521,7 @@ } private int getLogMinObjectAlignment() { - return config.logMinObjAlignment; + return config.logMinObjAlignment(); } private int getNarrowOopShift() { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Fri Oct 25 01:39:54 2013 +0200 @@ -210,7 +210,7 @@ } } - private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) { + public static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) { // If the base is zero, the compressed address has to be shifted left // in order to be uncompressed. if (base == 0) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Fri Oct 25 01:39:54 2013 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; @@ -57,9 +58,19 @@ emitCode(tasm, asm, config, false, state, scratch.getRegister()); } + /** + * Tests if the polling page address can be reached from the code cache with 32-bit + * displacements. + */ + private static boolean isPollingPageFar(HotSpotVMConfig config) { + final long pollingPageAddress = config.safepointPollingAddress; + // TODO return ForceUnreachable || + return !NumUtil.isInt(pollingPageAddress - config.codeCacheLowBoundary()) || !NumUtil.isInt(pollingPageAddress - config.codeCacheHighBoundary()); + } + public static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { final int pos = asm.codeBuffer.position(); - if (config.isPollingPageFar) { + if (isPollingPageFar(config)) { asm.movq(scratch, config.safepointPollingAddress); tasm.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); if (state != null) { diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Fri Oct 25 01:39:54 2013 +0200 @@ -60,7 +60,7 @@ assert access == null || access instanceof HeapAccess; if (config.useCompressedOops && isCompressCandidate(access)) { Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment)); + append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment())); } else { append(new LoadOp(kind, result, loadAddress, state)); } @@ -74,7 +74,7 @@ Variable input = load(inputVal); if (config.useCompressedOops && isCompressCandidate(access)) { Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment)); + append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment())); } else { append(new StoreOp(kind, storeAddress, input, state)); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Fri Oct 25 01:39:54 2013 +0200 @@ -103,9 +103,9 @@ HotSpotRegistersProvider registers = getProviders().getRegisters(); Register thread = registers.getThreadRegister(); Register stackPointer = registers.getStackPointerRegister(); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread, stackPointer)); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer)); result = super.emitForeignCall(linkage, info, args); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaPcOffset, config.threadJavaFrameAnchorFlagsOffset, thread)); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread)); } else { result = super.emitForeignCall(linkage, null, args); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Fri Oct 25 01:39:54 2013 +0200 @@ -61,7 +61,6 @@ public static void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { final int pos = masm.codeBuffer.position(); new Setx(config.safepointPollingAddress, scratch).emit(masm); - assert !config.isPollingPageFar; tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); if (state != null) { tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -48,7 +48,7 @@ @Override protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; - HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, true); + HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, compResult.getName(), true); HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult); CodeInstallResult result = runtime().getCompilerToVM().installCode(compiledNmethod, installedCode, null); Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -175,7 +175,7 @@ } public static Object test5Snippet() throws Exception { - return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object); + return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object, LocationIdentity.ANY_LOCATION); } /** @@ -250,7 +250,7 @@ public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception { final int offset = (c == null ? 0 : ((Integer) c).intValue()); final long displacement = (b == null ? 0 : ((Long) b).longValue()); - return UnsafeLoadNode.load(a, offset + displacement, Kind.Object); + return UnsafeLoadNode.load(a, offset + displacement, Kind.Object, LocationIdentity.ANY_LOCATION); } private HotSpotInstalledCode getInstalledCode(String name) throws Exception { diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Oct 25 01:39:54 2013 +0200 @@ -174,7 +174,7 @@ if (value != null) { OptionValue optionValue = desc.getOptionValue(); optionValue.setValue(value); - // Logger.info("Set option " + fieldName + " to " + value); + // Logger.info("Set option " + desc.getName() + " to " + value); } else { Logger.info("Wrong value \"" + valueString + "\" for option " + optionName); return false; diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Oct 25 01:39:54 2013 +0200 @@ -22,274 +22,792 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.graph.UnsafeAccess.*; + import java.lang.reflect.*; +import java.util.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.bridge.*; -import com.sun.management.HotSpotDiagnosticMXBean; - -import sun.management.ManagementFactoryHelper; /** * Used to access native configuration details. * - * All non-static, public fields in this class are final so that they can be compiled as constants. + * All non-static, public fields in this class are so that they can be compiled as constants. */ -public final class HotSpotVMConfig extends CompilerObject { +public class HotSpotVMConfig extends CompilerObject { private static final long serialVersionUID = -4744897993263044184L; - private static final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); + HotSpotVMConfig(CompilerToVM compilerToVm) { + compilerToVm.initializeConfiguration(this); + + // Fill the VM fields hash map. + HashMap vmFields = new HashMap<>(); + for (VMFields.Field e : new VMFields(gHotSpotVMStructs)) { + vmFields.put(e.getName(), e); + } + + // Fill the VM types hash map. + HashMap vmTypes = new HashMap<>(); + for (VMTypes.Type e : new VMTypes(gHotSpotVMTypes)) { + vmTypes.put(e.getTypeName(), e); + } + + // Fill the VM constants hash map. + HashMap vmConstants = new HashMap<>(); + for (AbstractConstant e : new VMIntConstants(gHotSpotVMIntConstants)) { + vmConstants.put(e.getName(), e); + } + for (AbstractConstant e : new VMLongConstants(gHotSpotVMLongConstants)) { + vmConstants.put(e.getName(), e); + } + + // Fill the flags hash map. + HashMap flags = new HashMap<>(); + for (Flags.Flag e : new Flags(vmFields, vmTypes)) { + flags.put(e.getName(), e); + } - HotSpotVMConfig(CompilerToVM c2vm) { - c2vm.initializeConfiguration(this); + for (Field f : HotSpotVMConfig.class.getDeclaredFields()) { + if (f.isAnnotationPresent(HotSpotVMField.class)) { + HotSpotVMField annotation = f.getAnnotation(HotSpotVMField.class); + String name = annotation.name(); + VMFields.Field entry = vmFields.get(name); + if (entry == null) { + if (annotation.optional()) { + continue; + } else { + throw new IllegalArgumentException("field not found: " + name); + } + } + switch (annotation.get()) { + case OFFSET: + setField(f, entry.getOffset()); + break; + case ADDRESS: + setField(f, entry.getAddress()); + break; + case VALUE: + setField(f, entry.getValue()); + break; + default: + throw GraalInternalError.shouldNotReachHere("unknown kind " + annotation.get()); + } + } else if (f.isAnnotationPresent(HotSpotVMType.class)) { + HotSpotVMType annotation = f.getAnnotation(HotSpotVMType.class); + String name = annotation.name(); + VMTypes.Type entry = vmTypes.get(name); + if (entry == null) { + throw new IllegalArgumentException("type not found: " + name); + } + switch (annotation.get()) { + case SIZE: + setField(f, entry.getSize()); + break; + default: + throw GraalInternalError.shouldNotReachHere("unknown kind " + annotation.get()); + } + } else if (f.isAnnotationPresent(HotSpotVMConstant.class)) { + HotSpotVMConstant annotation = f.getAnnotation(HotSpotVMConstant.class); + String name = annotation.name(); + AbstractConstant entry = vmConstants.get(name); + if (entry == null) { + if (annotation.optional()) { + continue; + } else { + throw new IllegalArgumentException("constant not found: " + name); + } + } + setField(f, entry.getValue()); + } else if (f.isAnnotationPresent(HotSpotVMFlag.class)) { + HotSpotVMFlag annotation = f.getAnnotation(HotSpotVMFlag.class); + String name = annotation.name(); + Flags.Flag entry = flags.get(name); + if (entry == null) { + if (annotation.optional()) { + continue; + } else { + throw new IllegalArgumentException("flag not found: " + name); + } + } + setField(f, entry.getValue()); + } + } + assert check(); } + private void setField(Field field, Object value) { + try { + Class fieldType = field.getType(); + if (fieldType == boolean.class) { + if (value instanceof String) { + field.setBoolean(this, Boolean.valueOf((String) value)); + } else if (value instanceof Boolean) { + field.setBoolean(this, (boolean) value); + } else if (value instanceof Long) { + field.setBoolean(this, ((long) value) != 0); + } else { + GraalInternalError.shouldNotReachHere(value.getClass().getSimpleName()); + } + } else if (fieldType == int.class) { + if (value instanceof Integer) { + field.setInt(this, (int) value); + } else if (value instanceof Long) { + field.setInt(this, (int) (long) value); + } else { + GraalInternalError.shouldNotReachHere(value.getClass().getSimpleName()); + } + } else if (fieldType == long.class) { + field.setLong(this, (long) value); + } else { + GraalInternalError.shouldNotReachHere(field.toString()); + } + } catch (IllegalAccessException e) { + throw GraalInternalError.shouldNotReachHere(field.toString() + ": " + e); + } + } + /** - * Gets the value of an VM option. - * - * @param name option's name - * @return value of option - * @throws IllegalArgumentException if option doesn't exist + * VMStructEntry (see vmStructs.hpp). */ - public static int getVMOptionInt(String name) { - String value = diagnostic.getVMOption(name).getValue(); - return Integer.valueOf(value).intValue(); - } + private long gHotSpotVMStructs; + private long gHotSpotVMStructEntryTypeNameOffset; + private long gHotSpotVMStructEntryFieldNameOffset; + private long gHotSpotVMStructEntryTypeStringOffset; + private long gHotSpotVMStructEntryIsStaticOffset; + private long gHotSpotVMStructEntryOffsetOffset; + private long gHotSpotVMStructEntryAddressOffset; + private long gHotSpotVMStructEntryArrayStride; + + class VMFields implements Iterable { + + private long address; + + public VMFields(long address) { + this.address = address; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + private Field current() { + return new Field(address + gHotSpotVMStructEntryArrayStride * index); + } + + /** + * The last entry is identified by a NULL fieldName. + */ + public boolean hasNext() { + Field entry = current(); + return entry.getFieldName() != null; + } + + public Field next() { + Field entry = current(); + index++; + return entry; + } + + @Override + public void remove() { + throw GraalInternalError.unimplemented(); + } + }; + } + + class Field { + + private long entryAddress; - /** - * Gets the value of an VM option. - * - * @param name option's name - * @param defaultValue default value if option is not exists (e.g. development options) - * @return value of option or defaultValue if option doesn't exist - */ - public static int getVMOption(String name, int defaultValue) { - try { - return getVMOptionInt(name); - } catch (IllegalArgumentException e) { - return defaultValue; + Field(long address) { + this.entryAddress = address; + } + + public String getTypeName() { + long typeNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryTypeNameOffset); + return readCStringAsString(typeNameAddress); + } + + public String getFieldName() { + long fieldNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryFieldNameOffset); + return readCStringAsString(fieldNameAddress); + } + + public String getTypeString() { + long typeStringAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryTypeStringOffset); + return readCStringAsString(typeStringAddress); + } + + public boolean isStatic() { + return unsafe.getInt(entryAddress + gHotSpotVMStructEntryIsStaticOffset) != 0; + } + + public long getOffset() { + return unsafe.getLong(entryAddress + gHotSpotVMStructEntryOffsetOffset); + } + + public long getAddress() { + return unsafe.getAddress(entryAddress + gHotSpotVMStructEntryAddressOffset); + } + + public String getName() { + String typeName = getTypeName(); + String fieldName = getFieldName(); + return typeName + "::" + fieldName; + } + + public long getValue() { + String type = getTypeString(); + switch (type) { + case "int": + return unsafe.getInt(getAddress()); + case "address": + case "intptr_t": + return unsafe.getAddress(getAddress()); + default: + // All foo* types are addresses. + if (type.endsWith("*")) { + return unsafe.getAddress(getAddress()); + } + throw GraalInternalError.shouldNotReachHere(type); + } + } + + @Override + public String toString() { + return String.format("Field[typeName=%s, fieldName=%s, typeString=%s, isStatic=%b, offset=%d, address=0x%x]", getTypeName(), getFieldName(), getTypeString(), isStatic(), getOffset(), + getAddress()); + } } } /** - * Gets the value of an VM option. - * - * @param name option's name - * @return value of option - * @throws IllegalArgumentException if option doesn't exist + * VMTypeEntry (see vmStructs.hpp). */ - public static boolean getVMOption(String name) { - String value = diagnostic.getVMOption(name).getValue(); - return Boolean.valueOf(value).booleanValue(); + private long gHotSpotVMTypes; + private long gHotSpotVMTypeEntryTypeNameOffset; + private long gHotSpotVMTypeEntrySuperclassNameOffset; + private long gHotSpotVMTypeEntryIsOopTypeOffset; + private long gHotSpotVMTypeEntryIsIntegerTypeOffset; + private long gHotSpotVMTypeEntryIsUnsignedOffset; + private long gHotSpotVMTypeEntrySizeOffset; + private long gHotSpotVMTypeEntryArrayStride; + + class VMTypes implements Iterable { + + private long address; + + public VMTypes(long address) { + this.address = address; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + private Type current() { + return new Type(address + gHotSpotVMTypeEntryArrayStride * index); + } + + /** + * The last entry is identified by a NULL type name. + */ + public boolean hasNext() { + Type entry = current(); + return entry.getTypeName() != null; + } + + public Type next() { + Type entry = current(); + index++; + return entry; + } + + @Override + public void remove() { + throw GraalInternalError.unimplemented(); + } + }; + } + + class Type { + + private long entryAddress; + + Type(long address) { + this.entryAddress = address; + } + + public String getTypeName() { + long typeNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMTypeEntryTypeNameOffset); + return readCStringAsString(typeNameAddress); + } + + public String getSuperclassName() { + long superclassNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMTypeEntrySuperclassNameOffset); + return readCStringAsString(superclassNameAddress); + } + + public boolean isOopType() { + return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsOopTypeOffset) != 0; + } + + public boolean isIntegerType() { + return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsIntegerTypeOffset) != 0; + } + + public boolean isUnsigned() { + return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsUnsignedOffset) != 0; + } + + public long getSize() { + return unsafe.getLong(entryAddress + gHotSpotVMTypeEntrySizeOffset); + } + + @Override + public String toString() { + return String.format("Type[typeName=%s, superclassName=%s, isOopType=%b, isIntegerType=%b, isUnsigned=%b, size=%d]", getTypeName(), getSuperclassName(), isOopType(), isIntegerType(), + isUnsigned(), getSize()); + } + } + } + + public abstract class AbstractConstant { + + protected long address; + protected long nameOffset; + protected long valueOffset; + + AbstractConstant(long address, long nameOffset, long valueOffset) { + this.address = address; + this.nameOffset = nameOffset; + this.valueOffset = valueOffset; + } + + public String getName() { + long nameAddress = unsafe.getAddress(address + nameOffset); + return readCStringAsString(nameAddress); + } + + public abstract long getValue(); + } + + /** + * VMIntConstantEntry (see vmStructs.hpp). + */ + private long gHotSpotVMIntConstants; + private long gHotSpotVMIntConstantEntryNameOffset; + private long gHotSpotVMIntConstantEntryValueOffset; + private long gHotSpotVMIntConstantEntryArrayStride; + + class VMIntConstants implements Iterable { + + private long address; + + public VMIntConstants(long address) { + this.address = address; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + private Constant current() { + return new Constant(address + gHotSpotVMIntConstantEntryArrayStride * index); + } + + /** + * The last entry is identified by a NULL name. + */ + public boolean hasNext() { + Constant entry = current(); + return entry.getName() != null; + } + + public Constant next() { + Constant entry = current(); + index++; + return entry; + } + + @Override + public void remove() { + throw GraalInternalError.unimplemented(); + } + }; + } + + class Constant extends AbstractConstant { + + Constant(long address) { + super(address, gHotSpotVMIntConstantEntryNameOffset, gHotSpotVMIntConstantEntryValueOffset); + } + + @Override + public long getValue() { + return unsafe.getInt(address + valueOffset); + } + + @Override + public String toString() { + return String.format("IntConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue()); + } + } } /** - * Gets the value of an VM option. - * - * @param name option's name - * @param defaultValue default value if option is not exists (e.g. development options) - * @return value of option or defaultValue if option doesn't exist + * VMLongConstantEntry (see vmStructs.hpp). */ - public static boolean getVMOption(String name, boolean defaultValue) { - try { - return getVMOption(name); - } catch (IllegalArgumentException e) { - return defaultValue; + private long gHotSpotVMLongConstants; + private long gHotSpotVMLongConstantEntryNameOffset; + private long gHotSpotVMLongConstantEntryValueOffset; + private long gHotSpotVMLongConstantEntryArrayStride; + + class VMLongConstants implements Iterable { + + private long address; + + public VMLongConstants(long address) { + this.address = address; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + private Constant currentEntry() { + return new Constant(address + gHotSpotVMLongConstantEntryArrayStride * index); + } + + /** + * The last entry is identified by a NULL name. + */ + public boolean hasNext() { + Constant entry = currentEntry(); + return entry.getName() != null; + } + + public Constant next() { + Constant entry = currentEntry(); + index++; + return entry; + } + + @Override + public void remove() { + throw GraalInternalError.unimplemented(); + } + }; + } + + class Constant extends AbstractConstant { + + Constant(long address) { + super(address, gHotSpotVMLongConstantEntryNameOffset, gHotSpotVMLongConstantEntryValueOffset); + } + + @Override + public long getValue() { + return unsafe.getLong(address + valueOffset); + } + + @Override + public String toString() { + return String.format("LongConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue()); + } } } - // Using systenm properties ensures the Java source compilers can never - // optimize away an access to a config field - private static final boolean UNINITIALIZED_BOOLEAN = Boolean.getBoolean("graal.config.uninitializedBoolean"); - private static final long UNINITIALIZED_LONG = Long.getLong("graal.config.uninitializedLong", 0L); - private static final int UNINITIALIZED_INT = Integer.getInteger("graal.config.uninitializedInt", 0); + class Flags implements Iterable { + + private long address; + private long entrySize; + private long typeOffset; + private long nameOffset; + private long addrOffset; + + public Flags(HashMap vmStructs, HashMap vmTypes) { + address = vmStructs.get("Flag::flags").getValue(); + entrySize = vmTypes.get("Flag").getSize(); + typeOffset = vmStructs.get("Flag::_type").getOffset(); + nameOffset = vmStructs.get("Flag::_name").getOffset(); + addrOffset = vmStructs.get("Flag::_addr").getOffset(); + + // TODO use the following after we switched to JDK 8 + assert vmTypes.get("bool").getSize() == Byte.SIZE / Byte.SIZE; // TODO Byte.BYTES; + assert vmTypes.get("intx").getSize() == Long.SIZE / Byte.SIZE; // TODO Long.BYTES; + assert vmTypes.get("uintx").getSize() == Long.SIZE / Byte.SIZE; // TODO Long.BYTES; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + private Flag current() { + return new Flag(address + entrySize * index); + } + + /** + * The last entry is identified by a NULL name. + */ + public boolean hasNext() { + Flag entry = current(); + return entry.getName() != null; + } + + public Flag next() { + Flag entry = current(); + index++; + return entry; + } - private static int getUninitializedInt() { - return UNINITIALIZED_INT; + @Override + public void remove() { + throw GraalInternalError.unimplemented(); + } + }; + } + + class Flag { + + private long entryAddress; + + Flag(long address) { + this.entryAddress = address; + } + + public String getType() { + long typeAddress = unsafe.getAddress(entryAddress + typeOffset); + return readCStringAsString(typeAddress); + } + + public String getName() { + long nameAddress = unsafe.getAddress(entryAddress + nameOffset); + return readCStringAsString(nameAddress); + } + + public long getAddr() { + return unsafe.getAddress(entryAddress + addrOffset); + } + + public Object getValue() { + switch (getType()) { + case "bool": + return Boolean.valueOf(unsafe.getByte(getAddr()) != 0); + case "intx": + case "uintx": + case "uint64_t": + return Long.valueOf(unsafe.getLong(getAddr())); + case "double": + return Double.valueOf(unsafe.getDouble(getAddr())); + case "ccstr": + case "ccstrlist": + return readCStringAsString(getAddr()); + default: + throw GraalInternalError.shouldNotReachHere(getType()); + } + } + + @Override + public String toString() { + return String.format("Flag[type=%s, name=%s, value=%s]", getType(), getName(), getValue()); + } + } } - private static long getUninitializedLong() { - return UNINITIALIZED_LONG; - } - - private static boolean getUninitializedBoolean() { - return UNINITIALIZED_BOOLEAN; + /** + * Read a null-terminated C string from memory and convert it to a Java String. + */ + private static String readCStringAsString(long address) { + if (address == 0) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0;; i++) { + char c = (char) unsafe.getByte(address + i); + if (c == 0) { + break; + } + sb.append(c); + } + return sb.toString(); } // os information, register layout, code generation, ... - public final boolean cAssertions = getUninitializedBoolean(); + @HotSpotVMConstant(name = "ASSERT") @Stable public boolean cAssertions; public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows"); - public final int codeEntryAlignment = getUninitializedInt(); - public final boolean verifyOops = getVMOption("VerifyOops", false); - public final boolean ciTime = getVMOption("CITime"); - public final int compileThreshold = getVMOptionInt("CompileThreshold"); - public final boolean compileTheWorld = getVMOption("CompileTheWorld", false); - public final int compileTheWorldStartAt = getVMOption("CompileTheWorldStartAt", 1); - public final int compileTheWorldStopAt = getVMOption("CompileTheWorldStopAt", Integer.MAX_VALUE); - public final boolean printCompilation = getVMOption("PrintCompilation"); - public final boolean printInlining = getVMOption("PrintInlining", false); - public final boolean useFastLocking = getVMOption("GraalUseFastLocking", true); - public final boolean useTLAB = getVMOption("UseTLAB"); - public final boolean useBiasedLocking = getVMOption("UseBiasedLocking"); - public final boolean usePopCountInstruction = getVMOption("UsePopCountInstruction"); - public final boolean useAESIntrinsics = getVMOption("UseAESIntrinsics"); - public final boolean useCRC32Intrinsics = getVMOption("UseCRC32Intrinsics"); - public final boolean useG1GC = getVMOption("UseG1GC"); - public final long gcTotalCollectionsAddress = getUninitializedLong(); - public final boolean useDeferredInitBarriers = getVMOption("GraalDeferredInitBarriers"); + + @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment; + @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops; + @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime; + @HotSpotVMFlag(name = "CompileThreshold") @Stable public long compileThreshold; + @HotSpotVMFlag(name = "CompileTheWorld") @Stable public boolean compileTheWorld; + @HotSpotVMFlag(name = "CompileTheWorldStartAt") @Stable public int compileTheWorldStartAt; + @HotSpotVMFlag(name = "CompileTheWorldStopAt") @Stable public int compileTheWorldStopAt; + @HotSpotVMFlag(name = "PrintCompilation") @Stable public boolean printCompilation; + @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining; + @HotSpotVMFlag(name = "GraalUseFastLocking") @Stable public boolean useFastLocking; + + @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB; + @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking; + @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction; + @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics; + @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics; + @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC; + + @HotSpotVMField(name = "Universe::_collectedHeap", get = HotSpotVMField.Type.VALUE) @Stable private long universeCollectedHeap; + @HotSpotVMField(name = "CollectedHeap::_total_collections", get = HotSpotVMField.Type.OFFSET) @Stable private int collectedHeapTotalCollectionsOffset; + + public long gcTotalCollectionsAddress() { + return universeCollectedHeap + collectedHeapTotalCollectionsOffset; + } + + @HotSpotVMFlag(name = "GraalDeferredInitBarriers") @Stable public boolean useDeferredInitBarriers; // Compressed Oops related values. - public final boolean useCompressedOops = getVMOption("UseCompressedOops"); - public final boolean useCompressedClassPointers = getVMOption("UseCompressedClassPointers"); - public final long narrowOopBase = getUninitializedLong(); - public final int narrowOopShift = getUninitializedInt(); - public final int logMinObjAlignment = (int) (Math.log(getVMOptionInt("ObjectAlignmentInBytes")) / Math.log(2)); - public final long narrowKlassBase = getUninitializedLong(); - public final int narrowKlassShift = getUninitializedInt(); - public final int logKlassAlignment = getUninitializedInt(); + @HotSpotVMFlag(name = "UseCompressedOops") @Stable public boolean useCompressedOops; + @HotSpotVMFlag(name = "UseCompressedClassPointers") @Stable public boolean useCompressedClassPointers; + + @HotSpotVMField(name = "Universe::_narrow_oop._base", get = HotSpotVMField.Type.VALUE) @Stable public long narrowOopBase; + @HotSpotVMField(name = "Universe::_narrow_oop._shift", get = HotSpotVMField.Type.VALUE) @Stable public int narrowOopShift; + @HotSpotVMFlag(name = "ObjectAlignmentInBytes") @Stable public int objectAlignment; + + public int logMinObjAlignment() { + return (int) (Math.log(objectAlignment) / Math.log(2)); + } + + @HotSpotVMField(name = "Universe::_narrow_klass._base", get = HotSpotVMField.Type.VALUE) @Stable public long narrowKlassBase; + @HotSpotVMField(name = "Universe::_narrow_klass._shift", get = HotSpotVMField.Type.VALUE) @Stable public int narrowKlassShift; + @HotSpotVMConstant(name = "LogKlassAlignmentInBytes") @Stable public int logKlassAlignment; // CPU capabilities - public final int useSSE = getVMOptionInt("UseSSE"); - public final int useAVX = getVMOption("UseAVX", 99); + @HotSpotVMFlag(name = "UseSSE") @Stable public int useSSE; + @HotSpotVMFlag(name = "UseAVX", optional = true) @Stable public int useAVX; // offsets, ... - public final int stackShadowPages = getVMOptionInt("StackShadowPages"); + @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages; - /** - * The offset of the mark word in an object's header. - */ - public final int markOffset = getUninitializedInt(); - - /** - * The offset of the hub (i.e. Klass*) in an object's header. - */ - public final int hubOffset = getUninitializedInt(); + @HotSpotVMField(name = "oopDesc::_mark", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset; + @HotSpotVMField(name = "oopDesc::_metadata._klass", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset; - /** - * The offset of the _prototype_header field in a Klass. - */ - public final int prototypeMarkWordOffset = getUninitializedInt(); + @HotSpotVMField(name = "Klass::_prototype_header", get = HotSpotVMField.Type.OFFSET) @Stable public int prototypeMarkWordOffset; + @HotSpotVMField(name = "Klass::_subklass", get = HotSpotVMField.Type.OFFSET) @Stable public int subklassOffset; + @HotSpotVMField(name = "Klass::_next_sibling", get = HotSpotVMField.Type.OFFSET) @Stable public int nextSiblingOffset; + @HotSpotVMField(name = "Klass::_super_check_offset", get = HotSpotVMField.Type.OFFSET) @Stable public int superCheckOffsetOffset; + @HotSpotVMField(name = "Klass::_secondary_super_cache", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySuperCacheOffset; + @HotSpotVMField(name = "Klass::_secondary_supers", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySupersOffset; - /** - * The offset of the _subklass field in a Klass. - */ - public final int subklassOffset = getUninitializedInt(); - - /** - * The offset of the _next_sibling field in a Klass. - */ - public final int nextSiblingOffset = getUninitializedInt(); + @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize; + @HotSpotVMField(name = "vtableEntry::_method", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset; + @Stable public int instanceKlassVtableStartOffset; /** * The offset of the array length word in an array object's header. */ - public final int arrayLengthOffset = getUninitializedInt(); + @Stable public int arrayLengthOffset; + + @HotSpotVMField(name = "Array::_length", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset; + @HotSpotVMField(name = "Array::_data", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset; - /** - * The offset of the _length field in an Array metaspace object (see array.hpp). - */ - public final int metaspaceArrayLengthOffset = getUninitializedInt(); + @HotSpotVMField(name = "InstanceKlass::_init_state", get = HotSpotVMField.Type.OFFSET) @Stable public int klassStateOffset; + @HotSpotVMConstant(name = "InstanceKlass::fully_initialized") @Stable public int klassStateFullyInitialized; + @HotSpotVMField(name = "InstanceKlass::_constants", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset; + + @HotSpotVMField(name = "ObjArrayKlass::_element_klass", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayClassElementOffset; - /** - * The offset of the _data field in an Array metaspace object (see array.hpp). - */ - public final int metaspaceArrayBaseOffset = getUninitializedInt(); + @HotSpotVMField(name = "Thread::_tlab", get = HotSpotVMField.Type.OFFSET) @Stable public int threadTlabOffset; - /** - * The offset of the _super_check_offset field in a Klass. - */ - public final int superCheckOffsetOffset = getUninitializedInt(); + @HotSpotVMField(name = "JavaThread::_anchor", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadAnchorOffset; + @HotSpotVMField(name = "JavaThread::_threadObj", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectOffset; + @HotSpotVMField(name = "JavaThread::_osthread", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadOffset; + @HotSpotVMField(name = "JavaThread::_dirty_card_queue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadDirtyCardQueueOffset; + @HotSpotVMField(name = "JavaThread::_is_method_handle_return", get = HotSpotVMField.Type.OFFSET) @Stable public int threadIsMethodHandleReturnOffset; + @HotSpotVMField(name = "JavaThread::_satb_mark_queue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset; + @HotSpotVMField(name = "JavaThread::_vm_result", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset; + @HotSpotVMField(name = "JavaThread::_graal_counters[0]", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable public int graalCountersThreadOffset; - /** - * The offset of the _secondary_super_cache field in a Klass. - */ - public final int secondarySuperCacheOffset = getUninitializedInt(); + @HotSpotVMConstant(name = "GRAAL_COUNTERS_SIZE", optional = true) @Stable public int graalCountersSize; /** - * The offset of the _secondary_supers field in a Klass. - */ - public final int secondarySupersOffset = getUninitializedInt(); - - /** - * The offset of the _init_state field in an instanceKlass. + * This field is used to pass exception objects into and out of the runtime system during + * exception handling for compiled code. + *

+ * NOTE: This is not the same as {@link #pendingExceptionOffset}. */ - public final int klassStateOffset = getUninitializedInt(); - - /** - * The value of instanceKlass::fully_initialized. - */ - public final int klassStateFullyInitialized = getUninitializedInt(); + @HotSpotVMField(name = "JavaThread::_exception_oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionOopOffset; + @HotSpotVMField(name = "JavaThread::_exception_pc", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionPcOffset; - /** - * The value of objArrayKlass::element_klass_offset(). - */ - public final int arrayClassElementOffset = getUninitializedInt(); + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable private int javaFrameAnchorLastJavaFpOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_flags", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable private int javaFrameAnchorFlagsOffset; - /** - * The value of JavaThread::tlab_top_offset(). - */ - public final int threadTlabTopOffset = getUninitializedInt(); + public int threadLastJavaSpOffset() { + return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset; + } - /** - * The value of JavaThread::tlab_end_offset(). - */ - public final int threadTlabEndOffset = getUninitializedInt(); + public int threadLastJavaPcOffset() { + return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset; + } /** - * The value of JavaThread::threadObj_offset(). - */ - public final int threadObjectOffset = getUninitializedInt(); - - /** - * The value of JavaThread::osthread_offset(). - */ - public final int osThreadOffset = getUninitializedInt(); - - /** - * The value of JavaThread::graal_counters_offset(). + * This value is only valid on AMD64. */ - public final int graalCountersThreadOffset = getUninitializedInt(); - - /** - * The length of the JavaThread::_graal_counters array. - */ - public final int graalCountersSize = getUninitializedInt(); - - /** - * The value of OSThread::interrupted_offset(). - */ - public final int osThreadInterruptedOffset = getUninitializedInt(); + public int threadLastJavaFpOffset() { + // TODO add an assert for AMD64 + return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset; + } /** - * The value of markOopDesc::unlocked_value. + * This value is only valid on SPARC. */ - public final int unlockedMask = getUninitializedInt(); + public int threadJavaFrameAnchorFlagsOffset() { + // TODO add an assert for SPARC + return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset; + } + + @HotSpotVMField(name = "PtrQueue::_active", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset; + @HotSpotVMField(name = "PtrQueue::_buf", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset; + @HotSpotVMField(name = "PtrQueue::_index", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueIndexOffset; + + @HotSpotVMField(name = "OSThread::_interrupted", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadInterruptedOffset; - /** - * The value of markOopDesc::biased_lock_mask_in_place. - */ - public final int biasedLockMaskInPlace = getUninitializedInt(); + @HotSpotVMConstant(name = "markOopDesc::unlocked_value") @Stable public int unlockedMask; + @HotSpotVMConstant(name = "markOopDesc::biased_lock_mask_in_place") @Stable public int biasedLockMaskInPlace; + @HotSpotVMConstant(name = "markOopDesc::age_mask_in_place") @Stable public int ageMaskInPlace; + @HotSpotVMConstant(name = "markOopDesc::epoch_mask_in_place") @Stable public int epochMaskInPlace; + + @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public long markOopDescHashShift; + @HotSpotVMConstant(name = "markOopDesc::hash_mask") @Stable public long markOopDescHashMask; + @HotSpotVMConstant(name = "markOopDesc::hash_mask_in_place") @Stable public long markOopDescHashMaskInPlace; + + @HotSpotVMConstant(name = "markOopDesc::biased_lock_pattern") @Stable public int biasedLockPattern; + @HotSpotVMConstant(name = "markOopDesc::no_hash_in_place") @Stable public int markWordNoHashInPlace; + @HotSpotVMConstant(name = "markOopDesc::no_lock_in_place") @Stable public int markWordNoLockInPlace; /** - * The value of markOopDesc::age_mask_in_place. + * See markOopDesc::prototype(). */ - public final int ageMaskInPlace = getUninitializedInt(); + public long arrayPrototypeMarkWord() { + return markWordNoHashInPlace | markWordNoLockInPlace; + } /** - * The value of markOopDesc::epoch_mask_in_place. - */ - public final int epochMaskInPlace = getUninitializedInt(); - - /** - * The value of markOopDesc::biased_lock_pattern. + * See markOopDesc::copy_set_hash(). */ - public final int biasedLockPattern = getUninitializedInt(); - - /** - * Identity hash code value when uninitialized. - */ - public final int uninitializedIdentityHashCodeValue = getUninitializedInt(); + public long tlabIntArrayMarkWord() { + long tmp = arrayPrototypeMarkWord() & (~markOopDescHashMaskInPlace); + tmp |= ((0x2 & markOopDescHashMask) << markOopDescHashShift); + return tmp; + } /** * Offset of the _pending_exception field in ThreadShadow (defined in exceptions.hpp). This @@ -297,301 +815,344 @@ *

* NOTE: This is not the same as {@link #threadExceptionOopOffset}. */ - public final int pendingExceptionOffset = getUninitializedInt(); - - /** - * Offset of the pending deoptimization field. - */ - public final int pendingDeoptimizationOffset = getUninitializedInt(); + @HotSpotVMField(name = "ThreadShadow::_pending_exception", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset; + @HotSpotVMField(name = "ThreadShadow::_pending_deoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset; /** * Mark word right shift to get identity hash code. */ - public final int identityHashCodeShift = getUninitializedInt(); - - /** - * Offset of _access_flags in a metaspace Method object. - */ - public final int methodAccessFlagsOffset = getUninitializedInt(); - - /** - * JVM_ACC_QUEUED defined in accessFlags.hpp and used for marking a Method object as queued for - * compilation. - */ - public final int methodQueuedForCompilationBit = getUninitializedInt(); + @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public int identityHashCodeShift; /** - * Offset of _intrinsic_id in a metaspace Method object. - */ - public final int methodIntrinsicIdOffset = getUninitializedInt(); - - /** - * Offset of _max_locals in a metaspace Method object. + * Identity hash code value when uninitialized. */ - public final int methodMaxLocalsOffset = getUninitializedInt(); - - /** - * Offset of _constMethod in a metaspace Method object. - */ - public final int methodConstMethodOffset = getUninitializedInt(); + @HotSpotVMConstant(name = "markOopDesc::no_hash") @Stable public int uninitializedIdentityHashCodeValue; /** - * Offset of _max_stack in a metaspace ConstMethod object. + * Used for marking a Method object as queued for compilation. */ - public final int constMethodMaxStackOffset = getUninitializedInt(); + @HotSpotVMConstant(name = "JVM_ACC_QUEUED") @Stable public int methodQueuedForCompilationBit; - /** - * Offset of _constants in a metaspace ConstMethod object. - */ - public final int constMethodConstantsOffset = getUninitializedInt(); + @HotSpotVMField(name = "Method::_access_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset; + @HotSpotVMField(name = "Method::_constMethod", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset; + @HotSpotVMField(name = "Method::_intrinsic_id", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset; + @HotSpotVMField(name = "Method::_vtable_index", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset; /** - * Offset of _pool_holder in a metaspace ConstantPool object. + * Value of Method::extra_stack_entries(). */ - public final int constantPoolHolderOffset = getUninitializedInt(); - - /** - * Value of extra_stack_entries() in method.hpp. - */ - public final int extraStackEntries = getUninitializedInt(); + @Stable public int extraStackEntries; - /** - * Value of JVM_ACC_HAS_FINALIZER in accessFlags.hpp. - */ - public final int klassHasFinalizerFlag = getUninitializedInt(); + @HotSpotVMField(name = "ConstMethod::_max_stack", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodMaxStackOffset; + @HotSpotVMField(name = "ConstMethod::_max_locals", get = HotSpotVMField.Type.OFFSET) @Stable public int methodMaxLocalsOffset; + @HotSpotVMField(name = "ConstMethod::_constants", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodConstantsOffset; - /** - * The value of JavaThread::is_method_handle_return_offset(). - */ - public final int threadIsMethodHandleReturnOffset = getUninitializedInt(); + @HotSpotVMField(name = "ConstantPool::_pool_holder", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolHolderOffset; + @HotSpotVMField(name = "ConstantPool::_length", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolLengthOffset; + + @HotSpotVMConstant(name = "JVM_ACC_HAS_FINALIZER") @Stable public int klassHasFinalizerFlag; /** * Bit pattern that represents a non-oop. Neither the high bits nor the low bits of this value * are allowed to look like (respectively) the high or low bits of a real oop. */ - public final long nonOopBits = getUninitializedLong(); + @HotSpotVMField(name = "Universe::_non_oop_bits", get = HotSpotVMField.Type.VALUE) @Stable public long nonOopBits; + + @HotSpotVMField(name = "StubRoutines::_verify_oop_count", get = HotSpotVMField.Type.ADDRESS) @Stable public long verifyOopCounterAddress; + @Stable public long verifyOopMask; + @Stable public long verifyOopBits; + + @HotSpotVMField(name = "CollectedHeap::_barrier_set", get = HotSpotVMField.Type.OFFSET) @Stable public int collectedHeapBarrierSetOffset; - public final long verifyOopCounterAddress = getUninitializedLong(); - public final long verifyOopMask = getUninitializedLong(); - public final long verifyOopBits = getUninitializedLong(); + @HotSpotVMField(name = "HeapRegion::LogOfHRGrainBytes", get = HotSpotVMField.Type.VALUE) @Stable public int logOfHRGrainBytes; + + @HotSpotVMField(name = "BarrierSet::_kind", get = HotSpotVMField.Type.OFFSET) @Stable public int barrierSetKindOffset; + @HotSpotVMConstant(name = "BarrierSet::CardTableModRef") @Stable public int barrierSetCardTableModRef; + @HotSpotVMConstant(name = "BarrierSet::CardTableExtension") @Stable public int barrierSetCardTableExtension; + @HotSpotVMConstant(name = "BarrierSet::G1SATBCT") @Stable public int barrierSetG1SATBCT; + @HotSpotVMConstant(name = "BarrierSet::G1SATBCTLogging") @Stable public int barrierSetG1SATBCTLogging; + @HotSpotVMConstant(name = "BarrierSet::ModRef") @Stable public int barrierSetModRef; + @HotSpotVMConstant(name = "BarrierSet::Other") @Stable public int barrierSetOther; - /** - * Offset of the _exception_oop field in Thread (defined in thread.hpp). This field is used to - * pass exception objects into and out of the runtime system during exception handling for - * compiled code. - *

- * NOTE: This is not the same as {@link #pendingExceptionOffset}. - */ - public final int threadExceptionOopOffset = getUninitializedInt(); + @HotSpotVMField(name = "CardTableModRefBS::byte_map_base", get = HotSpotVMField.Type.OFFSET) @Stable public int cardTableModRefBSByteMapBaseOffset; + @HotSpotVMConstant(name = "CardTableModRefBS::card_shift") @Stable public int cardTableModRefBSCardShift; + + public long cardtableStartAddress() { + final long barrierSetAddress = unsafe.getAddress(universeCollectedHeap + collectedHeapBarrierSetOffset); + final int kind = unsafe.getInt(barrierSetAddress + barrierSetKindOffset); + if ((kind == barrierSetCardTableModRef) || (kind == barrierSetCardTableExtension) || (kind == barrierSetG1SATBCT) || (kind == barrierSetG1SATBCTLogging)) { + final long base = unsafe.getAddress(barrierSetAddress + cardTableModRefBSByteMapBaseOffset); + assert base != 0 : "unexpected byte_map_base: " + base; + return base; + } + if ((kind == barrierSetModRef) || (kind == barrierSetOther)) { + // No post barriers + return 0; + } + throw GraalInternalError.shouldNotReachHere("kind: " + kind); + } - public final int threadExceptionPcOffset = getUninitializedInt(); - public final long cardtableStartAddress = getUninitializedLong(); - public final int cardtableShift = getUninitializedInt(); - public final long safepointPollingAddress = getUninitializedLong(); - public final boolean isPollingPageFar = getUninitializedBoolean(); + public int cardtableShift() { + final long barrierSetAddress = unsafe.getAddress(universeCollectedHeap + collectedHeapBarrierSetOffset); + final int kind = unsafe.getInt(barrierSetAddress + barrierSetKindOffset); + if ((kind == barrierSetCardTableModRef) || (kind == barrierSetCardTableExtension) || (kind == barrierSetG1SATBCT) || (kind == barrierSetG1SATBCTLogging)) { + return cardTableModRefBSCardShift; + } + if ((kind == barrierSetModRef) || (kind == barrierSetOther)) { + // No post barriers + return 0; + } + throw GraalInternalError.shouldNotReachHere("kind: " + kind); + } + + @HotSpotVMField(name = "os::_polling_page", get = HotSpotVMField.Type.VALUE) @Stable public long safepointPollingAddress; + + // G1 Collector Related Values. - /** - * G1 Collector Related Values. - */ - public final int g1CardQueueIndexOffset = getUninitializedInt(); - public final int g1CardQueueBufferOffset = getUninitializedInt(); - public final int logOfHRGrainBytes = getUninitializedInt(); - public final int g1SATBQueueMarkingOffset = getUninitializedInt(); - public final int g1SATBQueueIndexOffset = getUninitializedInt(); - public final int g1SATBQueueBufferOffset = getUninitializedInt(); + public int g1CardQueueIndexOffset() { + return javaThreadDirtyCardQueueOffset + ptrQueueIndexOffset; + } + + public int g1CardQueueBufferOffset() { + return javaThreadDirtyCardQueueOffset + ptrQueueBufferOffset; + } + + public int g1SATBQueueMarkingOffset() { + return javaThreadSatbMarkQueueOffset + ptrQueueActiveOffset; + } + + public int g1SATBQueueIndexOffset() { + return javaThreadSatbMarkQueueOffset + ptrQueueIndexOffset; + } + + public int g1SATBQueueBufferOffset() { + return javaThreadSatbMarkQueueOffset + ptrQueueBufferOffset; + } /** * The offset of the _java_mirror field (of type {@link Class}) in a Klass. */ - public final int classMirrorOffset = getUninitializedInt(); - - public final int runtimeCallStackSize = getUninitializedInt(); + @HotSpotVMField(name = "Klass::_java_mirror", get = HotSpotVMField.Type.OFFSET) @Stable public int classMirrorOffset; - /** - * The offset of the _modifier_flags field in a Klass. - */ - public final int klassModifierFlagsOffset = getUninitializedInt(); + @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", optional = true) @Stable public int runtimeCallStackSize; - /** - * The offset of the _access_flags field in a Klass. - */ - public final int klassAccessFlagsOffset = getUninitializedInt(); - - /** - * The offset of the _layout_helper field in a Klass. - */ - public final int klassLayoutHelperOffset = getUninitializedInt(); + @HotSpotVMField(name = "Klass::_super", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSuperKlassOffset; + @HotSpotVMField(name = "Klass::_modifier_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassModifierFlagsOffset; + @HotSpotVMField(name = "Klass::_access_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassAccessFlagsOffset; + @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int klassLayoutHelperOffset; + @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int klassInstanceSizeOffset; /** * Bit pattern in the klass layout helper that can be used to identify arrays. */ - public final int arrayKlassLayoutHelperIdentifier = getUninitializedInt(); + public final int arrayKlassLayoutHelperIdentifier = 0x80000000; + + @HotSpotVMField(name = "ArrayKlass::_component_mirror", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayKlassComponentMirrorOffset; + + @HotSpotVMField(name = "java_lang_Class::_klass_offset", get = HotSpotVMField.Type.VALUE) @Stable public int klassOffset; + @HotSpotVMField(name = "java_lang_Class::_array_klass_offset", get = HotSpotVMField.Type.VALUE) @Stable public int arrayKlassOffset; + @HotSpotVMField(name = "java_lang_Class::_graal_mirror_offset", get = HotSpotVMField.Type.VALUE) @Stable public int graalMirrorInClassOffset; + + @HotSpotVMField(name = "Method::_method_data", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOffset; + @HotSpotVMField(name = "Method::_from_compiled_entry", get = HotSpotVMField.Type.OFFSET) @Stable public int methodCompiledEntryOffset; + + @HotSpotVMField(name = "nmethod::_verified_entry_point", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset; + + @HotSpotVMType(name = "BasicLock", get = HotSpotVMType.Type.SIZE) @Stable public int basicLockSize; + @HotSpotVMField(name = "BasicLock::_displaced_header", get = HotSpotVMField.Type.OFFSET) @Stable public int basicLockDisplacedHeaderOffset; - /** - * The offset of the _componentMirror field in an ArrayKlass. - */ - public final int arrayKlassComponentMirrorOffset = getUninitializedInt(); + @Stable public long heapEndAddress; + @Stable public long heapTopAddress; + + @HotSpotVMField(name = "Thread::_allocated_bytes", get = HotSpotVMField.Type.OFFSET) @Stable public int threadAllocatedBytesOffset; + + @HotSpotVMFlag(name = "TLABWasteIncrement") @Stable public int tlabRefillWasteIncrement; + @Stable public int tlabAlignmentReserve; + + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferStartOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferEndOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_top", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferTopOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_slow_allocations", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferSlowAllocationsOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_fast_refill_waste", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferFastRefillWasteOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_number_of_refills", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferNumberOfRefillsOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_refill_waste_limit", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferRefillWasteLimitOffset; + @HotSpotVMField(name = "ThreadLocalAllocBuffer::_desired_size", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferDesiredSizeOffset; + + public int tlabSlowAllocationsOffset() { + return threadTlabOffset + threadLocalAllocBufferSlowAllocationsOffset; + } - /** - * The offset of the _super field in a Klass. - */ - public final int klassSuperKlassOffset = getUninitializedInt(); + public int tlabFastRefillWasteOffset() { + return threadTlabOffset + threadLocalAllocBufferFastRefillWasteOffset; + } + + public int tlabNumberOfRefillsOffset() { + return threadTlabOffset + threadLocalAllocBufferNumberOfRefillsOffset; + } + + public int tlabRefillWasteLimitOffset() { + return threadTlabOffset + threadLocalAllocBufferRefillWasteLimitOffset; + } + + public int threadTlabSizeOffset() { + return threadTlabOffset + threadLocalAllocBufferDesiredSizeOffset; + } + + public int threadTlabStartOffset() { + return threadTlabOffset + threadLocalAllocBufferStartOffset; + } - /** - * The offset of the injected klass field in a {@link Class}. - */ - public final int klassOffset = getUninitializedInt(); + public int threadTlabEndOffset() { + return threadTlabOffset + threadLocalAllocBufferEndOffset; + } + + public int threadTlabTopOffset() { + return threadTlabOffset + threadLocalAllocBufferTopOffset; + } + + @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats; + @Stable public boolean inlineContiguousAllocationSupported; - /** - * The offset of the injected array klass field in a {@link Class}. - */ - public final int arrayKlassOffset = getUninitializedInt(); + @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int layoutHelperOffset; + @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_shift") @Stable public int layoutHelperLog2ElementSizeShift; + @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_mask") @Stable public int layoutHelperLog2ElementSizeMask; + @HotSpotVMConstant(name = "Klass::_lh_element_type_shift") @Stable public int layoutHelperElementTypeShift; + @HotSpotVMConstant(name = "Klass::_lh_element_type_mask") @Stable public int layoutHelperElementTypeMask; + @HotSpotVMConstant(name = "Klass::_lh_header_size_shift") @Stable public int layoutHelperHeaderSizeShift; + @HotSpotVMConstant(name = "Klass::_lh_header_size_mask") @Stable public int layoutHelperHeaderSizeMask; + @HotSpotVMConstant(name = "Klass::_lh_array_tag_shift") @Stable public int layoutHelperArrayTagShift; + @HotSpotVMConstant(name = "Klass::_lh_array_tag_type_value") @Stable public int layoutHelperArrayTagTypeValue; + @HotSpotVMConstant(name = "Klass::_lh_array_tag_obj_value") @Stable public int layoutHelperArrayTagObjectValue; /** - * The offset of the injected graal_mirror field in a {@link Class}. + * This filters out the bit that differentiates a type array from an object array. */ - public final int graalMirrorInClassOffset = getUninitializedInt(); - - /** - * The offset of the _method_data field in a metaspace Method. - */ - public final int methodDataOffset = getUninitializedInt(); + public int layoutHelperElementTypePrimitiveInPlace() { + return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift; + } - public final int nmethodEntryOffset = getUninitializedInt(); - public final int methodCompiledEntryOffset = getUninitializedInt(); - public final int basicLockSize = getUninitializedInt(); - public final int basicLockDisplacedHeaderOffset = getUninitializedInt(); - public final long tlabIntArrayMarkWord = getUninitializedLong(); - public final long heapEndAddress = getUninitializedLong(); - public final long heapTopAddress = getUninitializedLong(); - public final int threadTlabStartOffset = getUninitializedInt(); - public final int threadTlabSizeOffset = getUninitializedInt(); - public final int threadAllocatedBytesOffset = getUninitializedInt(); - public final int threadLastJavaSpOffset = getUninitializedInt(); - public final int threadLastJavaPcOffset = getUninitializedInt(); - - /** - * This value is only valid on AMD64. - */ - public final int threadLastJavaFpOffset = getUninitializedInt(); + @HotSpotVMField(name = "MethodData::_data[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopDataOffset; + @HotSpotVMField(name = "MethodData::_trap_hist._array[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopTrapHistoryOffset; /** - * This value is only valid on SPARC. + * The DataLayout header size is the same as the cell size. */ - public final int threadJavaFrameAnchorFlagsOffset = getUninitializedInt(); + @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutHeaderSize; + @HotSpotVMField(name = "DataLayout::_header._struct._tag", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutTagOffset; + @HotSpotVMField(name = "DataLayout::_header._struct._flags", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutFlagsOffset; + @HotSpotVMField(name = "DataLayout::_header._struct._bci", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutBCIOffset; + @HotSpotVMField(name = "DataLayout::_cells[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutCellsOffset; + @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutCellSize; - public final int threadObjectResultOffset = getUninitializedInt(); - public final int tlabRefillWasteLimitOffset = getUninitializedInt(); - public final int tlabRefillWasteIncrement = getUninitializedInt(); - public final int tlabAlignmentReserve = getUninitializedInt(); - public final int tlabSlowAllocationsOffset = getUninitializedInt(); - public final int tlabFastRefillWasteOffset = getUninitializedInt(); - public final int tlabNumberOfRefillsOffset = getUninitializedInt(); - public final boolean tlabStats = getVMOption("TLABStats"); - public final int klassInstanceSizeOffset = getUninitializedInt(); - public final boolean inlineContiguousAllocationSupported = getUninitializedBoolean(); - public final long arrayPrototypeMarkWord = getUninitializedLong(); - public final int layoutHelperLog2ElementSizeShift = getUninitializedInt(); - public final int layoutHelperLog2ElementSizeMask = getUninitializedInt(); - public final int layoutHelperElementTypeShift = getUninitializedInt(); - public final int layoutHelperElementTypeMask = getUninitializedInt(); - public final int layoutHelperElementTypePrimitiveInPlace = getUninitializedInt(); - public final int layoutHelperHeaderSizeShift = getUninitializedInt(); - public final int layoutHelperHeaderSizeMask = getUninitializedInt(); - public final int layoutHelperOffset = getUninitializedInt(); + @HotSpotVMFlag(name = "BciProfileWidth") @Stable public int bciProfileWidth; + @HotSpotVMFlag(name = "TypeProfileWidth") @Stable public int typeProfileWidth; + @HotSpotVMFlag(name = "MethodProfileWidth") @Stable public int methodProfileWidth; + + @HotSpotVMField(name = "CodeBlob::_code_offset", get = HotSpotVMField.Type.OFFSET) @Stable private int codeBlobCodeOffsetOffset; + @HotSpotVMField(name = "SharedRuntime::_ic_miss_blob", get = HotSpotVMField.Type.VALUE) @Stable private long inlineCacheMissBlob; + + public long inlineCacheMissStub() { + return inlineCacheMissBlob + unsafe.getInt(inlineCacheMissBlob + codeBlobCodeOffsetOffset); + } - // methodData information - public final int methodDataOopDataOffset = getUninitializedInt(); - public final int methodDataOopTrapHistoryOffset = getUninitializedInt(); - public final int dataLayoutHeaderSize = getUninitializedInt(); - public final int dataLayoutTagOffset = getUninitializedInt(); - public final int dataLayoutFlagsOffset = getUninitializedInt(); - public final int dataLayoutBCIOffset = getUninitializedInt(); - public final int dataLayoutCellsOffset = getUninitializedInt(); - public final int dataLayoutCellSize = getUninitializedInt(); + @HotSpotVMField(name = "CodeCache::_heap", get = HotSpotVMField.Type.VALUE) @Stable private long codeCacheHeap; + @HotSpotVMField(name = "CodeHeap::_memory", get = HotSpotVMField.Type.OFFSET) @Stable private int codeHeapMemoryOffset; + @HotSpotVMField(name = "VirtualSpace::_low_boundary", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceLowBoundaryOffset; + @HotSpotVMField(name = "VirtualSpace::_high_boundary", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceHighBoundaryOffset; - // develop flag; might change - public final int bciProfileWidth = getVMOption("BciProfileWidth", 2); + /** + * @return CodeCache::_heap->_memory._low_boundary + */ + public long codeCacheLowBoundary() { + return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceLowBoundaryOffset); + } - public final int typeProfileWidth = getVMOptionInt("TypeProfileWidth"); - public final int methodProfileWidth = getVMOptionInt("MethodProfileWidth"); + /** + * @return CodeCache::_heap->_memory._high_boundary + */ + public long codeCacheHighBoundary() { + return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceHighBoundaryOffset); + } - public final long inlineCacheMissStub = getUninitializedLong(); - public final long handleDeoptStub = getUninitializedLong(); - public final long uncommonTrapStub = getUninitializedLong(); + @Stable public long handleDeoptStub; + @Stable public long uncommonTrapStub; - public final long aescryptEncryptBlockStub = getUninitializedLong(); - public final long aescryptDecryptBlockStub = getUninitializedLong(); - public final long cipherBlockChainingEncryptAESCryptStub = getUninitializedLong(); - public final long cipherBlockChainingDecryptAESCryptStub = getUninitializedLong(); - public final long updateBytesCRC32Stub = getUninitializedLong(); + @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub; + @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub; + @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_encryptAESCrypt", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingEncryptAESCryptStub; + @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_decryptAESCrypt", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingDecryptAESCryptStub; + @HotSpotVMField(name = "StubRoutines::_updateBytesCRC32", get = HotSpotVMField.Type.VALUE) @Stable public long updateBytesCRC32Stub; + @HotSpotVMField(name = "StubRoutines::_crc_table_adr", get = HotSpotVMField.Type.VALUE) @Stable public long crcTableAddress; - public final long newInstanceAddress = getUninitializedLong(); - public final long newArrayAddress = getUninitializedLong(); - public final long newMultiArrayAddress = getUninitializedLong(); - public final long dynamicNewArrayAddress = getUninitializedLong(); - public final long registerFinalizerAddress = getUninitializedLong(); - public final long threadIsInterruptedAddress = getUninitializedLong(); - public final long vmMessageAddress = getUninitializedLong(); - public final long identityHashCodeAddress = getUninitializedLong(); - public final long exceptionHandlerForPcAddress = getUninitializedLong(); - public final long exceptionHandlerForReturnAddressAddress = getUninitializedLong(); - public final long osrMigrationEndAddress = getUninitializedLong(); - public final long monitorenterAddress = getUninitializedLong(); - public final long monitorexitAddress = getUninitializedLong(); - public final long createNullPointerExceptionAddress = getUninitializedLong(); - public final long createOutOfBoundsExceptionAddress = getUninitializedLong(); - public final long logPrimitiveAddress = getUninitializedLong(); - public final long logObjectAddress = getUninitializedLong(); - public final long logPrintfAddress = getUninitializedLong(); - public final long vmErrorAddress = getUninitializedLong(); - public final long writeBarrierPreAddress = getUninitializedLong(); - public final long writeBarrierPostAddress = getUninitializedLong(); - public final long validateObject = getUninitializedLong(); - public final long javaTimeMillisAddress = getUninitializedLong(); - public final long javaTimeNanosAddress = getUninitializedLong(); - public final long arithmeticSinAddress = getUninitializedLong(); - public final long arithmeticCosAddress = getUninitializedLong(); - public final long arithmeticTanAddress = getUninitializedLong(); - public final long loadAndClearExceptionAddress = getUninitializedLong(); - public final long crcTableAddress = getUninitializedLong(); + @Stable public long newInstanceAddress; + @Stable public long newArrayAddress; + @Stable public long newMultiArrayAddress; + @Stable public long dynamicNewArrayAddress; + @Stable public long registerFinalizerAddress; + @Stable public long threadIsInterruptedAddress; + @Stable public long vmMessageAddress; + @Stable public long identityHashCodeAddress; + @Stable public long exceptionHandlerForPcAddress; + @Stable public long exceptionHandlerForReturnAddressAddress; + @Stable public long osrMigrationEndAddress; + @Stable public long monitorenterAddress; + @Stable public long monitorexitAddress; + @Stable public long createNullPointerExceptionAddress; + @Stable public long createOutOfBoundsExceptionAddress; + @Stable public long logPrimitiveAddress; + @Stable public long logObjectAddress; + @Stable public long logPrintfAddress; + @Stable public long vmErrorAddress; + @Stable public long writeBarrierPreAddress; + @Stable public long writeBarrierPostAddress; + @Stable public long validateObject; + @Stable public long javaTimeMillisAddress; + @Stable public long javaTimeNanosAddress; + @Stable public long arithmeticSinAddress; + @Stable public long arithmeticCosAddress; + @Stable public long arithmeticTanAddress; + @Stable public long loadAndClearExceptionAddress; - public final int deoptReasonNone = getUninitializedInt(); - public final int deoptReasonNullCheck = getUninitializedInt(); - public final int deoptReasonRangeCheck = getUninitializedInt(); - public final int deoptReasonClassCheck = getUninitializedInt(); - public final int deoptReasonArrayCheck = getUninitializedInt(); - public final int deoptReasonUnreached0 = getUninitializedInt(); - public final int deoptReasonTypeCheckInlining = getUninitializedInt(); - public final int deoptReasonOptimizedTypeCheck = getUninitializedInt(); - public final int deoptReasonNotCompiledExceptionHandler = getUninitializedInt(); - public final int deoptReasonUnresolved = getUninitializedInt(); - public final int deoptReasonJsrMismatch = getUninitializedInt(); - public final int deoptReasonDiv0Check = getUninitializedInt(); - public final int deoptReasonConstraint = getUninitializedInt(); - public final int deoptReasonLoopLimitCheck = getUninitializedInt(); + @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone; + @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_class_check") @Stable public int deoptReasonClassCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_array_check") @Stable public int deoptReasonArrayCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_null_assert") @Stable public int deoptReasonUnreached0; + @HotSpotVMConstant(name = "Deoptimization::Reason_intrinsic") @Stable public int deoptReasonTypeCheckInlining; + @HotSpotVMConstant(name = "Deoptimization::Reason_bimorphic") @Stable public int deoptReasonOptimizedTypeCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_unhandled") @Stable public int deoptReasonNotCompiledExceptionHandler; + @HotSpotVMConstant(name = "Deoptimization::Reason_uninitialized") @Stable public int deoptReasonUnresolved; + @HotSpotVMConstant(name = "Deoptimization::Reason_age") @Stable public int deoptReasonJsrMismatch; + @HotSpotVMConstant(name = "Deoptimization::Reason_div0_check") @Stable public int deoptReasonDiv0Check; + @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint; + @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck; - public final int deoptActionNone = getUninitializedInt(); - public final int deoptActionMaybeRecompile = getUninitializedInt(); - public final int deoptActionReinterpret = getUninitializedInt(); - public final int deoptActionMakeNotEntrant = getUninitializedInt(); - public final int deoptActionMakeNotCompilable = getUninitializedInt(); + @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone; + @HotSpotVMConstant(name = "Deoptimization::Action_maybe_recompile") @Stable public int deoptActionMaybeRecompile; + @HotSpotVMConstant(name = "Deoptimization::Action_reinterpret") @Stable public int deoptActionReinterpret; + @HotSpotVMConstant(name = "Deoptimization::Action_make_not_entrant") @Stable public int deoptActionMakeNotEntrant; + @HotSpotVMConstant(name = "Deoptimization::Action_make_not_compilable") @Stable public int deoptActionMakeNotCompilable; - public final int vmIntrinsicInvokeBasic = getUninitializedInt(); - public final int vmIntrinsicLinkToVirtual = getUninitializedInt(); - public final int vmIntrinsicLinkToStatic = getUninitializedInt(); - public final int vmIntrinsicLinkToSpecial = getUninitializedInt(); - public final int vmIntrinsicLinkToInterface = getUninitializedInt(); + @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic; + @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual; + @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic; + @HotSpotVMConstant(name = "vmIntrinsics::_linkToSpecial") @Stable public int vmIntrinsicLinkToSpecial; + @HotSpotVMConstant(name = "vmIntrinsics::_linkToInterface") @Stable public int vmIntrinsicLinkToInterface; public boolean check() { - assert codeEntryAlignment > 0 : codeEntryAlignment; - assert stackShadowPages > 0; for (Field f : getClass().getDeclaredFields()) { int modifiers = f.getModifiers(); if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) { - assert Modifier.isFinal(modifiers) : "field should be final: " + f; + assert Modifier.isFinal(modifiers) || f.getAnnotation(Stable.class) != null : "field should either be final or @Stable: " + f; } } + + assert codeEntryAlignment > 0 : codeEntryAlignment; + assert stackShadowPages > 0 : stackShadowPages; + + assert (layoutHelperArrayTagObjectValue & layoutHelperArrayTagTypeValue & arrayKlassLayoutHelperIdentifier) != 0 : "object array and type array must have first bit set"; + return true; } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConstant.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConstant.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface HotSpotVMConstant { + + String name(); + + boolean optional() default false; +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMField.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface HotSpotVMField { + + enum Type { + OFFSET, ADDRESS, VALUE; + } + + String name(); + + Type get(); + + boolean optional() default false; +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface HotSpotVMFlag { + + String name(); + + boolean optional() default false; +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMType.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface HotSpotVMType { + + enum Type { + SIZE; + } + + String name(); + + Type get(); +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Stable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Stable.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.hotspot; + +import java.lang.annotation.*; + +// TODO remove this annotation after we moved to JDK 8 and use sun.invoke.Stable instead + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stable { +} diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Oct 25 01:39:54 2013 +0200 @@ -120,8 +120,6 @@ */ JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve); - int constantPoolLength(HotSpotResolvedObjectType pool); - Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi); JavaMethod lookupMethodInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); @@ -202,10 +200,6 @@ Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; - int getVtableEntryOffset(long metaspaceMethod); - - boolean hasVtableEntry(long metaspaceMethod); - long[] getDeoptedLeafGraphIds(); long[] getLineNumberTable(HotSpotResolvedJavaMethod method); @@ -218,6 +212,8 @@ long readUnsafeKlassPointer(Object o); + void doNotInlineOrCompile(long metaspaceMethod); + /** * Invalidates the profiling information and restarts profiling upon the next invocation. * diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Oct 25 01:39:54 2013 +0200 @@ -76,9 +76,6 @@ public native JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve); @Override - public native int constantPoolLength(HotSpotResolvedObjectType pool); - - @Override public native Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi); @Override @@ -145,12 +142,6 @@ public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode); @Override - public native int getVtableEntryOffset(long metaspaceMethod); - - @Override - public native boolean hasVtableEntry(long metaspaceMethod); - - @Override public native long[] getDeoptedLeafGraphIds(); @Override @@ -178,6 +169,9 @@ public native long readUnsafeKlassPointer(Object o); @Override + public native void doNotInlineOrCompile(long metaspaceMethod); + + @Override public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException { return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Oct 25 01:39:54 2013 +0200 @@ -401,7 +401,7 @@ CompilationTask.withinEnqueue.set(Boolean.FALSE); } - if (Debug.isEnabled() && areDebugScopePatternsEnabled()) { + if (Debug.isEnabled() && areMetricsOrTimersEnabled()) { List topLevelMaps = DebugValueMap.getTopLevelMaps(); List debugValues = KeyRegistry.getDebugValues(); if (debugValues.size() > 0) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Fri Oct 25 01:39:54 2013 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.printer.*; /** @@ -157,7 +158,7 @@ } public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) { - HotSpotInstalledCode installedCode = new HotSpotNmethod(method, true); + HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), true); runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, entryBCI, compResult), installedCode, method.getSpeculationLog()); return installedCode; } @@ -165,7 +166,7 @@ @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, false); + HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(hotspotMethod, -1, compResult), code, null); if (result != CodeInstallResult.OK) { return null; @@ -173,10 +174,15 @@ return code; } + public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) { + HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; + return installMethod(hotspotMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult); + } + public InstalledCode addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) { HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode icode = new HotSpotNmethod(javaMethod, false, true); + HotSpotInstalledCode icode = new HotSpotNmethod(javaMethod, compResult.getName(), false, true); HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, -1, compResult); CompilerToVM vm = runtime.getCompilerToVM(); CodeInstallResult result = vm.installCode(compiled, icode, null); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Oct 25 01:39:54 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.meta.*; @@ -43,7 +44,9 @@ @Override public int length() { - return runtime().getCompilerToVM().constantPoolLength(type); + HotSpotVMConfig config = runtime().getConfig(); + long constantPoolAddress = unsafe.getAddress(type.metaspaceKlass() + config.instanceKlassConstantsOffset); + return unsafe.getInt(constantPoolAddress + config.constantPoolLengthOffset); } @Override diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Oct 25 01:39:54 2013 +0200 @@ -164,7 +164,7 @@ registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Fri Oct 25 01:39:54 2013 +0200 @@ -46,17 +46,17 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; private final boolean isExternal; + private final String name; - public HotSpotNmethod(HotSpotResolvedJavaMethod method, boolean isDefault) { - this.method = method; - this.isDefault = isDefault; - this.isExternal = false; + public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) { + this(method, name, isDefault, false); } - public HotSpotNmethod(HotSpotResolvedJavaMethod method, boolean isDefault, boolean isExternal) { + public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) { this.method = method; this.isDefault = isDefault; this.isExternal = isExternal; + this.name = name; } public boolean isDefault() { @@ -84,7 +84,7 @@ @Override public String toString() { - return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b]", method, getCodeBlob(), isDefault); + return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=]", method, getCodeBlob(), isDefault, name); } @Override diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Fri Oct 25 01:39:54 2013 +0200 @@ -199,6 +199,11 @@ if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { return value; } + } else if (isStable()) { + Constant value = readValue(receiver); + if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { + return value; + } } else { Class clazz = object.getClass(); if (StableOptionValue.class.isAssignableFrom(clazz)) { @@ -229,6 +234,20 @@ return clazz == SnippetCounter.class; } + /** + * Usually {@link Stable} fields are not considered constant if the value is the + * {@link Constant#isDefaultForKind default value}. For some special classes we want to override + * this behavior. + */ + private static boolean assumeDefaultStableFieldsAsFinal(Class clazz) { + // HotSpotVMConfig has a lot of zero-value fields which we know are stable and want to be + // considered as constants. + if (clazz == HotSpotVMConfig.class) { + return true; + } + return false; + } + @Override public HotSpotResolvedObjectType getDeclaringClass() { return holder; @@ -267,6 +286,16 @@ return false; } + /** + * Checks if this field has the {@link Stable} annotation. + * + * @return true if field has {@link Stable} annotation, false otherwise + */ + public boolean isStable() { + Annotation annotation = getAnnotation(Stable.class); + return annotation != null; + } + @Override public T getAnnotation(Class annotationClass) { Field javaField = toJava(); diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Oct 25 01:39:54 2013 +0200 @@ -190,6 +190,14 @@ } /** + * Manually adds a DontInline annotation to this method. + */ + public void setDontInline() { + dontInline = true; + runtime().getCompilerToVM().doNotInlineOrCompile(metaspaceMethod); + } + + /** * Returns true if this method is one of the special methods that is ignored by security stack * walks. * @@ -440,7 +448,7 @@ } /** - * Returns the offset of this method into the v-table. The method must have a v-table entry has + * Returns the offset of this method into the v-table. The method must have a v-table entry as * indicated by {@link #isInVirtualMethodTable()}, otherwise an exception is thrown. * * @return the offset of this method into the v-table @@ -449,12 +457,19 @@ if (!isInVirtualMethodTable() || !holder.isInitialized()) { throw new GraalInternalError("%s does not have a vtable entry", this); } - return runtime().getCompilerToVM().getVtableEntryOffset(metaspaceMethod); + HotSpotVMConfig config = runtime().getConfig(); + final int vtableIndex = getVtableIndex(); + return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset; } @Override public boolean isInVirtualMethodTable() { - return runtime().getCompilerToVM().hasVtableEntry(metaspaceMethod); + return getVtableIndex() >= 0; + } + + private int getVtableIndex() { + HotSpotVMConfig config = runtime().getConfig(); + return unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset); } public void setCurrentTask(CompilationTask task) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Oct 25 01:39:54 2013 +0200 @@ -488,6 +488,13 @@ return Constant.forIntegerKind(runtime().getTarget().wordKind, metaspaceKlass, this); } + /** + * Gets the address of the C++ Klass object for this type. + */ + public long metaspaceKlass() { + return metaspaceKlass; + } + public boolean isPrimaryType() { return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset(); } @@ -500,7 +507,7 @@ public long prototypeMarkWord() { HotSpotVMConfig config = runtime().getConfig(); if (isArray()) { - return config.arrayPrototypeMarkWord; + return config.arrayPrototypeMarkWord(); } else { return unsafeReadWord(metaspaceKlass + config.prototypeMarkWordOffset); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -39,7 +39,9 @@ @Override protected boolean verify(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) { - assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node; + if (node.recordsUsages() || !node.gatherUsages().isEmpty()) { + assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node; + } } return true; } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -68,7 +68,7 @@ LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph)); FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); - graph.replaceFloating(node, freadNode); + node.replace(freadNode); } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Fri Oct 25 01:39:54 2013 +0200 @@ -66,7 +66,7 @@ } private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) { - Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object); + Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object, LocationIdentity.ANY_LOCATION); Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte)); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Oct 25 01:39:54 2013 +0200 @@ -78,9 +78,6 @@ return arraycopyMethods.get(kind); } - private static final Kind VECTOR_KIND = Kind.Long; - private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); - private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { Object nonNullSrc = guardingNonNull(src); Object nonNullDest = guardingNonNull(dest); @@ -88,32 +85,32 @@ UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, baseKind); } - public static int checkArrayType(Word hub) { + private static int checkArrayType(Word hub) { int layoutHelper = readLayoutHelper(hub); - if (layoutHelper >= 0) { + if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return layoutHelper; } - public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { - if (srcPos < 0) { + private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { + if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) { checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (destPos < 0) { + if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) { checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (length < 0) { + if (probability(SLOW_PATH_PROBABILITY, length < 0)) { checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (srcPos + length > ArrayLengthNode.arrayLength(src)) { + if (probability(SLOW_PATH_PROBABILITY, srcPos + length > ArrayLengthNode.arrayLength(src))) { checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (destPos + length > ArrayLengthNode.arrayLength(dest)) { + if (probability(SLOW_PATH_PROBABILITY, destPos + length > ArrayLengthNode.arrayLength(dest))) { checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } @@ -170,12 +167,6 @@ @Snippet public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { - arrayObjectCopy(src, srcPos, dest, destPos, length); - } - - // Does NOT perform store checks - @Snippet - public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) { objectCounter.inc(); checkedCopy(src, srcPos, dest, destPos, length, Kind.Object); } @@ -193,7 +184,7 @@ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { genericObjectExactCallCounter.inc(); - arrayObjectCopy(nonNullSrc, srcPos, nonNullDest, destPos, length); + UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, Kind.Object); } else { genericPrimitiveCallCounter.inc(); UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Fri Oct 25 01:39:54 2013 +0200 @@ -62,7 +62,7 @@ @MethodSubstitution(isStatic = false) static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { - Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object); + Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION); if (getAESCryptClass().isInstance(embeddedCipher)) { crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true); } else { @@ -72,7 +72,7 @@ @MethodSubstitution(isStatic = false) static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { - Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object); + Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false); } else { @@ -81,8 +81,8 @@ } private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) { - Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object); - Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object); + Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object, LocationIdentity.ANY_LOCATION); + Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object, LocationIdentity.ANY_LOCATION); Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte)); Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte)); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Oct 25 01:39:54 2013 +0200 @@ -81,21 +81,21 @@ @Fold public static int threadTlabTopOffset() { - return config().threadTlabTopOffset; + return config().threadTlabTopOffset(); } public static final LocationIdentity TLAB_END_LOCATION = new NamedLocationIdentity("TlabEnd"); @Fold private static int threadTlabEndOffset() { - return config().threadTlabEndOffset; + return config().threadTlabEndOffset(); } public static final LocationIdentity TLAB_START_LOCATION = new NamedLocationIdentity("TlabStart"); @Fold private static int threadTlabStartOffset() { - return config().threadTlabStartOffset; + return config().threadTlabStartOffset(); } public static final LocationIdentity PENDING_EXCEPTION_LOCATION = new NamedLocationIdentity("PendingException"); @@ -230,7 +230,7 @@ @Fold public static long arrayPrototypeMarkWord() { - return config().arrayPrototypeMarkWord; + return config().arrayPrototypeMarkWord(); } @Fold @@ -358,22 +358,22 @@ @Fold public static int cardTableShift() { - return config().cardtableShift; + return config().cardtableShift(); } @Fold public static long cardTableStart() { - return config().cardtableStartAddress; + return config().cardtableStartAddress(); } @Fold public static int g1CardQueueIndexOffset() { - return config().g1CardQueueIndexOffset; + return config().g1CardQueueIndexOffset(); } @Fold public static int g1CardQueueBufferOffset() { - return config().g1CardQueueBufferOffset; + return config().g1CardQueueBufferOffset(); } @Fold @@ -383,17 +383,17 @@ @Fold public static int g1SATBQueueMarkingOffset() { - return config().g1SATBQueueMarkingOffset; + return config().g1SATBQueueMarkingOffset(); } @Fold public static int g1SATBQueueIndexOffset() { - return config().g1SATBQueueIndexOffset; + return config().g1SATBQueueIndexOffset(); } @Fold public static int g1SATBQueueBufferOffset() { - return config().g1SATBQueueBufferOffset; + return config().g1SATBQueueBufferOffset(); } @Fold @@ -485,7 +485,7 @@ public static Word loadWordFromObject(Object object, int offset) { assert offset != hubOffset() : "Use loadHubIntrinsic instead"; - return loadWordFromObjectIntrinsic(object, offset, getWordKind()); + return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.ANY_LOCATION); } @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) @@ -493,7 +493,7 @@ @SuppressWarnings("unused") @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind) { + private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) { return Word.unsigned(unsafeReadWord(object, offset)); } @@ -561,7 +561,7 @@ @Fold public static long tlabIntArrayMarkWord() { - return config().tlabIntArrayMarkWord; + return config().tlabIntArrayMarkWord(); } @Fold @@ -578,7 +578,7 @@ @Fold public static int threadTlabSizeOffset() { - return config().threadTlabSizeOffset; + return config().threadTlabSizeOffset(); } public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = new NamedLocationIdentity("TlabThreadAllocatedBytes"); @@ -592,28 +592,28 @@ @Fold public static int tlabRefillWasteLimitOffset() { - return config().tlabRefillWasteLimitOffset; + return config().tlabRefillWasteLimitOffset(); } public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = new NamedLocationIdentity("TlabNOfRefills"); @Fold public static int tlabNumberOfRefillsOffset() { - return config().tlabNumberOfRefillsOffset; + return config().tlabNumberOfRefillsOffset(); } public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = new NamedLocationIdentity("TlabFastRefillWaste"); @Fold public static int tlabFastRefillWasteOffset() { - return config().tlabFastRefillWasteOffset; + return config().tlabFastRefillWasteOffset(); } public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = new NamedLocationIdentity("TlabSlowAllocations"); @Fold public static int tlabSlowAllocationsOffset() { - return config().tlabSlowAllocationsOffset; + return config().tlabSlowAllocationsOffset(); } @Fold @@ -663,7 +663,7 @@ @Fold public static int layoutHelperElementTypePrimitiveInPlace() { - return config().layoutHelperElementTypePrimitiveInPlace; + return config().layoutHelperElementTypePrimitiveInPlace(); } static { @@ -705,7 +705,7 @@ @Fold public static long gcTotalCollectionsAddress() { - return config().gcTotalCollectionsAddress; + return config().gcTotalCollectionsAddress(); } @Fold diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -112,6 +112,9 @@ @Override public LocationIdentity getLocationIdentity() { + if (elementKind != null) { + return NamedLocationIdentity.getArrayLocation(elementKind); + } return ANY_LOCATION; } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Fri Oct 25 01:39:54 2013 +0200 @@ -34,20 +34,24 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; -import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; +/** + * As opposed to {@link ArrayCopySnippets}, these Snippets do not perform store checks. + */ public class UnsafeArrayCopySnippets implements Snippets { private static final boolean supportsUnalignedMemoryAccess = runtime().getTarget().arch.supportsUnalignedMemoryAccess(); + // TODO: make vector kind architecture dependent private static final Kind VECTOR_KIND = Kind.Long; - private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); + private static final long VECTOR_SIZE = arrayIndexScale(VECTOR_KIND); - private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { + private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind, LocationIdentity locationIdentity) { int arrayBaseOffset = arrayBaseOffset(baseKind); int elementSize = arrayIndexScale(baseKind); long byteLength = (long) length * elementSize; @@ -86,143 +90,101 @@ for (long i = 0; i < postLoopBytes; i += elementSize) { srcOffset -= elementSize; destOffset -= elementSize; - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind); + Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); } // Main-loop for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) { srcOffset -= VECTOR_SIZE; destOffset -= VECTOR_SIZE; - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND); + Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND, locationIdentity); } // Pre-loop for (long i = 0; i < preLoopBytes; i += elementSize) { srcOffset -= elementSize; destOffset -= elementSize; - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind); + Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); } } else { // Pre-loop for (long i = 0; i < preLoopBytes; i += elementSize) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind); + Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); srcOffset += elementSize; destOffset += elementSize; } // Main-loop for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) { - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND); + Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND, locationIdentity); srcOffset += VECTOR_SIZE; destOffset += VECTOR_SIZE; } // Post-loop for (long i = 0; i < postLoopBytes; i += elementSize) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind); + Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); + UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); srcOffset += elementSize; destOffset += elementSize; } } } + @Fold + private static LocationIdentity getArrayLocation(Kind kind) { + return NamedLocationIdentity.getArrayLocation(kind); + } + @Snippet public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte, getArrayLocation(Kind.Byte)); } @Snippet public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte, getArrayLocation(Kind.Boolean)); } @Snippet public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char, getArrayLocation(Kind.Char)); } @Snippet public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short, getArrayLocation(Kind.Short)); } @Snippet public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int, getArrayLocation(Kind.Int)); } @Snippet public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) { - vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float); + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float, getArrayLocation(Kind.Float)); } @Snippet public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) { - Kind baseKind = Kind.Long; - int arrayBaseOffset = arrayBaseOffset(baseKind); - long byteLength = (long) length * arrayIndexScale(baseKind); - long srcOffset = (long) srcPos * arrayIndexScale(baseKind); - long destOffset = (long) destPos * arrayIndexScale(baseKind); - if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND); - } - } else { - for (long i = 0; i < byteLength; i += VECTOR_SIZE) { - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND); - } - } + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Long, getArrayLocation(Kind.Long)); } @Snippet public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) { - Kind baseKind = Kind.Double; - int arrayBaseOffset = arrayBaseOffset(baseKind); - long byteLength = (long) length * arrayIndexScale(baseKind); - long srcOffset = (long) srcPos * arrayIndexScale(baseKind); - long destOffset = (long) destPos * arrayIndexScale(baseKind); - if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND); - } - } else { - for (long i = 0; i < byteLength; i += VECTOR_SIZE) { - /* - * TODO atomicity problem on 32-bit architectures: The JVM spec requires double - * values to be copied atomically, but not long values. For example, on Intel 32-bit - * this code is not atomic as long as the vector kind remains Kind.Long. - */ - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND); - UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND); - } - } + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values to be + * copied atomically, but not long values. For example, on Intel 32-bit this code is not + * atomic as long as the vector kind remains Kind.Long. + */ + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Double, getArrayLocation(Kind.Double)); } - /** - * Does NOT perform store checks. - */ @Snippet public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) { - final int scale = arrayIndexScale(Kind.Object); - int arrayBaseOffset = arrayBaseOffset(Kind.Object); - if (src == dest && srcPos < destPos) { // bad aliased case - long start = (long) (length - 1) * scale; - for (long i = start; i >= 0; i -= scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a); - } - } else { - long end = (long) length * scale; - for (long i = 0; i < end; i += scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a); - } - } + vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Object, getArrayLocation(Kind.Object)); } @Snippet diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -174,6 +174,13 @@ StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 1), StampFactory.forInteger(Kind.Long, Integer.MIN_VALUE, Integer.MAX_VALUE))); assertEquals(StampFactory.forInteger(Kind.Int, -2147483647, 31 - 2147483647), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 31), StampFactory.forInteger(Kind.Int, -2147483647, -2147483647))); + + assertEquals(StampFactory.forInteger(Kind.Int, 0x8000007e, 0x8000007f, 0x8000007eL, 0x8000007fL), + StampTool.add(StampFactory.forInteger(Kind.Int, 0x7ffffffe, 0x7fffffff, 0x7ffffffeL, 0x7fffffffL), StampFactory.forInteger(Kind.Int, 128, 128))); + + assertEquals(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampTool.add(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL))); } @Test diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -45,6 +45,17 @@ } /** + * Used to measure the impact of ConstantNodes not recording their usages. This and all code + * predicated on this value being true will be removed at some point. + */ + public static final boolean ConstantNodeRecordsUsages = Boolean.getBoolean("graal.constantNodeRecordsUsages"); + + @Override + public boolean recordsUsages() { + return ConstantNodeRecordsUsages; + } + + /** * Constructs a new ConstantNode representing the specified constant. * * @param value the constant @@ -54,6 +65,35 @@ this.value = value; } + /** + * Computes the usages of this node by iterating over all the nodes in the graph, searching for + * those that have this node as an input. + */ + public List gatherUsages() { + assert !ConstantNodeRecordsUsages; + List usages = new ArrayList<>(); + for (Node node : graph().getNodes()) { + for (Node input : node.inputs()) { + if (input == this) { + usages.add(node); + } + } + } + return usages; + } + + public void replace(Node replacement) { + if (!recordsUsages()) { + List usages = gatherUsages(); + for (Node usage : usages) { + usage.replaceFirstInput(this, replacement); + } + graph().removeFloating(this); + } else { + graph().replaceFloating(this, replacement); + } + } + @Override public void generate(LIRGeneratorTool gen) { if (gen.canInlineConstant(value) || onlyUsedInVirtualState()) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -99,9 +99,8 @@ DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason)); deopt.setDeoptimizationState(getDeoptimizationState()); setNext(deopt); - } else { - this.replaceAtUsages(null); } + this.replaceAtUsages(null); graph().removeFixed(this); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -45,7 +45,7 @@ @Input private LogicNode condition; private final DeoptimizationReason reason; - private final DeoptimizationAction action; + private DeoptimizationAction action; private boolean negated; public GuardNode(LogicNode condition, GuardingNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated) { @@ -107,4 +107,8 @@ public void negate() { negated = !negated; } + + public void setAction(DeoptimizationAction invalidaterecompile) { + this.action = invalidaterecompile; + } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -90,7 +90,7 @@ } ValueNode removedValue = phi.valueAt(predIndex); phi.removeInput(predIndex); - if (removedValue != null && removedValue.isAlive() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) { + if (removedValue != null && removedValue.isAlive() && removedValue.recordsUsages() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) { GraphUtil.killWithUnusedFloatingInputs(removedValue); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -37,8 +37,8 @@ public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { @Input private LogicNode guardingCondition; - public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind) { - this(object, offset, accessKind, LocationIdentity.ANY_LOCATION, null); + public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { + this(object, offset, accessKind, locationIdentity, null); } public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) { @@ -78,9 +78,9 @@ return this.graph().add(new LoadFieldNode(object(), field)); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "unused"}) @NodeIntrinsic - public static T load(Object object, long offset, @ConstantNodeParameter Kind kind) { + public static T load(Object object, long offset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { if (kind == Kind.Boolean) { return (T) (Boolean) unsafe.getBoolean(object, offset); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -39,10 +39,6 @@ @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; - public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind) { - this(object, offset, value, accessKind, LocationIdentity.ANY_LOCATION); - } - public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) { super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity); assert accessKind != Kind.Void && accessKind != Kind.Illegal; @@ -106,55 +102,55 @@ @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putObject(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putBoolean(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putByte(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putChar(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putDouble(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putFloat(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putInt(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putLong(object, offset, value); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind) { + public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { unsafe.putShort(object, offset, value); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Oct 25 01:39:54 2013 +0200 @@ -185,7 +185,9 @@ return StampFactory.illegal(Kind.Illegal); } IntegerStamp other = (IntegerStamp) otherStamp; - return createStamp(other, Math.min(upperBound, other.upperBound), Math.max(lowerBound, other.lowerBound), downMask | other.downMask, upMask & other.upMask); + long newDownMask = downMask | other.downMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask); } @Override diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Oct 25 01:39:54 2013 +0200 @@ -114,13 +114,23 @@ return StampFactory.forKind(kind); } - private static boolean addOverflows(long x, long y, Kind kind) { + private static boolean addOverflowsPositively(long x, long y, Kind kind) { long result = x + y; if (kind == Kind.Long) { - return ((x ^ result) & (y ^ result)) < 0; + return (~x & ~y & result) < 0; } else { assert kind == Kind.Int; - return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE; + return result > Integer.MAX_VALUE; + } + } + + private static boolean addOverflowsNegatively(long x, long y, Kind kind) { + long result = x + y; + if (kind == Kind.Long) { + return (x & y & ~result) < 0; + } else { + assert kind == Kind.Int; + return result < Integer.MIN_VALUE; } } @@ -142,16 +152,22 @@ long lowerBound; long upperBound; - if (addOverflows(stamp1.lowerBound(), stamp2.lowerBound(), kind) || addOverflows(stamp1.upperBound(), stamp2.upperBound(), kind)) { + boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), kind); + boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), kind); + if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsNegatively && !lowerOverflowsPositively && upperOverflowsPositively)) { lowerBound = kind.getMinValue(); upperBound = kind.getMaxValue(); } else { - lowerBound = stamp1.lowerBound() + stamp2.lowerBound(); - upperBound = stamp1.upperBound() + stamp2.upperBound(); + lowerBound = signExtend(stamp1.lowerBound() + stamp2.lowerBound(), kind); + upperBound = signExtend(stamp1.upperBound() + stamp2.upperBound(), kind); } IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound); newUpMask &= limit.upMask(); - return new IntegerStamp(kind, lowerBound | newDownMask, signExtend(upperBound & newUpMask, kind), newDownMask, newUpMask); + upperBound = signExtend(upperBound & newUpMask, kind); + lowerBound |= newDownMask; + return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask); } catch (Throwable e) { throw new RuntimeException(stamp1 + " + " + stamp2, e); } @@ -238,14 +254,16 @@ if (shiftCount != 0) { long lowerBound; long upperBound; + long downMask = value.downMask() >>> shiftCount; + long upMask = value.upMask() >>> shiftCount; if (value.lowerBound() < 0) { - lowerBound = 0; - upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; + lowerBound = downMask; + upperBound = upMask; } else { lowerBound = value.lowerBound() >>> shiftCount; upperBound = value.upperBound() >>> shiftCount; } - return new IntegerStamp(kind, lowerBound, upperBound, value.downMask() >>> shiftCount, value.upMask() >>> shiftCount); + return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask); } } long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound()); @@ -309,7 +327,7 @@ } private static long signExtend(long value, Kind valueKind) { - if (valueKind != Kind.Char && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { + if (valueKind != Kind.Char && valueKind != Kind.Long && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { return value | (-1L << valueKind.getBitCount()); } else { return value; diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Fri Oct 25 01:39:54 2013 +0200 @@ -123,13 +123,17 @@ } public static void killWithUnusedFloatingInputs(Node node) { - List floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); - node.safeDelete(); + if (node.recordsUsages()) { + List floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); + node.safeDelete(); - for (Node in : floatingInputs) { - if (in.isAlive() && in.usages().isEmpty()) { - killWithUnusedFloatingInputs(in); + for (Node in : floatingInputs) { + if (in.isAlive() && (!in.recordsUsages() || in.usages().isEmpty())) { + killWithUnusedFloatingInputs(in); + } } + } else { + assert node.inputs().isEmpty(); } } diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -206,7 +206,7 @@ } private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(node); return true; } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Fri Oct 25 01:39:54 2013 +0200 @@ -89,10 +89,9 @@ int successorCount = controlSplit.successors().count(); List otherGuards = new ArrayList<>(successorCount - 1); for (GuardNode guard : successor.guards().snapshot()) { - if (guard.condition().usages().count() < successorCount) { + if (guard.isDeleted() || guard.condition().usages().count() < successorCount) { continue; } - for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) { if (conditonGuard != guard) { GuardingNode conditonGuardAnchor = conditonGuard.getGuard(); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -631,8 +631,10 @@ cdbc.apply(cfg.getNodeToBlock().get(succ)); } ensureScheduledUsages(node, strategy); - for (Node usage : node.usages()) { - blocksForUsage(node, usage, cdbc, strategy); + if (node.recordsUsages()) { + for (Node usage : node.usages()) { + blocksForUsage(node, usage, cdbc, strategy); + } } List usages = phantomUsages.get(node); if (usages != null) { @@ -808,8 +810,10 @@ } private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) { - for (Node usage : node.usages().filter(ScheduledNode.class)) { - assignBlockToNode((ScheduledNode) usage, strategy); + if (node.recordsUsages()) { + for (Node usage : node.usages().filter(ScheduledNode.class)) { + assignBlockToNode((ScheduledNode) usage, strategy); + } } // now true usages are ready } @@ -1057,14 +1061,16 @@ } visited.mark(instruction); - for (Node usage : instruction.usages()) { - if (usage instanceof VirtualState) { - // only fixed nodes can have VirtualState -> no need to schedule them - } else { - if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) { - // value proxies should be scheduled before the loopexit, not after + if (instruction.recordsUsages()) { + for (Node usage : instruction.usages()) { + if (usage instanceof VirtualState) { + // only fixed nodes can have VirtualState -> no need to schedule them } else { - addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited); + if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) { + // value proxies should be scheduled before the loopexit, not after + } else { + addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited); + } } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Oct 25 01:39:54 2013 +0200 @@ -327,7 +327,7 @@ out.println("=== Succesors ==="); printNamedNodes(node, node.successors().iterator(), "", "\n", null); out.println("=== Usages ==="); - if (!node.usages().isEmpty()) { + if (node.recordsUsages() && !node.usages().isEmpty()) { for (Node usage : node.usages()) { out.print(nodeToString(usage)).print(" "); } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Fri Oct 25 01:39:54 2013 +0200 @@ -94,7 +94,7 @@ return false; } - if (method != curMethod || !curDecorators.equals(decorators)) { + if (!method.equals(curMethod) || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile); curMethod = method; diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Fri Oct 25 01:39:54 2013 +0200 @@ -64,22 +64,22 @@ @MethodSubstitution private static Node getNode(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), Node.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class, false, false); } @MethodSubstitution private static NodeList getNodeList(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), NodeList.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class, false, false); } @MethodSubstitution private static void putNode(Node node, long offset, Node value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object); + UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); } @MethodSubstitution private static void putNodeList(Node node, long offset, NodeList value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object); + UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -321,7 +321,8 @@ } public void cleanUpReturnCheckCast(Node newInstance) { - if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { + if (newInstance.recordsUsages() && newInstance instanceof ValueNode && + (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { StructuredGraph graph = (StructuredGraph) newInstance.graph(); for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) { for (Node checkCastUsage : checkCastNode.usages().snapshot()) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Oct 25 01:39:54 2013 +0200 @@ -273,6 +273,20 @@ } } + static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider { + + final Varargs varargs; + + public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) { + super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass())); + this.varargs = varargs; + } + + public ValueNode length() { + return ConstantNode.forInt(varargs.length, graph()); + } + } + static class CacheKey { private final ResolvedJavaMethod method; @@ -411,7 +425,7 @@ assert checkTemplate(metaAccess, args, method, signature); int parameterCount = args.info.getParameterCount(); - ConstantNode[] placeholders = new ConstantNode[parameterCount]; + VarargsPlaceholderNode[] placeholders = new VarargsPlaceholderNode[parameterCount]; for (int i = 0; i < parameterCount; i++) { if (args.info.isConstantParameter(i)) { @@ -426,8 +440,7 @@ nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy)); } else if (args.info.isVarargsParameter(i)) { Varargs varargs = (Varargs) args.values[i]; - Object array = Array.newInstance(varargs.componentType, varargs.length); - ConstantNode placeholder = ConstantNode.forObject(array, metaAccess, snippetCopy); + VarargsPlaceholderNode placeholder = snippetCopy.unique(new VarargsPlaceholderNode(varargs, providers.getMetaAccess())); nodeReplacements.put(snippetGraph.getLocal(i), placeholder); placeholders[i] = placeholder; } @@ -461,7 +474,7 @@ } parameters[i] = locals; - ConstantNode placeholder = placeholders[i]; + VarargsPlaceholderNode placeholder = placeholders[i]; assert placeholder != null; for (Node usage : placeholder.usages().snapshot()) { if (usage instanceof LoadIndexedNode) { @@ -584,7 +597,7 @@ this.returnNode = retNode; } - private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) { + private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) { for (int i = 0; i < parameterCount; i++) { if (placeholders[i] != null) { assert placeholders[i].isDeleted() : placeholders[i]; @@ -800,7 +813,7 @@ // check if some node in snippet graph also kills the same location LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity(); if (locationIdentity == ANY_LOCATION) { - assert !(memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode); + assert !(memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode) : replacee + " kills ANY_LOCATION, but snippet does not"; } assert kills.contains(locationIdentity) : replacee + " kills " + locationIdentity + ", but snippet doesn't contain a kill to this location"; return true; diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Fri Oct 25 01:39:54 2013 +0200 @@ -53,7 +53,7 @@ @MethodSubstitution(isStatic = false) public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - return UnsafeLoadNode.load(o, offset, Kind.Object); + return UnsafeLoadNode.load(o, offset, Kind.Object, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -66,7 +66,7 @@ @MethodSubstitution(isStatic = false) public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { - UnsafeStoreNode.store(o, offset, x, Kind.Object); + UnsafeStoreNode.store(o, offset, x, Kind.Object, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -85,7 +85,7 @@ @MethodSubstitution(isStatic = false) public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, offset, Kind.Int); + Integer value = UnsafeLoadNode.load(o, offset, Kind.Int, LocationIdentity.ANY_LOCATION); return value; } @@ -99,7 +99,7 @@ @MethodSubstitution(isStatic = false) public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { - UnsafeStoreNode.store(o, offset, x, Kind.Int); + UnsafeStoreNode.store(o, offset, x, Kind.Int, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -119,7 +119,7 @@ @MethodSubstitution(isStatic = false) public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean); + Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean, LocationIdentity.ANY_LOCATION); return result; } @@ -133,7 +133,7 @@ @MethodSubstitution(isStatic = false) public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, offset, x, Kind.Boolean); + UnsafeStoreNode.store(o, offset, x, Kind.Boolean, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -146,7 +146,7 @@ @MethodSubstitution(isStatic = false) public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte); + Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte, LocationIdentity.ANY_LOCATION); return result; } @@ -160,7 +160,7 @@ @MethodSubstitution(isStatic = false) public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { - UnsafeStoreNode.store(o, offset, x, Kind.Byte); + UnsafeStoreNode.store(o, offset, x, Kind.Byte, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -173,7 +173,7 @@ @MethodSubstitution(isStatic = false) public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, offset, Kind.Short); + Short result = UnsafeLoadNode.load(o, offset, Kind.Short, LocationIdentity.ANY_LOCATION); return result; } @@ -187,7 +187,7 @@ @MethodSubstitution(isStatic = false) public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { - UnsafeStoreNode.store(o, offset, x, Kind.Short); + UnsafeStoreNode.store(o, offset, x, Kind.Short, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -200,7 +200,7 @@ @MethodSubstitution(isStatic = false) public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, offset, Kind.Char); + Character result = UnsafeLoadNode.load(o, offset, Kind.Char, LocationIdentity.ANY_LOCATION); return result; } @@ -214,7 +214,7 @@ @MethodSubstitution(isStatic = false) public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { - UnsafeStoreNode.store(o, offset, x, Kind.Char); + UnsafeStoreNode.store(o, offset, x, Kind.Char, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -227,7 +227,7 @@ @MethodSubstitution(isStatic = false) public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, offset, Kind.Long); + Long result = UnsafeLoadNode.load(o, offset, Kind.Long, LocationIdentity.ANY_LOCATION); return result; } @@ -241,7 +241,7 @@ @MethodSubstitution(isStatic = false) public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { - UnsafeStoreNode.store(o, offset, x, Kind.Long); + UnsafeStoreNode.store(o, offset, x, Kind.Long, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -261,7 +261,7 @@ @MethodSubstitution(isStatic = false) public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, offset, Kind.Float); + Float result = UnsafeLoadNode.load(o, offset, Kind.Float, LocationIdentity.ANY_LOCATION); return result; } @@ -275,7 +275,7 @@ @MethodSubstitution(isStatic = false) public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { - UnsafeStoreNode.store(o, offset, x, Kind.Float); + UnsafeStoreNode.store(o, offset, x, Kind.Float, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -288,7 +288,7 @@ @MethodSubstitution(isStatic = false) public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, offset, Kind.Double); + Double result = UnsafeLoadNode.load(o, offset, Kind.Double, LocationIdentity.ANY_LOCATION); return result; } @@ -302,7 +302,7 @@ @MethodSubstitution(isStatic = false) public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { - UnsafeStoreNode.store(o, offset, x, Kind.Double); + UnsafeStoreNode.store(o, offset, x, Kind.Double, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java --- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java Fri Oct 25 01:39:54 2013 +0200 @@ -22,36 +22,50 @@ */ package com.oracle.graal.truffle.hotspot.amd64; +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.amd64.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.hotspot.amd64.util.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; /** - * Subclass of {@link AMD64HotSpotBackend} that injects special code into + * Backend that decorates an existing {@link AMD64HotSpotBackend}, injecting special code into * {@link OptimizedCallTarget#call(PackedFrame, Arguments)} for making a tail-call to the entry * point of the target callee. */ -class AMD64HotSpotTruffleBackend extends AMD64HotSpotBackend { +class AMD64HotSpotTruffleBackend extends Backend { + + private final AMD64HotSpotBackend original; - private ResolvedJavaMethod optimizedCallTargetCall; + private HotSpotResolvedJavaMethod optimizedCallTargetCall; - public AMD64HotSpotTruffleBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { - super(runtime, providers); + public AMD64HotSpotTruffleBackend(AMD64HotSpotBackend original) { + super(original.getProviders()); + this.original = original; } private ResolvedJavaMethod getInstrumentedMethod() throws GraalInternalError { if (optimizedCallTargetCall == null) { try { - optimizedCallTargetCall = getProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class)); + optimizedCallTargetCall = (HotSpotResolvedJavaMethod) getProviders().getMetaAccess().lookupJavaMethod( + OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class)); + optimizedCallTargetCall.setDontInline(); } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); } @@ -60,10 +74,88 @@ } @Override - protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) { - super.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub); + public SuitesProvider getSuites() { + return original.getSuites(); + } + + @Override + public DisassemblerProvider getDisassembler() { + return original.getDisassembler(); + } + + @Override + public FrameMap newFrameMap() { + return original.newFrameMap(); + } + + @Override + public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) { + return original.newLIRGenerator(graph, frameMap, cc, lir); + } + + @Override + protected AbstractAssembler createAssembler(FrameMap frameMap) { + return null; + } + + @Override + public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { + return original.newAssembler(lirGen, compilationResult); + } + + @Override + public boolean shouldAllocateRegisters() { + return original.shouldAllocateRegisters(); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) { + AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; + FrameMap frameMap = tasm.frameMap; + RegisterConfig regConfig = frameMap.registerConfig; + HotSpotVMConfig config = original.getRuntime().getConfig(); + Label verifiedStub = new Label(); + + // Emit the prefix + original.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub); + if (getInstrumentedMethod().equals(installedCodeOwner)) { - // TODO emit tailcall code + // Inject code for {@link OptimizedCallTarget#call(PackedFrame, Arguments)} + injectCode(asm, config); } + + // Emit code for the LIR + original.emitCodeBody(installedCodeOwner, tasm, lirGen); + + // Emit the suffix + original.emitCodeSuffix(installedCodeOwner, tasm, lirGen, asm, frameMap); + } + + private void injectCode(AMD64MacroAssembler asm, HotSpotVMConfig config) { + HotSpotProviders providers = original.getRuntime().getHostProviders(); + Register thisRegister = providers.getCodeCache().getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0]; + Register spillRegister = AMD64.r10; // TODO(mg): fix me + AMD64Address nMethodAddress = new AMD64Address(thisRegister, OptimizedCallTargetFieldInfo.getCompiledMethodFieldOffset()); + if (config.useCompressedOops) { + asm.movl(spillRegister, nMethodAddress); + AMD64HotSpotMove.decodePointer(asm, spillRegister, providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment()); + } else { + asm.movq(spillRegister, nMethodAddress); + } + Label doProlog = new Label(); + + asm.cmpq(spillRegister, 0); + asm.jcc(ConditionFlag.Equal, doProlog); + + AMD64Address codeBlobAddress = new AMD64Address(spillRegister, OptimizedCallTargetFieldInfo.getCodeBlobFieldOffset()); + asm.movq(spillRegister, codeBlobAddress); + asm.cmpq(spillRegister, 0); + asm.jcc(ConditionFlag.Equal, doProlog); + + AMD64Address verifiedEntryPointAddress = new AMD64Address(spillRegister, config.nmethodEntryOffset); + asm.movq(spillRegister, verifiedEntryPointAddress); + asm.jmp(spillRegister); + + asm.bind(doProlog); } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java --- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java Fri Oct 25 01:39:54 2013 +0200 @@ -23,18 +23,22 @@ package com.oracle.graal.truffle.hotspot.amd64; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.hotspot.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.amd64.*; -import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.truffle.*; /** * Factory to create a Truffle-specialized AMD64 HotSpot backend. */ -@ServiceProvider(HotSpotBackendFactory.class) -public class AMD64HotSpotTruffleBackendFactory extends AMD64HotSpotBackendFactory { +@ServiceProvider(TruffleBackendFactory.class) +public class AMD64HotSpotTruffleBackendFactory implements TruffleBackendFactory { @Override - protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { - return new AMD64HotSpotTruffleBackend(runtime, providers); + public Backend createBackend(Backend original) { + return new AMD64HotSpotTruffleBackend((AMD64HotSpotBackend) original); + } + + public String getArchitecture() { + return "AMD64"; } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/util/OptimizedCallTargetFieldInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/util/OptimizedCallTargetFieldInfo.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.hotspot.amd64.util; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.truffle.*; + +public class OptimizedCallTargetFieldInfo { + + private static final Unsafe unsafe = UnsafeAccess.unsafe; + private static int compiledMethodFieldOffset = -1; + private static int codeBlobFieldOffset = -1; + + public static int getCodeBlobFieldOffset() { + if (codeBlobFieldOffset == -1) { + codeBlobFieldOffset = getFieldOffset("codeBlob", HotSpotInstalledCode.class); + } + return codeBlobFieldOffset; + } + + public static int getCompiledMethodFieldOffset() { + if (compiledMethodFieldOffset == -1) { + compiledMethodFieldOffset = getFieldOffset("compiledMethod", OptimizedCallTarget.class); + } + return compiledMethodFieldOffset; + + } + + private static int getFieldOffset(String name, Class container) { + try { + container.getDeclaredField(name).setAccessible(true); + Field field = container.getDeclaredField(name); + return (int) unsafe.objectFieldOffset(field); + } catch (NoSuchFieldException | SecurityException e) { + throw GraalInternalError.shouldNotReachHere(); + } + } +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Fri Oct 25 01:39:54 2013 +0200 @@ -102,7 +102,7 @@ compilable.call(null, arguments); } while (compilable.inline()); - StructuredGraph graph = Debug.scope("TruffleCompilation", new DebugDumpScope("TruffleCompilation: " + compilable), new Callable() { + StructuredGraph graph = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable), new Callable() { @Override public StructuredGraph call() { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Fri Oct 25 01:39:54 2013 +0200 @@ -22,11 +22,28 @@ */ package com.oracle.graal.truffle; +import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; +import java.lang.reflect.*; import java.util.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.impl.*; @@ -47,6 +64,7 @@ private ArrayList excludes; private GraalTruffleRuntime() { + installOptimizedCallTargetCallMethod(); } public String getName() { @@ -138,4 +156,55 @@ } } } + + public static void installOptimizedCallTargetCallMethod() { + Providers providers = getGraalProviders(); + MetaAccessProvider metaAccess = providers.getMetaAccess(); + ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod()); + providers.getCodeCache().setDefaultMethod(resolvedCallMethod, compileMethod(resolvedCallMethod)); + } + + private static Method getCallMethod() { + Method method; + try { + method = OptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{PackedFrame.class, Arguments.class}); + } catch (NoSuchMethodException | SecurityException e) { + throw GraalInternalError.shouldNotReachHere(); + } + return method; + } + + private static Backend instrumentBackend(Backend original) { + String arch = original.getTarget().arch.getName(); + + for (TruffleBackendFactory factory : ServiceLoader.loadInstalled(TruffleBackendFactory.class)) { + if (factory.getArchitecture().equals(arch)) { + return factory.createBackend(original); + } + } + + return original; + } + + private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) { + Providers providers = getGraalProviders(); + MetaAccessProvider metaAccess = providers.getMetaAccess(); + Suites suites = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); + suites.getHighTier().findPhase(InliningPhase.class).remove(); + StructuredGraph graph = new StructuredGraph(javaMethod); + ForeignCallsProvider foreignCalls = providers.getForeignCalls(); + new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); + Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + return GraalCompiler.compileGraph(graph, cc, javaMethod, providers, instrumentBackend(backend), providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog(), suites, new CompilationResult()); + } + + private static Providers getGraalProviders() { + RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); + return runtimeProvider.getHostBackend().getProviders(); + } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Fri Oct 25 01:39:54 2013 +0200 @@ -77,6 +77,14 @@ } private Object callHelper(PackedFrame caller, Arguments args) { + if (compiledMethod != null && compiledMethod.isValid()) { + TruffleRuntime runtime = Truffle.getRuntime(); + if (runtime instanceof GraalTruffleRuntime) { + OUT.printf("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut."); + OUT.println(); + GraalTruffleRuntime.installOptimizedCallTargetCallMethod(); + } + } if (TruffleCallTargetProfiling.getValue()) { callCount++; } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Oct 25 01:39:54 2013 +0200 @@ -104,7 +104,7 @@ final StructuredGraph graph = new StructuredGraph(executeHelperMethod); - Debug.scope("createGraph", graph, new Runnable() { + Debug.scope("createGraph", new Runnable() { @Override public void run() { @@ -245,13 +245,12 @@ ValueNode arg = arguments.get(local.index()); if (arg.isConstant()) { Constant constant = arg.asConstant(); - ConstantNode constantNode = ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy); - local.replaceAndDelete(constantNode); - for (Node usage : constantNode.usages()) { + for (Node usage : local.usages()) { if (usage instanceof Canonicalizable) { modifiedNodes.add(usage); } } + local.replaceAndDelete(ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy)); } } Debug.scope("TruffleUnrollLoop", targetMethod, new Runnable() { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleBackendFactory.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import com.oracle.graal.compiler.target.*; + +public interface TruffleBackendFactory { + + Backend createBackend(Backend original); + + /** + * Gets the CPU architecture of this backend. + */ + String getArchitecture(); +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Oct 25 01:39:54 2013 +0200 @@ -156,7 +156,7 @@ int beforeInvokeMark = graph.getMark(); expandInvoke(methodCallTarget); for (Node arg : argumentSnapshot) { - if (arg != null) { + if (arg != null && arg.recordsUsages()) { for (Node argUsage : arg.usages()) { if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { canonicalizerUsages.add(argUsage); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Oct 25 01:39:54 2013 +0200 @@ -198,7 +198,7 @@ public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) { final PhasePlan plan = createPhasePlan(config); - Debug.scope("TruffleFinal", graph, new Runnable() { + Debug.scope("TruffleFinal", new Runnable() { @Override public void run() { @@ -211,10 +211,15 @@ @Override public CompilationResult call() { try (TimerCloseable a = CompilationTime.start()) { - CodeCacheProvider codeCache = providers.getCodeCache(); - CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); - return GraalCompiler.compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(), suites, - new CompilationResult()); + return Debug.scope("GraalCompiler", new Object[]{providers.getCodeCache()}, new Callable() { + public CompilationResult call() { + CodeCacheProvider codeCache = providers.getCodeCache(); + CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); + CompilationResult compilationResult = new CompilationResult(compilable.toString()); + return GraalCompiler.compileGraphNoScope(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, plan, OptimisticOptimizations.ALL, + new SpeculationLog(), suites, compilationResult); + } + }); } } }); @@ -235,7 +240,7 @@ result.setAssumptions(newAssumptions); - InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{graph.method()}, new Callable() { + InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{providers.getCodeCache()}, new Callable() { @Override public InstalledCode call() throws Exception { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java Fri Oct 25 01:39:54 2013 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import static com.oracle.graal.api.meta.MetaUtil.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.truffle.api.impl.*; + +/** + * Enables a Truffle compilable to masquerade as a {@link JavaMethod} for use as a context value in + * {@linkplain Debug#scope(String, Object[], Runnable) debug scopes}. + */ +public class TruffleDebugJavaMethod implements JavaMethod { + private final DefaultCallTarget compilable; + + private static final JavaType declaringClass = new JavaType() { + + public String getName() { + return "LTruffle;"; + } + + public JavaType getComponentType() { + return null; + } + + public JavaType getArrayClass() { + throw new UnsupportedOperationException(); + } + + public Kind getKind() { + return Kind.Object; + } + + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object obj) { + return obj.getClass() == getClass(); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + }; + + private static final Signature signature = new Signature() { + + public JavaType getReturnType(ResolvedJavaType accessingClass) { + return declaringClass; + } + + public Kind getReturnKind() { + return declaringClass.getKind(); + } + + public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { + throw new IndexOutOfBoundsException(); + } + + public int getParameterSlots(boolean withReceiver) { + return 0; + } + + public Kind getParameterKind(int index) { + throw new IndexOutOfBoundsException(); + } + + public int getParameterCount(boolean receiver) { + return 0; + } + }; + + public TruffleDebugJavaMethod(DefaultCallTarget compilable) { + this.compilable = compilable; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TruffleDebugJavaMethod) { + TruffleDebugJavaMethod other = (TruffleDebugJavaMethod) obj; + return other.compilable.equals(compilable); + } + return false; + } + + @Override + public int hashCode() { + return compilable.hashCode(); + } + + public Signature getSignature() { + return signature; + } + + public String getName() { + return compilable.toString().replace('.', '_').replace(' ', '_'); + } + + public JavaType getDeclaringClass() { + return declaringClass; + } + + @Override + public String toString() { + return format("Truffle<%n(%p)>", this); + } +} diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -163,7 +163,7 @@ ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph()); for (int i = 0; i < frameSize; i++) { objectArrayEntryState[i] = objectDefault; - primitiveArrayEntryState[i] = initialValue(frameDescriptor.getSlots().get(i).getKind()); + primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind()); tagArrayEntryState[i] = tagDefault; } tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); @@ -186,7 +186,7 @@ tool.replaceWithVirtual(virtualFrame); } - private ValueNode initialValue(FrameSlotKind kind) { + private ValueNode initialPrimitiveValue(FrameSlotKind kind) { Kind graalKind = null; switch (kind) { case Boolean: @@ -208,9 +208,8 @@ graalKind = Kind.Long; break; case Object: - graalKind = Kind.Object; - break; case Illegal: + // won't be stored in the primitive array, so default to long graalKind = Kind.Long; break; default: diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Oct 25 01:39:54 2013 +0200 @@ -34,6 +34,9 @@ public class OptimizedCallTargetSubstitutions { @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args); + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) public static native Object callHelper(OptimizedCallTarget target, PackedFrame caller, Arguments args); @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) diff -r cf6cfa79593d -r faded4a83d63 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 Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Oct 25 01:39:54 2013 +0200 @@ -531,8 +531,10 @@ void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node) { if (node.isAlive()) { aliases.set(node, virtual); - for (Node usage : node.usages()) { - markVirtualUsages(usage); + if (node.recordsUsages()) { + for (Node usage : node.usages()) { + markVirtualUsages(usage); + } } } } diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Oct 25 01:39:54 2013 +0200 @@ -61,6 +61,9 @@ wordAccess.inferStamps(graph); for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { + if (!node.recordsUsages()) { + continue; + } for (Node usage : node.usages()) { if (usage instanceof AccessMonitorNode) { verify(!isWord(node), node, usage, "word value has no monitor"); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Fri Oct 25 01:39:54 2013 +0200 @@ -306,7 +306,7 @@ case LONG: return "Long"; case DECLARED: - return ((DeclaredType) mirror).asElement().getSimpleName().toString(); + return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString()); case ARRAY: return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; case VOID: @@ -379,7 +379,7 @@ } private static String getDeclaredName(DeclaredType element) { - String simpleName = element.asElement().getSimpleName().toString(); + String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString()); if (element.getTypeArguments().size() == 0) { return simpleName; @@ -399,6 +399,14 @@ return b.toString(); } + public static String fixECJBinaryNameIssue(String name) { + if (name.contains("$")) { + int lastIndex = name.lastIndexOf('$'); + return name.substring(lastIndex + 1, name.length()); + } + return name; + } + public static String getQualifiedName(TypeElement element) { String qualifiedName = element.getQualifiedName().toString(); if (qualifiedName.contains("$")) { diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Fri Oct 25 01:39:54 2013 +0200 @@ -135,7 +135,7 @@ } private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { - String name = type.asElement().getSimpleName().toString(); + String name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString()); if (needsImport(enclosedElement, type)) { TypeMirror usedByType = simpleNamesUsed.get(name); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Fri Oct 25 01:39:54 2013 +0200 @@ -964,16 +964,78 @@ for (CodeExecutableElement method : createImplicitChildrenAccessors()) { clazz.add(method); } - clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); clazz.add(createInfoMessage(node)); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(clazz.asType(), null)); + clazz.add(createCopyPolymorphicConstructor(clazz.asType())); + } + if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { clazz.add(createGenericExecute(node, rootGroup)); } } + protected boolean needsInvokeCopyConstructorMethod() { + return getModel().getNode().isPolymorphic(); + } + + protected CodeExecutableElement createInvokeCopyConstructor(TypeMirror baseType, SpecializationData specialization) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), baseType, "invokeCopyConstructor"); + if (specialization == null) { + method.getModifiers().add(ABSTRACT); + } else { + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startNew(getElement().asType()); + builder.string("this"); + for (ActualParameter param : getImplicitTypeParamters(specialization)) { + builder.string(implicitTypeName(param)); + } + builder.end().end(); + } + return method; + } + + protected CodeExecutableElement createCopyPolymorphicConstructor(TypeMirror baseType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), baseType, "copyPolymorphic"); + CodeTreeBuilder builder = method.createBuilder(); + CodeTreeBuilder nullBuilder = builder.create(); + CodeTreeBuilder oldBuilder = builder.create(); + CodeTreeBuilder resetBuilder = builder.create(); + + for (ActualParameter param : getModel().getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + + CodeTreeBuilder access = builder.create(); + access.string("this.").string(child.getName()); + if (child.getCardinality().isMany()) { + access.string("[").string(String.valueOf(param.getIndex())).string("]"); + } + + String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName()); + oldBuilder.declaration(child.getNodeData().getNodeType(), oldName, access); + nullBuilder.startStatement().tree(access.getRoot()).string(" = null").end(); + resetBuilder.startStatement().tree(access.getRoot()).string(" = ").string(oldName).end(); + } + + builder.tree(oldBuilder.getRoot()); + builder.tree(nullBuilder.getRoot()); + + builder.startStatement().type(baseType).string(" copy = "); + builder.startCall("invokeCopyConstructor").end(); + builder.end(); + + builder.tree(resetBuilder.getRoot()); + builder.startReturn().string("copy").end(); + return method; + } + private List createImplicitChildrenAccessors() { NodeData node = getModel().getNode(); // Map> expectTypes = new HashMap<>(); @@ -1795,27 +1857,14 @@ String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); CodeTreeBuilder builder = parent.create(); + builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyPolymorphic()"); builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end()); - - for (ActualParameter param : node.getGenericSpecialization().getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = node.findChild(param.getSpecification().getName()); - if (child != null) { - builder.startStatement().string(currentNode).string(".").string(child.getName()); - if (child.getCardinality().isMany()) { - builder.string("[").string(String.valueOf(param.getIndex())).string("]"); - } - builder.string(" = null").end(); - } - } builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end(); - builder.startStatement().startCall("polymorphic", "setNext0").string(currentNode).end().end(); - builder.startStatement().startCall(currentNode, "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); + builder.startStatement().startCall("polymorphic", "setNext0").string("currentCopy").end().end(); + builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); builder.startReturn(); - builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization())); + builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization())); addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null); builder.end(); builder.end(); @@ -1981,6 +2030,21 @@ } } + protected final List getImplicitTypeParamters(SpecializationData model) { + List parameter = new ArrayList<>(); + for (ActualParameter param : model.getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (types.size() > 1) { + parameter.add(param); + } + } + return parameter; + } + protected final TreeSet lookupPolymorphicTargetTypes(ActualParameter param) { SpecializationData specialization = getModel(); TreeSet possiblePolymorphicTypes = new TreeSet<>(); @@ -2529,6 +2593,10 @@ getElement().add(createUpdateType(parameter)); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization)); + } + createCachedExecuteMethods(specialization); } @@ -2607,6 +2675,9 @@ if (specialization.getNode().isPolymorphic()) { getElement().add(createUpdateTypes(nodeGen.asType())); } + if (needsInvokeCopyConstructorMethod()) { + clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization)); + } } protected void createConstructors(CodeTypeElement clazz) { @@ -2636,20 +2707,13 @@ builder.statement("this.next0 = null"); } - for (ActualParameter param : getModel().getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); - superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); - - builder.startStatement(); - builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); - builder.end(); - } + for (ActualParameter param : getImplicitTypeParamters(getModel())) { + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); + superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); + + builder.startStatement(); + builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); + builder.end(); } clazz.add(superConstructor); diff -r cf6cfa79593d -r faded4a83d63 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java Tue Oct 22 15:06:02 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java Fri Oct 25 01:39:54 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.truffle.sl.nodes; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; public class BlockNode extends StatementNode { @@ -33,6 +34,7 @@ } @Override + @ExplodeLoop public void executeVoid(VirtualFrame frame) { for (StatementNode statement : statements) { statement.executeVoid(frame); diff -r cf6cfa79593d -r faded4a83d63 make/solaris/makefiles/jsig.make --- a/make/solaris/makefiles/jsig.make Tue Oct 22 15:06:02 2013 +0200 +++ b/make/solaris/makefiles/jsig.make Fri Oct 25 01:39:54 2013 +0200 @@ -79,9 +79,9 @@ install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" - $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + -$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) - $(QUIETLY) test -f $(LIBJSIG_DIZ) && \ + -$(QUIETLY) test -f $(LIBJSIG_DIZ) && \ cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" diff -r cf6cfa79593d -r faded4a83d63 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Tue Oct 22 15:06:02 2013 +0200 +++ b/make/solaris/makefiles/vm.make Fri Oct 25 01:39:54 2013 +0200 @@ -341,9 +341,9 @@ install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" - $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + -$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) - $(QUIETLY) test -f $(LIBJVM_DIZ) && \ + -$(QUIETLY) test -f $(LIBJVM_DIZ) && \ cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" diff -r cf6cfa79593d -r faded4a83d63 mx/commands.py --- a/mx/commands.py Tue Oct 22 15:06:02 2013 +0200 +++ b/mx/commands.py Fri Oct 25 01:39:54 2013 +0200 @@ -244,7 +244,7 @@ if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: return 'amd64' if machine in ['sun4v', 'sun4u']: - return 'sparc' + return 'sparcv9' if machine == 'i386' and mx.get_os() == 'darwin': try: # Support for Snow Leopard and earlier version of MacOSX @@ -320,11 +320,14 @@ for line in f: if line.startswith('-') and defaultVM is None: parts = line.split() - assert len(parts) == 2, parts - assert parts[1] == 'KNOWN', parts[1] - defaultVM = parts[0][1:] - jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] - jvmCfgLines += ['-original KNOWN\n'] + if len(parts) == 2: + assert parts[1] == 'KNOWN', parts[1] + defaultVM = parts[0][1:] + jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] + jvmCfgLines += ['-original KNOWN\n'] + else: + # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client') + pass else: jvmCfgLines += [line] diff -r cf6cfa79593d -r faded4a83d63 mxtool/mx.py --- a/mxtool/mx.py Tue Oct 22 15:06:02 2013 +0200 +++ b/mxtool/mx.py Fri Oct 25 01:39:54 2013 +0200 @@ -27,119 +27,9 @@ # r""" -mx is a command line tool inspired by mvn (http://maven.apache.org/) -and hg (http://mercurial.selenic.com/). It includes a mechanism for -managing the dependencies between a set of projects (like Maven) -as well as making it simple to run commands -(like hg is the interface to the Mercurial commands). - -The organizing principle of mx is a project suite. A suite is a directory -containing one or more projects. It's not coincidental that this closely -matches the layout of one or more projects in a Mercurial repository. -The configuration information for a suite lives in an 'mx' sub-directory -at the top level of the suite. A suite is given a name by a 'suite=name' -property in the 'mx/projects' file (if omitted the name is suite directory). -An 'mx' subdirectory can be named as plain 'mx' or 'mx.name', where -'name' is typically the name as the suite name. -The latter is useful to avoid clashes in IDE project names. - -When launched, mx treats the current working directory as a suite. -This is the primary suite. All other suites are called included suites. - -The configuration files (i.e. in the 'mx' sub-directory) of a suite are: - - projects - Defines the projects and libraries in the suite and the - dependencies between them. - - commands.py - Suite specific extensions to the commands available to mx. - - imports - Other suites to be loaded. This is recursive. Each - line in an imports file is the name of an imported suite. - The suite is located using a SuiteModel (cf searchpath) - - env - A set of environment variable definitions. These override any - existing environment variables. Common properties set here - include JAVA_HOME and IGNORED_PROJECTS. - -The env file is typically not put under version control -as it usually contain local file-system paths. - -The projects file is like the pom.xml file from Maven except that -it is a properties file (not XML). Each non-comment line -in the file specifies an attribute of a project or library. The main -difference between a project and a library is that the former contains -source code built by the mx tool where as the latter is an external -dependency. The format of the projects file is - -Library specification format: - - library@@= - -Built-in library properties (* = required): - - *path - The file system path for the library to appear on a class path. - - urls - A comma separated list of URLs from which the library (jar) can - be downloaded and saved in the location specified by 'path'. - - optional - If "true" then this library will be omitted from a class path - if it doesn't exist on the file system and no URLs are specified. - - sourcePath - The file system path for a jar file containing the library sources. - - sourceUrls - A comma separated list of URLs from which the library source jar can - be downloaded and saved in the location specified by 'sourcePath'. - -Project specification format: - - project@@= - -The name of a project also denotes the directory it is in. - -Built-in project properties (* = required): - - subDir - The sub-directory of the suite in which the project directory is - contained. If not specified, the project directory is directly - under the suite directory. - - *sourceDirs - A comma separated list of source directory names (relative to - the project directory). - - dependencies - A comma separated list of the libraries and project the project - depends upon (transitive dependencies should be omitted). - - checkstyle - The project whose Checkstyle configuration - (i.e. /.checkstyle_checks.xml) is used. - - native - "true" if the project is native. - - javaCompliance - The minimum JDK version (format: x.y) to which the project's - sources comply (required for non-native projects). - - workingSets - A comma separated list of working set names. The project belongs - to the given working sets, for which the eclipseinit command - will generate Eclipse configurations. - -Other properties can be specified for projects and libraries for use -by extension commands. - -Property values can use environment variables with Bash syntax (e.g. ${HOME}). +mx is a command line tool for managing the development of Java code organized as suites of projects. + +Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool """ import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch @@ -156,7 +46,8 @@ _dists = dict() _suites = dict() _annotationProcessors = None -_mainSuite = None +_primary_suite_path = None +_primary_suite = None _src_suitemodel = None _dst_suitemodel = None _opts = None @@ -514,19 +405,16 @@ except OSError: self.has_hg = False warn(self.missing) - + if not self.has_hg: if abortOnFail: abort(self.missing) else: warn(self.missing) - def tip(self, s, abortOnError=True): + def tip(self, sDir, abortOnError=True): try: - version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}']) - if s.version is not None and s.version != version: - abort('version of suite ' + s.name +' has changed during run') - return version + return subprocess.check_output(['hg', 'tip', '-R', sDir, '--template', '{node}']) except OSError: warn(self.missing) except subprocess.CalledProcessError: @@ -564,19 +452,19 @@ self.primaryDir = None self.suitenamemap = {} - def _find_suite_dir(self, suitename): + def find_suite_dir(self, suitename): """locates the URL/path for suitename or None if not found""" - abort('_find_suite_dir not implemented') - - def _set_primary_dir(self, d): + abort('find_suite_dir not implemented') + + def set_primary_dir(self, d): """informs that d is the primary suite directory""" self._primaryDir = d - def _importee_dir(self, importer_dir, suitename): + def importee_dir(self, importer_dir, suitename): """returns the directory path for an import of suitename, given importer_dir""" - abort('_importee_dir not implemented') - - def _nestedsuites_dirname(self): + abort('importee_dir not implemented') + + def nestedsuites_dirname(self): """Returns the dirname that contains any nested suites if the model supports that""" return None @@ -613,7 +501,7 @@ self.suitenamemap[mappair[0]] = mappair[1] @staticmethod - def _set_suitemodel(option, suitemap): + def set_suitemodel(option, suitemap): if option.startswith('sibling'): return SiblingSuiteModel(os.getcwd(), option, suitemap) elif option.startswith('nested'): @@ -624,7 +512,7 @@ abort('unknown suitemodel type: ' + option) @staticmethod - def _parse_options(): + def parse_options(): # suite-specific args may match the known args so there is no way at this early stage # to use ArgParser to handle the suite model global arguments, so we just do it manually. def _get_argvalue(arg, args, i): @@ -650,13 +538,15 @@ # to get warnings on suite loading issues before command line is parsed global _warn _warn = True - + elif arg == '-p' or arg == '--primary-suite-path': + global _primary_suite_path + _primary_suite_path = os.path.abspath(_get_argvalue(arg, args, i + 1)) i = i + 1 global _src_suitemodel - _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg) + _src_suitemodel = SuiteModel.set_suitemodel(src_suitemodel_arg, suitemap_arg) global _dst_suitemodel - _dst_suitemodel = SuiteModel._set_suitemodel(dst_suitemodel_arg, suitemap_arg) + _dst_suitemodel = SuiteModel.set_suitemodel(dst_suitemodel_arg, suitemap_arg) class SiblingSuiteModel(SuiteModel): @@ -666,14 +556,14 @@ self._suiteRootDir = suiteRootDir self._create_suitenamemap(option[len('sibling:'):], suitemap) - def _find_suite_dir(self, name): + def find_suite_dir(self, name): return self._search_dir(self._suiteRootDir, self._mxDirName(name)) - def _set_primary_dir(self, d): - SuiteModel._set_primary_dir(self, d) + def set_primary_dir(self, d): + SuiteModel.set_primary_dir(self, d) self._suiteRootDir = dirname(d) - def _importee_dir(self, importer_dir, suitename): + def importee_dir(self, importer_dir, suitename): if self.suitenamemap.has_key(suitename): suitename = self.suitenamemap[suitename] return join(dirname(importer_dir), suitename) @@ -688,10 +578,10 @@ self._primaryDir = primaryDir self._create_suitenamemap(option[len('nested:'):], suitemap) - def _find_suite_dir(self, name): + def find_suite_dir(self, name): return self._search_dir(join(self._primaryDir, self._imported_suites_dirname()), self._mxDirName(name)) - def _importee_dir(self, importer_dir, suitename): + def importee_dir(self, importer_dir, suitename): if self.suitenamemap.has_key(suitename): suitename = self.suitenamemap[suitename] if basename(importer_dir) == basename(self._primaryDir): @@ -703,7 +593,7 @@ else: return join(dirname(importer_dir), suitename) - def _nestedsuites_dirname(self): + def nestedsuites_dirname(self): return self._imported_suites_dirname() class PathSuiteModel(SuiteModel): @@ -722,13 +612,13 @@ suiteurl = pair[0] self.suit_to_url[suitename] = suiteurl - def _find_suite_dir(self, suitename): + def find_suite_dir(self, suitename): if self.suit_to_url.has_key(suitename): return self.suit_to_url[suitename] else: return None - def _importee_dir(self, importer_dir, suitename): + def importee_dir(self, importer_dir, suitename): if suitename in self.suit_to_url: return self.suit_to_url[suitename] else: @@ -740,7 +630,7 @@ self.version = version @staticmethod - def _parse_specification(specification): + def parse_specification(specification): pair = specification.split(',') name = pair[0] if len(pair) > 1: @@ -750,7 +640,7 @@ return SuiteImport(name, version) @staticmethod - def _tostring(name, version): + def tostring(name, version): return name + ',' + version def __str__(self): @@ -767,9 +657,6 @@ self.commands = None self.primary = primary self.name = _suitename(mxDir) # validated in _load_projects - self.version = None # _hg.tip checks current version if not None - # TODO this forces hg to be run every time mx is run - #self.version = _hg.tip(self, False) if load: # load suites bottom up to make sure command overriding works properly self._load_imports() @@ -780,6 +667,10 @@ def __str__(self): return self.name + def version(self, abortOnError=True): + # we do not cache the version + return _hg.tip(self.dir, abortOnError) + def _load_projects(self): libsMap = dict() projsMap = dict() @@ -877,7 +768,7 @@ abort('Missing "suite=" in ' + projectsFile) def _commands_name(self): - return 'mx_' + self.name + return 'mx_' + self.name.replace('-', '_') def _find_commands(self, name): commandsPath = join(self.mxDir, name + '.py') @@ -912,7 +803,7 @@ mod.mx_init(self) self.commands = mod - def _visit_imports(self, visitor, **extra_args): + def visit_imports(self, visitor, **extra_args): """ Visitor support for the imports file. For each line of the imports file that specifies an import, the visitor function is @@ -922,7 +813,7 @@ for writing a (possibly) updated import line to the file, and the file is (possibly) updated after all imports are processed. N.B. There is no built-in support for avoiding visiting the same suite multiple times, - as this function only visits the imports of a singkle suite. If a (recursive) visitor function + as this function only visits the imports of a single suite. If a (recursive) visitor function wishes to visit a suite exactly once, it must manage that through extra_args. """ importsFile = join(self.mxDir, 'imports') @@ -937,25 +828,25 @@ if out is not None: out.write(sline + '\n') continue - suite_import = SuiteImport._parse_specification(line.strip()) + suite_import = SuiteImport.parse_specification(line.strip()) visitor(self, suite_import, **extra_args) if out is not None: update_file(importsFile, out.getvalue()) @staticmethod - def _find_and_loadsuite(suite, suite_import, **extra_args): + def _find_and_loadsuite(importing_suite, suite_import, **extra_args): """visitor for the initial suite load""" - importMxDir = _src_suitemodel._find_suite_dir(suite_import.name) + importMxDir = _src_suitemodel.find_suite_dir(suite_import.name) if importMxDir is None: abort('import ' + suite_import.name + ' not found') - suite.imports.append(suite_import) - imported_suite = _loadSuite(importMxDir, False) - if imported_suite.version != suite.version: - warn('import version of ' + imported_suite.name +' does not match tip of ' + suite.version) + importing_suite.imports.append(suite_import) + _loadSuite(importMxDir, False) + # we do not check at this stage whether the tip version of imported_suite + # matches that of the import, since during development, this can and will change def _load_imports(self): - self._visit_imports(self._find_and_loadsuite) + self.visit_imports(self._find_and_loadsuite) def _load_env(self): e = join(self.mxDir, 'env') @@ -1320,7 +1211,7 @@ else: break - envPath = join(_mainSuite.mxDir, 'env') + envPath = join(_primary_suite.mxDir, 'env') if ask_yes_no('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath, 'y'): with open(envPath, 'a') as fp: print >> fp, 'JAVA_HOME=' + javaHome @@ -1341,6 +1232,7 @@ self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output') self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output') self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages') + self.add_argument('-p', '--primary-suite-path', help='set the primary suite directory', metavar='') self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on for a debugger', metavar='') self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"') self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='') @@ -1909,7 +1801,7 @@ javaCompliance = java().javaCompliance - defaultEcjPath = join(_mainSuite.mxDir, 'ecj.jar') + defaultEcjPath = join(_primary_suite.mxDir, 'ecj.jar') parser = parser if parser is not None else ArgumentParser(prog='mx build') parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)') @@ -2228,7 +2120,7 @@ if len(modified) != 0: if args.backup: backup = os.path.abspath('eclipseformat.backup.zip') - arcbase = _mainSuite.dir + arcbase = _primary_suite.dir zf = zipfile.ZipFile(backup, 'w', zipfile.ZIP_DEFLATED) for fi in modified: arcname = os.path.relpath(fi.path, arcbase).replace(os.sep, '/') @@ -2482,7 +2374,7 @@ self.path = path self.timestamp = os.path.getmtime(path) if exists(path) else None - def outOfDate(self, arg): + def isOlderThan(self, arg): if not self.timestamp: return True if isinstance(arg, types.ListType): @@ -2542,7 +2434,7 @@ timestamp = TimeStampFile(join(p.suite.mxDir, 'checkstyle-timestamps', sourceDir[len(p.suite.dir) + 1:].replace(os.sep, '_') + '.timestamp')) mustCheck = False if not args.force and timestamp.exists(): - mustCheck = timestamp.outOfDate(javafilelist) + mustCheck = timestamp.isOlderThan(javafilelist) else: mustCheck = True @@ -2853,7 +2745,7 @@ if refreshOnly and not timestamp.exists(): return - if not timestamp.outOfDate(projectsFile): + if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__): logv('[Eclipse configurations are up to date - skipping]') return @@ -3067,7 +2959,7 @@ launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'}) if logToFile: logFile = join(externalToolDir, name + '.log') - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile}) + launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile}) launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_APPEND_TO_FILE', 'value': 'true' if appendToLogFile else 'false'}) # expect to find the OS command to invoke mx in the same directory @@ -3125,7 +3017,7 @@ if os.environ.has_key('WORKSPACE'): expected_wsroot = os.environ['WORKSPACE'] else: - expected_wsroot = _mainSuite.dir + expected_wsroot = _primary_suite.dir wsroot = _find_eclipse_wsroot(expected_wsroot) if wsroot is None: @@ -3263,7 +3155,7 @@ if refreshOnly and not timestamp.exists(): return - if not timestamp.outOfDate(projectsFile): + if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__): logv('[NetBeans configurations are up to date - skipping]') return @@ -3529,8 +3421,8 @@ if '.hg' in dirnames: dirnames.remove('.hg') # if there are nested suites must not scan those now, as they are not in projectDirs - if _src_suitemodel._nestedsuites_dirname() in dirnames: - dirnames.remove(_src_suitemodel._nestedsuites_dirname()) + if _src_suitemodel.nestedsuites_dirname() in dirnames: + dirnames.remove(_src_suitemodel.nestedsuites_dirname()) elif dirpath in projectDirs: # don't traverse subdirs of an existing project in this suite dirnames[:] = [] @@ -3682,7 +3574,7 @@ names.append(p.name) links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/'] - out = join(_mainSuite.dir, docDir) + out = join(_primary_suite.dir, docDir) if args.base is not None: out = join(args.base, docDir) cp = classpath() @@ -3951,7 +3843,7 @@ def sclone(args): """clone a suite repository, and its imported suites""" - _hg.check(True) + _hg.check() parser = ArgumentParser(prog='mx sclone') parser.add_argument('--source', help='url/path of repo containing suite', metavar='') parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='') @@ -3968,11 +3860,11 @@ if args.source is None: # must be primary suite and dest is required - if _mainSuite is None: + if _primary_suite is None: abort('--source missing and no primary suite found') if args.dest is None: abort('--dest required when --source is not given') - source = _mainSuite.dir + source = _primary_suite.dir else: source = args.source @@ -3983,8 +3875,8 @@ dest = os.path.abspath(dest) # We can now set the primary dir for the src/dst suitemodel - _dst_suitemodel._set_primary_dir(dest) - _src_suitemodel._set_primary_dir(source) + _dst_suitemodel.set_primary_dir(dest) + _src_suitemodel.set_primary_dir(source) _sclone(source, dest, None, args.no_imports) @@ -4006,12 +3898,12 @@ # create a Suite (without loading) to enable imports visitor s = Suite(mxDir, False, load=False) if not no_imports: - s._visit_imports(_scloneimports_visitor, source=source) + s.visit_imports(_scloneimports_visitor, source=source) return s def _scloneimports_visitor(s, suite_import, source, **extra_args): """ - cloneimports visitor for Suite._visit_imports. + cloneimports visitor for Suite.visit_imports. The destination information is encapsulated by 's' """ _scloneimports(s, suite_import, source) @@ -4026,18 +3918,21 @@ def _scloneimports(s, suite_import, source): # clone first, then visit imports once we can locate them - importee_source = _src_suitemodel._importee_dir(source, suite_import.name) - importee_dest = _dst_suitemodel._importee_dir(s.dir, suite_import.name) + importee_source = _src_suitemodel.importee_dir(source, suite_import.name) + importee_dest = _dst_suitemodel.importee_dir(s.dir, suite_import.name) if exists(importee_dest): + # already exists in the suite model, but may be wrong version importee_suite = _scloneimports_suitehelper(importee_dest) - importee_suite._visit_imports(_scloneimports_visitor, source=importee_source) + if suite_import.version is not None and importee_suite.version() != suite_import.version: + abort("imported version of " + suite_import.name + " in " + s.name + " does not match the version in already existing suite: " + importee_suite.dir) + importee_suite.visit_imports(_scloneimports_visitor, source=importee_source) else: _sclone(importee_source, importee_dest, suite_import.version, False) # _clone handles the recursive visit of the new imports def scloneimports(args): """clone the imports of an existing suite""" - _hg.check(True) + _hg.check() parser = ArgumentParser(prog='mx scloneimports') parser.add_argument('--source', help='url/path of repo containing suite', metavar='') parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') @@ -4058,21 +3953,21 @@ # We can now set the primary dir for the dst suitemodel # N.B. source is effectively the destination and the default_path is the (original) source - _dst_suitemodel._set_primary_dir(args.source) - - s._visit_imports(_scloneimports_visitor, source=default_path) + _dst_suitemodel.set_primary_dir(args.source) + + s.visit_imports(_scloneimports_visitor, source=default_path) def _spush_import_visitor(s, suite_import, dest, checks, clonemissing, **extra_args): - """push visitor for Suite._visit_imports""" + """push visitor for Suite.visit_imports""" if dest is not None: - dest = _dst_suitemodel._importee_dir(dest, suite_import.name) + dest = _dst_suitemodel.importee_dir(dest, suite_import.name) _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing) def _spush_check_import_visitor(s, suite_import, **extra_args): - """push check visitor for Suite._visit_imports""" - currentTip = _hg.tip(suite(suite_import.name)) + """push check visitor for Suite.visit_imports""" + currentTip = suite(suite_import.name).version() if currentTip != suite_import.version: - abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') + abort('imported version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') def _spush(s, suite_import, dest, checks, clonemissing): if checks: @@ -4081,10 +3976,10 @@ # check imports first if checks: - s._visit_imports(_spush_check_import_visitor) + s.visit_imports(_spush_check_import_visitor) # ok, push imports - s._visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing) + s.visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing) dest_exists = True @@ -4116,7 +4011,7 @@ def spush(args): """push primary suite and all its imports""" - _hg.check(True) + _hg.check() parser = ArgumentParser(prog='mx spush') parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='') parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled') @@ -4139,7 +4034,7 @@ args.nochecks = True if args.dest is not None: - _dst_suitemodel._set_primary_dir(args.dest) + _dst_suitemodel.set_primary_dir(args.dest) _spush(s, None, args.dest, not args.no_checks, args.clonemissing) @@ -4147,29 +4042,29 @@ _supdate(suite(suite_import.name), suite_import) def _supdate(s, suite_import): - s._visit_imports(_supdate_import_visitor) + s.visit_imports(_supdate_import_visitor) run(['hg', '-R', s.dir, 'update']) def supdate(args): """update primary suite and all its imports""" - _hg.check(True) + _hg.check() s = _check_primary_suite() _supdate(s, None) def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports): - """checkimportversions visitor for Suite._visit_imports""" - _scheck_imports(suite(suite_import.name), suite_import, update_versions, updated_imports) - -def _scheck_imports(s, suite_import, update_versions, updated_imports): + """scheckimports visitor for Suite.visit_imports""" + _scheck_imports(s, suite(suite_import.name), suite_import, update_versions, updated_imports) + +def _scheck_imports(importing_suite, imported_suite, suite_import, update_versions, updated_imports): # check imports recursively - s._visit_imports(_scheck_imports_visitor, update_versions=update_versions) - - currentTip = _hg.tip(s) + imported_suite.visit_imports(_scheck_imports_visitor, update_versions=update_versions) + + currentTip = imported_suite.version() if currentTip != suite_import.version: - print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else '')) + print('imported version of ' + imported_suite.name + ' in ' + importing_suite.name + ' does not match tip' + (': updating' if update_versions else '')) if update_versions: suite_import.version = currentTip @@ -4181,25 +4076,25 @@ parser = ArgumentParser(prog='mx scheckimports') parser.add_argument('--update-versions', help='update imported version ids', action='store_true') args = parser.parse_args(args) - _check_primary_suite()._visit_imports(_scheck_imports_visitor, update_versions=args.update_versions) + _check_primary_suite().visit_imports(_scheck_imports_visitor, update_versions=args.update_versions) def _spull_import_visitor(s, suite_import, update_versions, updated_imports): - """pull visitor for Suite._visit_imports""" + """pull visitor for Suite.visit_imports""" _spull(suite(suite_import.name), update_versions, updated_imports) def _spull(s, update_versions, updated_imports): - _hg.check(True) + _hg.check() # pull imports first - s._visit_imports(_spull_import_visitor, update_versions=update_versions) + s.visit_imports(_spull_import_visitor, update_versions=update_versions) run(['hg', '-R', s.dir, 'pull', '-u']) if update_versions and updated_imports is not None: - tip = _hg.tip(s) - updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n') + tip = s.version() + updated_imports.write(SuiteImport.tostring(s.name, tip) + '\n') def spull(args): """pull primary suite and all its imports""" - _hg.check(True) + _hg.check() parser = ArgumentParser(prog='mx spull') parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites') args = parser.parse_args(args) @@ -4380,48 +4275,74 @@ return mxDir def _check_primary_suite(): - if _mainSuite is None: + if _primary_suite is None: abort('no primary suite found') else: - return _mainSuite + return _primary_suite def _needs_primary_suite(command): return not command.startswith("sclone") -def _findPrimarySuiteMxDir(): - # try current working directory first, the look up the tree - curdir = os.getcwd() - while curdir: - mxDir = _is_suite_dir(curdir) +def _needs_primary_suite_cl(): + return not any("sclone" in s for s in sys.argv[1:]) + +def _findPrimarySuiteMxDirFrom(d): + """ search for a suite directory upwards from 'd' """ + while d: + mxDir = _is_suite_dir(d) if mxDir is not None: return mxDir - parent = dirname(curdir) - if curdir == parent: + parent = dirname(d) + if d == parent: return None - curdir = parent + d = parent return None +def _findPrimarySuiteMxDir(): + # check for explicit setting + if _primary_suite_path is not None: + mxDir = _is_suite_dir(_primary_suite_path) + if mxDir is not None: + return mxDir + else: + abort(_primary_suite_path + ' does not contain an mx suite') + + # try current working directory first + mxDir = _findPrimarySuiteMxDirFrom(os.getcwd()) + if mxDir is not None: + return mxDir + # backwards compatibility: search from path of this file + return _findPrimarySuiteMxDirFrom(dirname(__file__)) + def main(): - SuiteModel._parse_options() + SuiteModel.parse_options() global _hg _hg = HgConfig() + primary_suite_error = 'no primary suite found' primarySuiteMxDir = _findPrimarySuiteMxDir() if primarySuiteMxDir: - _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir)) - global _mainSuite - _mainSuite = _loadSuite(primarySuiteMxDir, True) + _src_suitemodel.set_primary_dir(dirname(primarySuiteMxDir)) + global _primary_suite + _primary_suite = _loadSuite(primarySuiteMxDir, True) + else: + # in general this is an error, except for the sclone/scloneimports commands, + # and an extensions command will likely not parse in this case, as any extra arguments + # will not have been added to _argParser. + # If the command line does not contain a string matching one of the exceptions, we can safely abort, + # but not otherwise, as we can't be sure the string isn't in a value for some other option. + if _needs_primary_suite_cl(): + abort(primary_suite_error) opts, commandAndArgs = _argParser._parse_cmd_line() if primarySuiteMxDir is None: - msg = 'no primary suite found' if len(commandAndArgs) > 0 and _needs_primary_suite(commandAndArgs[0]): - abort(msg) + abort(primary_suite_error) else: - warn(msg) + warn(primary_suite_error) global _opts, _java _opts = opts diff -r cf6cfa79593d -r faded4a83d63 src/cpu/x86/vm/vmStructs_x86.hpp --- a/src/cpu/x86/vm/vmStructs_x86.hpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/cpu/x86/vm/vmStructs_x86.hpp Fri Oct 25 01:39:54 2013 +0200 @@ -43,7 +43,8 @@ #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ + declare_constant(frame::arg_reg_save_area_bytes) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) diff -r cf6cfa79593d -r faded4a83d63 src/gpu/ptx/vm/gpu_ptx.cpp --- a/src/gpu/ptx/vm/gpu_ptx.cpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/gpu/ptx/vm/gpu_ptx.cpp Fri Oct 25 01:39:54 2013 +0200 @@ -385,7 +385,7 @@ case T_INT: { int return_val; - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_INT_BYTE_SIZE); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status); return false; @@ -396,7 +396,7 @@ case T_BOOLEAN: { int return_val; - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_INT_BYTE_SIZE); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status); return false; @@ -407,7 +407,7 @@ case T_FLOAT: { float return_val; - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_FLOAT_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_FLOAT_BYTE_SIZE); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status); return false; @@ -418,7 +418,7 @@ case T_DOUBLE: { double return_val; - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_DOUBLE_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_DOUBLE_BYTE_SIZE); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status); return false; @@ -429,7 +429,7 @@ case T_LONG: { long return_val; - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_LONG_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_LONG_BYTE_SIZE); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status); return false; @@ -443,11 +443,11 @@ tty->print_cr("[CUDA] TODO *** Unhandled return type: %d", return_type); } - // handle post-invocation object and array arguemtn - ptxka.reiterate(); + // Copy all reference arguments from device to host memory. + ptxka.copyRefArgsFromDtoH(); // Free device memory allocated for result - status = gpu::Ptx::_cuda_cu_memfree(ptxka._return_value_ptr); + status = gpu::Ptx::_cuda_cu_memfree(ptxka._dev_return_value); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to free device memory of return value", status); return false; diff -r cf6cfa79593d -r faded4a83d63 src/gpu/ptx/vm/ptxKernelArguments.cpp --- a/src/gpu/ptx/vm/ptxKernelArguments.cpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/gpu/ptx/vm/ptxKernelArguments.cpp Fri Oct 25 01:39:54 2013 +0200 @@ -32,127 +32,132 @@ // Get next java argument oop PTXKernelArguments::next_arg(BasicType expectedType) { assert(_index < _args->length(), "out of bounds"); - oop arg = ((objArrayOop) (_args))->obj_at(_index++); assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); - return arg; } void PTXKernelArguments::do_int() { - if (is_after_invocation()) { + // If the parameter is a return value, + if (is_return_type()) { + if (is_kernel_arg_setup()) { + // Allocate device memory for T_INT return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_INT_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // If the parameter is a return value, - if (is_return_type()) { - // Allocate device memory for T_INT return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_INT_BYTE_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); - } else { - // Get the next java argument and its value which should be a T_INT - oop arg = next_arg(T_INT); - // Copy the java argument value to kernelArgBuffer - jvalue intval; - if (java_lang_boxing_object::get_value(arg, &intval) != T_INT) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = intval.i; - _bufferOffset += sizeof(intval.i); + _bufferOffset += sizeof(_dev_return_value); + } else { + // Get the next java argument and its value which should be a T_INT + oop arg = next_arg(T_INT); + // Copy the java argument value to kernelArgBuffer + jvalue intval; + if (java_lang_boxing_object::get_value(arg, &intval) != T_INT) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT"); + _success = false; + return; } - return; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = intval.i; + } + // Advance _bufferOffset + _bufferOffset += sizeof(intval.i); + } + return; } void PTXKernelArguments::do_float() { - if (is_after_invocation()) { + // If the parameter is a return value, + if (is_return_type()) { + if (is_kernel_arg_setup()) { + // Allocate device memory for T_INT return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_FLOAT_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // If the parameter is a return value, - if (is_return_type()) { - // Allocate device memory for T_INT return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_FLOAT_BYTE_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); - } else { - // Get the next java argument and its value which should be a T_INT - oop arg = next_arg(T_FLOAT); - // Copy the java argument value to kernelArgBuffer - jvalue floatval; - if (java_lang_boxing_object::get_value(arg, &floatval) != T_FLOAT) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) floatval.f; - _bufferOffset += sizeof(floatval.f); + // Advance _bufferOffset + _bufferOffset += sizeof(_dev_return_value); + } else { + // Get the next java argument and its value which should be a T_FLOAT + oop arg = next_arg(T_FLOAT); + // Copy the java argument value to kernelArgBuffer + jvalue floatval; + if (java_lang_boxing_object::get_value(arg, &floatval) != T_FLOAT) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_FLOAT"); + _success = false; + return; } - return; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) floatval.f; + } + // Advance _bufferOffset + _bufferOffset += sizeof(floatval.f); + } + return; } void PTXKernelArguments::do_double() { - if (is_after_invocation()) { + // If the parameter is a return value, + jvalue doubleval; + if (is_return_type()) { + if (is_kernel_arg_setup()) { + // Allocate device memory for T_INT return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_DOUBLE_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // If the parameter is a return value, - jvalue doubleval; - if (is_return_type()) { - // Allocate device memory for T_INT return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_DOUBLE_BYTE_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - // _bufferOffset += sizeof(_return_value_ptr); - _bufferOffset += sizeof(doubleval.d); - } else { - // Get the next java argument and its value which should be a T_INT - oop arg = next_arg(T_FLOAT); - // Copy the java argument value to kernelArgBuffer - if (java_lang_boxing_object::get_value(arg, &doubleval) != T_DOUBLE) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) doubleval.d; - _bufferOffset += sizeof(doubleval.d); + // Advance _bufferOffset + _bufferOffset += sizeof(doubleval.d); + } else { + // Get the next java argument and its value which should be a T_INT + oop arg = next_arg(T_FLOAT); + // Copy the java argument value to kernelArgBuffer + if (java_lang_boxing_object::get_value(arg, &doubleval) != T_DOUBLE) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT"); + _success = false; + return; } - return; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) doubleval.d; + } + // Advance _bufferOffset + _bufferOffset += sizeof(doubleval.d); + } + return; } void PTXKernelArguments::do_long() { - if (is_after_invocation()) { - return; - } // If the parameter is a return value, if (is_return_type()) { - // Allocate device memory for T_LONG return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_LONG_BYTE_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; + if (is_kernel_arg_setup()) { + // Allocate device memory for T_LONG return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_LONG_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; + return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); + // Advance _bufferOffset + _bufferOffset += sizeof(_dev_return_value); } else { // Get the next java argument and its value which should be a T_LONG oop arg = next_arg(T_LONG); @@ -163,119 +168,132 @@ _success = false; return; } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.j; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.j; + } + // Advance _bufferOffset _bufferOffset += sizeof(val.j); } return; } void PTXKernelArguments::do_byte() { - if (is_after_invocation()) { + // If the parameter is a return value, + if (is_return_type()) { + if (is_kernel_arg_setup()) { + // Allocate device memory for T_BYTE return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // If the parameter is a return value, - if (is_return_type()) { - // Allocate device memory for T_BYTE return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BYTE_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); - } else { - // Get the next java argument and its value which should be a T_BYTE - oop arg = next_arg(T_BYTE); - // Copy the java argument value to kernelArgBuffer - jvalue val; - if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b; - _bufferOffset += sizeof(val.b); + // Advance _bufferOffset + _bufferOffset += sizeof(_dev_return_value); + } else { + // Get the next java argument and its value which should be a T_BYTE + oop arg = next_arg(T_BYTE); + // Copy the java argument value to kernelArgBuffer + jvalue val; + if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); + _success = false; + return; } - return; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b; + } + // Advance _bufferOffset + _bufferOffset += sizeof(val.b); + } + return; } void PTXKernelArguments::do_bool() { - if (is_after_invocation()) { + // If the parameter is a return value, + if (is_return_type()) { + if (is_kernel_arg_setup()) { + // Allocate device memory for T_BYTE return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_BOOLEAN_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; return; + } + // Push _dev_return_value to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value; } - // If the parameter is a return value, - if (is_return_type()) { - // Allocate device memory for T_BYTE return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BOOLEAN_SIZE); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); - } else { - // Get the next java argument and its value which should be a T_BYTE - oop arg = next_arg(T_BYTE); - // Copy the java argument value to kernelArgBuffer - jvalue val; - if (java_lang_boxing_object::get_value(arg, &val) != T_BOOLEAN) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.z; - _bufferOffset += sizeof(val.z); + // Advance _bufferOffset + _bufferOffset += sizeof(_dev_return_value); + } else { + // Get the next java argument and its value which should be a T_BYTE + oop arg = next_arg(T_BYTE); + // Copy the java argument value to kernelArgBuffer + jvalue val; + if (java_lang_boxing_object::get_value(arg, &val) != T_BOOLEAN) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); + _success = false; + return; } - return; + if (is_kernel_arg_setup()) { + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.z; + } + // Advance _bufferOffset + _bufferOffset += sizeof(val.z); + } + return; } void PTXKernelArguments::do_array(int begin, int end) { - gpu::Ptx::CUdeviceptr _array_ptr; - int status; - - // Get the next java argument and its value which should be a T_ARRAY - oop arg = next_arg(T_OBJECT); - int array_size = arg->size() * HeapWordSize; + // Get the next java argument and its value which should be a T_ARRAY + oop arg = next_arg(T_OBJECT); + assert(arg->is_array(), "argument value not an array"); + // Size of array argument + int argSize = arg->size() * HeapWordSize; + // Device pointer to array argument. + gpu::Ptx::CUdeviceptr arrayArgOnDev; + int status; - if (is_after_invocation()) { - _array_ptr = *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]); - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(arg, _array_ptr, array_size); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument to host", status); - _success = false; - return; - } else { - // tty->print_cr("device: %x host: %x size: %d", _array_ptr, arg, array_size); - } - return; + if (is_kernel_arg_setup()) { + // Allocate device memory for array argument on device. Size in bytes + status = gpu::Ptx::_cuda_cu_memalloc(&arrayArgOnDev, argSize); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for array argument on device", + status); + _success = false; + return; } - // Allocate device memory for T_ARRAY return value pointer on device. Size in bytes - status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, array_size); - if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; - } - status = gpu::Ptx::_cuda_cu_memcpy_htod(_return_value_ptr, arg, array_size); + // Copy array argument to device + status = gpu::Ptx::_cuda_cu_memcpy_htod(arrayArgOnDev, arg, argSize); if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to copy array to device argument", status); - _success = false; - return; - } else { - // tty->print_cr("host: %x device: %x size: %d", arg, _return_value_ptr, array_size); + tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument content to device memory", + status); + _success = false; + return; } - // Push _return_value_ptr to _kernelBuffer - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; - _bufferOffset += sizeof(_return_value_ptr); - return; + + // Push device array argument to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = arrayArgOnDev; + } else { + arrayArgOnDev = *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(arg, arrayArgOnDev, argSize); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument to host", status); + _success = false; + return; + } + } + + // Advance _bufferOffset + _bufferOffset += sizeof(arrayArgOnDev); + return; } void PTXKernelArguments::do_void() { - return; + return; } // TODO implement other do_* diff -r cf6cfa79593d -r faded4a83d63 src/gpu/ptx/vm/ptxKernelArguments.hpp --- a/src/gpu/ptx/vm/ptxKernelArguments.hpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/gpu/ptx/vm/ptxKernelArguments.hpp Fri Oct 25 01:39:54 2013 +0200 @@ -42,7 +42,13 @@ char _kernelArgBuffer[1024]; // Current offset into _kernelArgBuffer size_t _bufferOffset; - gpu::Ptx::CUdeviceptr _return_value_ptr; + // Device pointer holding return value + gpu::Ptx::CUdeviceptr _dev_return_value; + + // Indicates if signature iteration is being done during kernel + // setup i.e., java arguments are being copied to device pointers. + bool _kernelArgSetup; + private: // Array of java argument oops arrayOop _args; @@ -51,7 +57,6 @@ // Flag to indicate successful creation of kernel argument buffer bool _success; - bool _afterInvoocation; // Get next java argument oop next_arg(BasicType expectedType); @@ -62,7 +67,9 @@ _args = args; _success = true; _bufferOffset = 0; - _return_value_ptr = 0; + _dev_return_value = 0; + _kernelArgSetup = true; + //_dev_call_by_reference_args_index = 0; if (!is_static) { // TODO : Create a device argument for receiver object and add it to _kernelBuffer tty->print_cr("{CUDA] ****** TODO: Support for execution of non-static java methods not implemented yet."); @@ -80,23 +87,23 @@ return _bufferOffset; } - void reiterate() { - _afterInvoocation = true; - _bufferOffset = 0; - _index = 0; - iterate(); - } + void copyRefArgsFromDtoH() { + _kernelArgSetup = false; + _bufferOffset = 0; + _index = 0; + iterate(); + } - inline bool is_after_invocation() { - return _afterInvoocation; - } + inline bool is_kernel_arg_setup() { + return _kernelArgSetup; + } // Get the return oop value oop get_return_oop(); // get device return value ptr - gpu::Ptx::CUdeviceptr get_return_value_ptr() { - return _return_value_ptr; + gpu::Ptx::CUdeviceptr get_dev_return_value() { + return _dev_return_value; } diff -r cf6cfa79593d -r faded4a83d63 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Fri Oct 25 01:39:54 2013 +0200 @@ -32,6 +32,7 @@ import com.sun.hotspot.igv.graph.InputSlot; import java.awt.Color; import java.util.List; +import java.util.regex.Pattern; /** * Filter that colors usage and successor edges differently. @@ -55,6 +56,7 @@ @Override public void apply(Diagram d) { List

figures = d.getFigures(); + Pattern ndf = Pattern.compile(".*#NDF(\\[[0-9]*\\])?"); for (Figure f : figures) { Properties p = f.getProperties(); int predCount; @@ -78,7 +80,7 @@ is.setColor(color); for (Connection c : is.getConnections()) { - if (c.getLabel() == null || !c.getLabel().endsWith("#NDF")) { + if (c.getLabel() == null || !ndf.matcher(c.getLabel()).matches()) { c.setColor(color); if (c.getStyle() != ConnectionStyle.DASHED) { c.setStyle(style); diff -r cf6cfa79593d -r faded4a83d63 src/share/tools/IdealGraphVisualizer/nbproject/project.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Fri Oct 25 01:39:54 2013 +0200 @@ -40,5 +40,5 @@ # Disable assertions for RequestProcessor to prevent annoying messages in case # of multiple SceneAnimator update tasks in the default RequestProcessor. -run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx4g +run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor diff -r cf6cfa79593d -r faded4a83d63 src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Fri Oct 25 01:39:54 2013 +0200 @@ -491,9 +491,7 @@ // Total number of GC collections (started) unsigned int total_collections() const { return _total_collections; } unsigned int total_full_collections() const { return _total_full_collections;} -#ifdef GRAAL - unsigned int* total_collections_address() { return &_total_collections;} -#endif + // Increment total number of GC collections (started) // Should be protected but used by PSMarkSweep - cleanup for 1.4.2 void increment_total_collections(bool full = false) { diff -r cf6cfa79593d -r faded4a83d63 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Oct 25 01:39:54 2013 +0200 @@ -38,6 +38,8 @@ #include "graal/graalCodeInstaller.hpp" #include "graal/graalVMToCompiler.hpp" #include "gc_implementation/g1/heapRegion.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/vmStructs.hpp" Method* getMethodFromHotSpotMethod(oop hotspot_method) { @@ -307,11 +309,6 @@ return code == NULL ? 0 : code->insts_size(); C2V_END -C2V_VMENTRY(jint, constantPoolLength, (JNIEnv *env, jobject, jobject type)) - ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - return cp->length(); -C2V_END - C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) ResourceMark rm; @@ -547,12 +544,14 @@ return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); C2V_END +// TODO move to Java C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); return InstanceKlass::cast(klass)->is_initialized(); C2V_END +// TODO move to Java C2V_VMENTRY(jboolean, isTypeLinked,(JNIEnv *, jobject, jobject hotspot_klass)) Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); @@ -642,152 +641,120 @@ return id; } +C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject, jlong metaspace_method)) + methodHandle method = asMethod(metaspace_method); + method->set_not_c1_compilable(); + method->set_not_c2_compilable(); + method->set_dont_inline(true); +C2V_END + +extern "C" { +extern VMStructEntry* gHotSpotVMStructs; +extern uint64_t gHotSpotVMStructEntryTypeNameOffset; +extern uint64_t gHotSpotVMStructEntryFieldNameOffset; +extern uint64_t gHotSpotVMStructEntryTypeStringOffset; +extern uint64_t gHotSpotVMStructEntryIsStaticOffset; +extern uint64_t gHotSpotVMStructEntryOffsetOffset; +extern uint64_t gHotSpotVMStructEntryAddressOffset; +extern uint64_t gHotSpotVMStructEntryArrayStride; + +extern VMTypeEntry* gHotSpotVMTypes; +extern uint64_t gHotSpotVMTypeEntryTypeNameOffset; +extern uint64_t gHotSpotVMTypeEntrySuperclassNameOffset; +extern uint64_t gHotSpotVMTypeEntryIsOopTypeOffset; +extern uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset; +extern uint64_t gHotSpotVMTypeEntryIsUnsignedOffset; +extern uint64_t gHotSpotVMTypeEntrySizeOffset; +extern uint64_t gHotSpotVMTypeEntryArrayStride; + +extern VMIntConstantEntry* gHotSpotVMIntConstants; +extern uint64_t gHotSpotVMIntConstantEntryNameOffset; +extern uint64_t gHotSpotVMIntConstantEntryValueOffset; +extern uint64_t gHotSpotVMIntConstantEntryArrayStride; + +extern VMLongConstantEntry* gHotSpotVMLongConstants; +extern uint64_t gHotSpotVMLongConstantEntryNameOffset; +extern uint64_t gHotSpotVMLongConstantEntryValueOffset; +extern uint64_t gHotSpotVMLongConstantEntryArrayStride; +} + C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) #define set_address(name, value) do { set_long(name, (jlong) value); } while (0) -#define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong"); - set_boolean("cAssertions", DEBUG_ONLY(true) NOT_DEBUG(false)); - set_int("codeEntryAlignment", CodeEntryAlignment); - set_int("hubOffset", oopDesc::klass_offset_in_bytes()); - set_int("markOffset", oopDesc::mark_offset_in_bytes()); - set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); - set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); - set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); - set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); - set_int("subklassOffset", in_bytes(Klass::subklass_offset())); - set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); + set_address("gHotSpotVMStructs", gHotSpotVMStructs); + set_long("gHotSpotVMStructEntryTypeNameOffset", gHotSpotVMStructEntryTypeNameOffset); + set_long("gHotSpotVMStructEntryFieldNameOffset", gHotSpotVMStructEntryFieldNameOffset); + set_long("gHotSpotVMStructEntryTypeStringOffset", gHotSpotVMStructEntryTypeStringOffset); + set_long("gHotSpotVMStructEntryIsStaticOffset", gHotSpotVMStructEntryIsStaticOffset); + set_long("gHotSpotVMStructEntryOffsetOffset", gHotSpotVMStructEntryOffsetOffset); + set_long("gHotSpotVMStructEntryAddressOffset", gHotSpotVMStructEntryAddressOffset); + set_long("gHotSpotVMStructEntryArrayStride", gHotSpotVMStructEntryArrayStride); + + set_address("gHotSpotVMTypes", gHotSpotVMTypes); + set_long("gHotSpotVMTypeEntryTypeNameOffset", gHotSpotVMTypeEntryTypeNameOffset); + set_long("gHotSpotVMTypeEntrySuperclassNameOffset", gHotSpotVMTypeEntrySuperclassNameOffset); + set_long("gHotSpotVMTypeEntryIsOopTypeOffset", gHotSpotVMTypeEntryIsOopTypeOffset); + set_long("gHotSpotVMTypeEntryIsIntegerTypeOffset", gHotSpotVMTypeEntryIsIntegerTypeOffset); + set_long("gHotSpotVMTypeEntryIsUnsignedOffset", gHotSpotVMTypeEntryIsUnsignedOffset); + set_long("gHotSpotVMTypeEntrySizeOffset", gHotSpotVMTypeEntrySizeOffset); + set_long("gHotSpotVMTypeEntryArrayStride", gHotSpotVMTypeEntryArrayStride); + + set_address("gHotSpotVMIntConstants", gHotSpotVMIntConstants); + set_long("gHotSpotVMIntConstantEntryNameOffset", gHotSpotVMIntConstantEntryNameOffset); + set_long("gHotSpotVMIntConstantEntryValueOffset", gHotSpotVMIntConstantEntryValueOffset); + set_long("gHotSpotVMIntConstantEntryArrayStride", gHotSpotVMIntConstantEntryArrayStride); + + set_address("gHotSpotVMLongConstants", gHotSpotVMLongConstants); + set_long("gHotSpotVMLongConstantEntryNameOffset", gHotSpotVMLongConstantEntryNameOffset); + set_long("gHotSpotVMLongConstantEntryValueOffset", gHotSpotVMLongConstantEntryValueOffset); + set_long("gHotSpotVMLongConstantEntryArrayStride", gHotSpotVMLongConstantEntryArrayStride); + + //------------------------------------------------------------------------------------------------ + set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); - set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); - set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); - set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); - set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); - set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); - set_int("threadIsMethodHandleReturnOffset", in_bytes(JavaThread::is_method_handle_return_offset())); - set_int("osThreadOffset", in_bytes(JavaThread::osthread_offset())); - set_int("osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset())); - set_int("unlockedMask", (int) markOopDesc::unlocked_value); - set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); - set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place); - set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); - set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern); - set_int("methodMaxLocalsOffset", in_bytes(ConstMethod::size_of_locals_offset())); - set_int("methodConstMethodOffset", in_bytes(Method::const_offset())); - set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset())); - set_int("constMethodConstantsOffset", in_bytes(ConstMethod::constants_offset())); - set_int("constantPoolHolderOffset", ConstantPool::pool_holder_offset_in_bytes()); + set_int("extraStackEntries", Method::extra_stack_entries()); - set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); - set_int("methodQueuedForCompilationBit", (int) JVM_ACC_QUEUED); - set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes()); - set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); - set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); - set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_long("safepointPollingAddress", (jlong)(os::get_polling_page())); -#ifdef TARGET_ARCH_x86 - set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); - set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); -#endif - set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); - set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); - set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); - set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); - set_int("arrayKlassOffset", java_lang_Class::array_klass_offset_in_bytes()); - set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); - set_int("klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset())); - set_int("klassSuperKlassOffset", in_bytes(Klass::super_offset())); - set_int("methodDataOffset", in_bytes(Method::method_data_offset())); - set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset()); - set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); - set_int("basicLockSize", sizeof(BasicLock)); - set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); - set_int("uninitializedIdentityHashCodeValue", markOopDesc::no_hash); - set_int("identityHashCodeShift", markOopDesc::hash_shift); - - set_int("arrayKlassLayoutHelperIdentifier", 0x80000000); - assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set"); - set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); - - - set_int("pendingExceptionOffset", in_bytes(ThreadShadow::pending_exception_offset())); - set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset())); - - set_int("metaspaceArrayLengthOffset", Array::length_offset_in_bytes()); - set_int("metaspaceArrayBaseOffset", Array::base_offset_in_bytes()); - set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset())); - set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); - set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); - set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); - set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); - set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); - set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); - set_int("dataLayoutCellSize", DataLayout::cell_size); set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); - set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr()); - set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset())); - set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); - set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); - set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset())); - set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset())); -#ifdef TARGET_ARCH_x86 - set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset())); -#endif -#ifdef TARGET_ARCH_sparc - set_int("threadJavaFrameAnchorFlagsOffset", in_bytes(JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset())); -#endif - set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset())); - set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); - set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset())); - set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset())); - set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset())); - set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); - set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset())); + set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc()); - set_address("nonOopBits", Universe::non_oop_word()); - set_long("verifyOopCounterAddress", (jlong)(address) StubRoutines::verify_oop_count_addr()); set_long("verifyOopMask", Universe::verify_oop_mask()); set_long("verifyOopBits", Universe::verify_oop_bits()); - set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype()); - set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift); - set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); - set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); - set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); - // this filters out the bit that differentiates a type array from an object array - set_int("layoutHelperElementTypePrimitiveInPlace", (Klass::_lh_array_tag_type_value & ~Klass::_lh_array_tag_obj_value) << Klass::_lh_array_tag_shift); - set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); - set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); - set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); + set_int("instanceKlassVtableStartOffset", InstanceKlass::vtable_start_offset() * HeapWordSize); + + //------------------------------------------------------------------------------------------------ + + set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); + set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap()); - set_address("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub()); - set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); - set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); - set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); - set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); - set_address("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt()); - set_address("updateBytesCRC32Stub", StubRoutines::updateBytesCRC32()); + set_address("registerFinalizerAddress", SharedRuntime::register_finalizer); + set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address); + set_address("osrMigrationEndAddress", SharedRuntime::OSR_migration_end); + + set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); + set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); + set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); + set_address("arithmeticCosAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); + set_address("arithmeticTanAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); set_address("newInstanceAddress", GraalRuntime::new_instance); set_address("newArrayAddress", GraalRuntime::new_array); set_address("newMultiArrayAddress", GraalRuntime::new_multi_array); set_address("dynamicNewArrayAddress", GraalRuntime::dynamic_new_array); - set_address("registerFinalizerAddress", SharedRuntime::register_finalizer); set_address("threadIsInterruptedAddress", GraalRuntime::thread_is_interrupted); - set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap()); set_address("vmMessageAddress", GraalRuntime::vm_message); set_address("identityHashCodeAddress", GraalRuntime::identity_hash_code); set_address("exceptionHandlerForPcAddress", GraalRuntime::exception_handler_for_pc); - set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address); - set_address("osrMigrationEndAddress", SharedRuntime::OSR_migration_end); set_address("monitorenterAddress", GraalRuntime::monitorenter); set_address("monitorexitAddress", GraalRuntime::monitorexit); set_address("createNullPointerExceptionAddress", GraalRuntime::create_null_exception); @@ -797,82 +764,11 @@ set_address("logPrintfAddress", GraalRuntime::log_printf); set_address("vmErrorAddress", GraalRuntime::vm_error); set_address("loadAndClearExceptionAddress", GraalRuntime::load_and_clear_exception); - set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); - set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); - set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); - set_address("arithmeticCosAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); - set_address("arithmeticTanAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); - set_address("crcTableAddress", StubRoutines::crc_table_addr()); - - set_int("deoptReasonNone", Deoptimization::Reason_none); - set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check); - set_int("deoptReasonRangeCheck", Deoptimization::Reason_range_check); - set_int("deoptReasonClassCheck", Deoptimization::Reason_class_check); - set_int("deoptReasonArrayCheck", Deoptimization::Reason_array_check); - set_int("deoptReasonUnreached0", Deoptimization::Reason_unreached0); - set_int("deoptReasonTypeCheckInlining", Deoptimization::Reason_type_checked_inlining); - set_int("deoptReasonOptimizedTypeCheck", Deoptimization::Reason_optimized_type_check); - set_int("deoptReasonNotCompiledExceptionHandler", Deoptimization::Reason_not_compiled_exception_handler); - set_int("deoptReasonUnresolved", Deoptimization::Reason_unresolved); - set_int("deoptReasonJsrMismatch", Deoptimization::Reason_jsr_mismatch); - set_int("deoptReasonDiv0Check", Deoptimization::Reason_div0_check); - set_int("deoptReasonConstraint", Deoptimization::Reason_constraint); - set_int("deoptReasonLoopLimitCheck", Deoptimization::Reason_loop_limit_check); - - set_int("deoptActionNone", Deoptimization::Action_none); - set_int("deoptActionMaybeRecompile", Deoptimization::Action_maybe_recompile); - set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret); - set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant); - set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable); - - set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic); - set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual); - set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic); - set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial); - set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface); - - set_address("narrowOopBase", Universe::narrow_oop_base()); - set_int("narrowOopShift", Universe::narrow_oop_shift()); - set_address("narrowKlassBase", Universe::narrow_klass_base()); - set_int("narrowKlassShift", Universe::narrow_klass_shift()); - set_int("logKlassAlignment", LogKlassAlignmentInBytes); - - - set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index())); - set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf())); - set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes); - set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active())); - set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index())); - set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf())); set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre); set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post); - set_address("gcTotalCollectionsAddress", (jlong)(address)(Universe::heap()->total_collections_address())); set_address("validateObject", GraalRuntime::validate_object); - BarrierSet* bs = Universe::heap()->barrier_set(); - switch (bs->kind()) { - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging:{ - jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; - assert(base != 0, "unexpected byte_map_base"); - set_long("cardtableStartAddress", base); - set_int("cardtableShift", CardTableModRefBS::card_shift); - break; - } - case BarrierSet::ModRef: - case BarrierSet::Other: - set_long("cardtableStartAddress", 0); - set_int("cardtableShift", 0); - // No post barriers - break; - default: - ShouldNotReachHere(); - break; - } - - set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); + //------------------------------------------------------------------------------------------------ set_int("graalCountersThreadOffset", in_bytes(JavaThread::graal_counters_offset())); set_int("graalCountersSize", (jint) GRAAL_COUNTERS_SIZE); @@ -880,7 +776,6 @@ #undef set_boolean #undef set_int #undef set_long -#undef set_object C2V_END @@ -996,26 +891,6 @@ } C2V_END -C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) - - Method* method = asMethod(metaspace_method); - assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods"); - assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked"); - assert(method->vtable_index() >= 0, "vtable entry offset should not be used"); - - // get entry offset in words - int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size(); - // convert to bytes - vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); - - return vtable_entry_offset; -C2V_END - -C2V_VMENTRY(jboolean, hasVtableEntry, (JNIEnv *, jobject, jlong metaspace_method)) - Method* method = asMethod(metaspace_method); - return method->vtable_index() >= 0; -C2V_END - C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject)) // the contract for this method is as follows: @@ -1138,7 +1013,7 @@ C2V_VMENTRY(jobject, readUnsafeUncompressedPointer, (JNIEnv *env, jobject, jobject o, jlong offset)) oop resolved_o = JNIHandles::resolve(o); - address addr = offset + (address)resolved_o; + address addr = ((address)resolved_o) + offset; return JNIHandles::make_local(*((oop*)addr)); C2V_END @@ -1196,12 +1071,10 @@ {CC"getUniqueImplementor", CC"("HS_RESOLVED_TYPE")"RESOLVED_TYPE, FN_PTR(getUniqueImplementor)}, {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, {CC"initializeMethod", CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V", FN_PTR(initializeMethod)}, + {CC"doNotInlineOrCompile", CC"("METASPACE_METHOD")V", FN_PTR(doNotInlineOrCompile)}, {CC"initializeMethodData", CC"("METASPACE_METHOD_DATA METHOD_DATA")V", FN_PTR(initializeMethodData)}, {CC"isMethodCompilable", CC"("METASPACE_METHOD")Z", FN_PTR(isMethodCompilable)}, {CC"getCompiledCodeSize", CC"("METASPACE_METHOD")I", FN_PTR(getCompiledCodeSize)}, - {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, - {CC"hasVtableEntry", CC"("METASPACE_METHOD")Z", FN_PTR(hasVtableEntry)}, - {CC"constantPoolLength", CC"("HS_RESOLVED_TYPE")I", FN_PTR(constantPoolLength)}, {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"IB)"OBJECT, FN_PTR(lookupAppendixInPool)}, diff -r cf6cfa79593d -r faded4a83d63 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Oct 25 01:39:54 2013 +0200 @@ -85,6 +85,7 @@ start_class(HotSpotNmethod) \ boolean_field(HotSpotNmethod, isDefault) \ boolean_field(HotSpotNmethod, isExternal) \ + oop_field(HotSpotNmethod, name, "Ljava/lang/String;") \ end_class \ start_class(HotSpotCompiledCode) \ oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ diff -r cf6cfa79593d -r faded4a83d63 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Oct 25 01:39:54 2013 +0200 @@ -89,6 +89,7 @@ #ifdef GRAAL #include "graal/graalCompiler.hpp" +#include "graal/graalJavaAccess.hpp" #endif @@ -1420,6 +1421,19 @@ if (TraceDeoptimization) { // make noise on the tty tty->print("Uncommon trap occurred in"); nm->method()->print_short_name(tty); +#ifdef GRAAL + oop installedCode = nm->graal_installed_code(); + if (installedCode != NULL) { + oop installedCodeName = HotSpotNmethod::name(installedCode); + if (installedCodeName != NULL) { + tty->print(" (Graal: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName)); + } else { + tty->print(" (Graal: installed code has no name) "); + } + } else if (nm->is_compiled_by_graal()) { + tty->print(" (Graal: no installed code) "); + } +#endif //GRAAL tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d", fr.pc(), os::current_thread_id(), diff -r cf6cfa79593d -r faded4a83d63 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Tue Oct 22 15:06:02 2013 +0200 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Oct 25 01:39:54 2013 +0200 @@ -563,6 +563,8 @@ nonstatic_field(Space, _bottom, HeapWord*) \ nonstatic_field(Space, _end, HeapWord*) \ \ + static_field(HeapRegion, LogOfHRGrainBytes, int) \ + \ nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \ @@ -890,6 +892,7 @@ static_field(Threads, _return_code, int) \ \ nonstatic_field(ThreadShadow, _pending_exception, oop) \ + nonstatic_field(ThreadShadow, _pending_deoptimization, int) \ nonstatic_field(ThreadShadow, _exception_file, const char*) \ nonstatic_field(ThreadShadow, _exception_line, int) \ volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \ @@ -1243,6 +1246,7 @@ static_field(java_lang_Class, _array_klass_offset, int) \ static_field(java_lang_Class, _oop_size_offset, int) \ static_field(java_lang_Class, _static_oop_field_count_offset, int) \ + GRAAL_ONLY(static_field(java_lang_Class, _graal_mirror_offset, int)) \ \ /************************/ \ /* Miscellaneous fields */ \ @@ -1482,6 +1486,8 @@ declare_type(EdenSpace, ContiguousSpace) \ declare_type(OffsetTableContigSpace, ContiguousSpace) \ declare_type(TenuredSpace, OffsetTableContigSpace) \ + declare_type(G1OffsetTableContigSpace, ContiguousSpace) \ + declare_type(HeapRegion, G1OffsetTableContigSpace) \ declare_toplevel_type(BarrierSet) \ declare_type(ModRefBarrierSet, BarrierSet) \ declare_type(CardTableModRefBS, ModRefBarrierSet) \