# HG changeset patch # User Thomas Wuerthinger # Date 1307735539 -7200 # Node ID c76db61fbb73204f90fed308f9df602593d77c15 # Parent e86e83c5adbc41b3e978a74a552fb699b107c97a# Parent 668603cb3263109f5a7d181ad3c47c14ab196147 Merge. diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jun 10 21:52:19 2011 +0200 @@ -55,6 +55,7 @@ public static boolean ZapStackOnMethodEntry = ____; public static boolean StressLinearScan = ____; public static boolean BailoutOnException = ____; + public static boolean DeoptALot = ____; /** * See {@link Filter#Filter(String, Object)}. @@ -104,8 +105,9 @@ // Code generator settings public static boolean GenLIR = true; public static boolean GenCode = true; + public static boolean UseBranchPrediction = ____; - public static boolean UseConstDirectCall = false; + public static boolean UseConstDirectCall = ____; public static boolean GenSpecialDivChecks = ____; public static boolean GenAssertionCode = ____; diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jun 10 21:52:19 2011 +0200 @@ -164,7 +164,12 @@ assert lastOp instanceof LIRBranch : "branch must be of type LIRBranch"; LIRBranch lastBranch = (LIRBranch) lastOp; - assert lastBranch.block() != null : "last branch must always have a block as target"; + if (lastBranch.block() == null) { + // this might target a deoptimization stub... + // TODO check if the target is really a deopt stub... +// assert lastBranch.block() != null : "last branch must always have a block as target, current block #" + block.blockID(); + continue; + } assert lastBranch.label() == lastBranch.block().label() : "must be equal"; if (lastBranch.info == null) { diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jun 10 21:52:19 2011 +0200 @@ -2122,7 +2122,7 @@ } if (compilation.compiler.isObserved()) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, compilation.graph, hirValid, true)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, /*compilation.graph*/ null, hirValid, true)); } } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jun 10 21:52:19 2011 +0200 @@ -140,6 +140,7 @@ stream.println(" "); stream.println(" "); + flush(); } private List printNodes(Collection nodes, boolean shortNames, NodeMap nodeToBlock) { diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java Fri Jun 10 21:52:19 2011 +0200 @@ -140,7 +140,7 @@ @Override public void compilationEvent(CompilationEvent event) { - if (printer != null && event.getGraph() != null) { + if (printer != null && event.getGraph() != null && event.isHIRValid()) { Graph graph = event.getGraph(); printer.print(graph, event.getLabel(), true); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jun 10 21:52:19 2011 +0200 @@ -38,6 +38,7 @@ import com.oracle.max.graal.compiler.globalstub.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; @@ -207,8 +208,10 @@ public static class DeoptimizationStub { public final Label label = new Label(); public final LIRDebugInfo info; + public final DeoptAction action; - public DeoptimizationStub(FrameState state) { + public DeoptimizationStub(DeoptAction action, FrameState state) { + this.action = action; info = new LIRDebugInfo(state); } } @@ -293,12 +296,22 @@ if (Modifier.isSynchronized(compilation.method.accessFlags())) { bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; } + + boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags()); + CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null); + int[] argumentSlots = new int[arguments.length]; + int slot = 0; + for (int arg = 0; arg < arguments.length; arg++) { + argumentSlots[arg] = slot; + slot += arguments[arg].sizeInSlots(); + } + FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, compilation.graph); for (Node node : compilation.graph.start().usages()) { if (node instanceof Local) { Local local = (Local) node; int i = local.index(); - fs.storeLocal(i, local); + fs.storeLocal(argumentSlots[i], local); CiValue src = args.locations[i]; assert src.isLegal() : "check"; @@ -310,9 +323,21 @@ setResult(local, dest); } } + assert checkOperands(fs); return fs; } + private boolean checkOperands(FrameState fs) { + boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags()); + CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null); + int slot = 0; + for (CiKind kind : arguments) { + assert fs.localAt(slot) != null : "slot: " + slot; + slot += kind.sizeInSlots(); + } + return true; + } + @Override public void visitCheckCast(CheckCast x) { XirArgument obj = toXirArgument(x.object()); @@ -395,7 +420,7 @@ deoptimizationStubs = new ArrayList(); } - DeoptimizationStub stub = new DeoptimizationStub(state); + DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state); deoptimizationStubs.add(stub); emitCompare(x.node()); @@ -954,7 +979,8 @@ @Override public void visitDeoptimize(Deoptimize deoptimize) { - DeoptimizationStub stub = new DeoptimizationStub(lastState); + assert lastState != null : "deoptimize always needs a state"; + DeoptimizationStub stub = new DeoptimizationStub(deoptimize.action(), lastState); addDeoptimizationStub(stub); lir.branch(Condition.TRUE, stub.label, stub.info); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jun 10 21:52:19 2011 +0200 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; import com.sun.cri.bytecode.*; @@ -136,6 +137,11 @@ public static class DeoptBlock extends Block { } + public static class BranchOverride { + public DeoptBlock block; + public boolean taken; + } + private static final Block[] NO_SUCCESSORS = new Block[0]; /** @@ -151,6 +157,8 @@ private final RiMethod method; + public final HashMap branchOverride; + private Block[] blockMap; private BitSet canTrap; @@ -167,6 +175,7 @@ } this.blocks = new ArrayList(); this.storesInLoops = new BitSet(method.maxLocals()); + branchOverride = new HashMap(); } /** @@ -260,15 +269,12 @@ case IF_ACMPNE: // fall through case IFNULL: // fall through case IFNONNULL: { - int probability = method.branchProbability(bci); -// if (probability == 0 || probability == 100) { -// System.out.println("prob: " + probability); -// } current = null; - Block b1 = makeBlock(bci + 3); - Block b2 = makeBlock(bci + Bytes.beS2(code, bci + 1)); -// Block b1 = probability == 100 ? makeDeoptBlock(bci + 3) : makeBlock(bci + 3); -// Block b2 = probability == 0 ? makeDeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1)); + + int probability = GraalOptions.UseBranchPrediction ? method.branchProbability(bci) : -1; + + Block b1 = probability == 100 ? makeBranchOverrideBlock(bci, bci + 3, false) : makeBlock(bci + 3); + Block b2 = probability == 0 ? makeBranchOverrideBlock(bci, bci + Bytes.beS2(code, bci + 1), true) : makeBlock(bci + Bytes.beS2(code, bci + 1)); setSuccessors(bci, b1, b2); assert lengthOf(code, bci) == 3; @@ -385,11 +391,14 @@ } } - private Block makeDeoptBlock(int startBci) { - System.out.println("Deopt block created"); + private Block makeBranchOverrideBlock(int branchBci, int startBci, boolean taken) { DeoptBlock newBlock = new DeoptBlock(); newBlock.startBci = startBci; - blockMap[startBci] = newBlock; + BranchOverride override = new BranchOverride(); + override.block = newBlock; + override.taken = taken; + assert branchOverride.get(branchBci) == null; + branchOverride.put(branchBci, override); return newBlock; } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Jun 10 21:52:19 2011 +0200 @@ -70,7 +70,7 @@ public void build() { new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph); printGraph("After GraphBuilding", compilation.graph); - new DuplicationPhase().apply(compilation.graph); + //new DuplicationPhase().apply(compilation.graph); new DeadCodeEliminationPhase().apply(compilation.graph); printGraph("After DeadCodeElimination", compilation.graph); @@ -87,8 +87,8 @@ if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase().apply(graph); + new DeadCodeEliminationPhase().apply(compilation.graph); printGraph("After Canonicalization", graph); - new DeadCodeEliminationPhase().apply(compilation.graph); } new LoweringPhase().apply(graph); diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java Fri Jun 10 21:52:19 2011 +0200 @@ -31,10 +31,20 @@ private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; - private String message; + public static enum DeoptAction { + None, // just interpret, do not invalidate nmethod + Recompile, // recompile the nmethod; need not invalidate + InvalidateReprofile, // invalidate the nmethod, reset IC, maybe recompile + InvalidateRecompile, // invalidate the nmethod, recompile (probably) + InvalidateStopCompiling, // invalidate the nmethod and do not compile + } - public Deoptimize(Graph graph) { + private String message; + private final DeoptAction action; + + public Deoptimize(DeoptAction action, Graph graph) { super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.action = action; } public void setMessage(String message) { @@ -45,6 +55,10 @@ return message; } + public DeoptAction action() { + return action; + } + @Override public void accept(ValueVisitor v) { v.visitDeoptimize(this); @@ -62,7 +76,7 @@ @Override public Node copy(Graph into) { - Deoptimize x = new Deoptimize(into); + Deoptimize x = new Deoptimize(action, into); x.setMessage(message); return x; } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java Fri Jun 10 21:52:19 2011 +0200 @@ -22,8 +22,11 @@ */ package com.oracle.max.graal.compiler.ir; +import java.util.*; + import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.graph.*; +import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -34,15 +37,38 @@ public final class Local extends FloatingNode { private static final int INPUT_COUNT = 1; + private static final int INPUT_START = 0; private static final int SUCCESSOR_COUNT = 0; + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The start node of the graph that this local belongs to. This is used for correctly scheduling the locals. + */ + private StartNode start() { + return (StartNode) inputs().get(super.inputCount() + INPUT_START); + } + + private void setStart(StartNode n) { + inputs().set(super.inputCount() + INPUT_START, n); + } + private final int index; private RiType declaredType; - public Local(CiKind kind, int javaIndex, Graph graph) { + public Local(CiKind kind, int javaIndex, StartNode start, Graph graph) { super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); this.index = javaIndex; + setStart(start); } /** @@ -81,18 +107,15 @@ } @Override - protected int inputCount() { - return super.inputCount() + INPUT_COUNT; - } - - @Override - protected int successorCount() { - return super.successorCount() + SUCCESSOR_COUNT; + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("index", index()); + return properties; } @Override public Node copy(Graph into) { - Local x = new Local(kind, index, into); + Local x = new Local(kind, index, start(), into); x.setDeclaredType(declaredType()); return x; } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java Fri Jun 10 21:52:19 2011 +0200 @@ -23,6 +23,7 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -32,6 +33,7 @@ * The {@code NegateOp} instruction negates its operand. */ public final class Negate extends FloatingNode { + private static final NegateCanonicalizerOp CANONICALIZER = new NegateCanonicalizerOp(); private static final int INPUT_COUNT = 2; private static final int INPUT_X = 0; @@ -103,4 +105,31 @@ Negate x = new Negate(kind, into); return x; } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static class NegateCanonicalizerOp implements CanonicalizerOp { + @Override + public Node canonical(Node node) { + Negate negate = (Negate) node; + Value x = negate.x(); + Graph graph = negate.graph(); + if (x.isConstant()) { + switch (x.kind) { + case Int: return Constant.forInt(-x.asConstant().asInt(), graph); + case Long: return Constant.forLong(-x.asConstant().asLong(), graph); + case Float: return Constant.forFloat(-x.asConstant().asFloat(), graph); + case Double: return Constant.forDouble(-x.asConstant().asDouble(), graph); + } + } + return negate; + } + } } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Fri Jun 10 21:52:19 2011 +0200 @@ -205,6 +205,4 @@ properties.put("operand", operand == null ? "null" : operand.toString()); return properties; } - - } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Jun 10 21:52:19 2011 +0200 @@ -22,46 +22,30 @@ */ package com.oracle.max.graal.compiler.phases; -import java.util.*; - import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.graph.*; +/* TODO (gd) Canonicalize : + * - Compare & If + * - InstanceOf (if it's not transformed into a Condition for Compare) + * - Switches + */ public class CanonicalizerPhase extends Phase { - + private static final int MAX_ITERATION_PER_NODE = 10; @Override protected void run(Graph graph) { - NodeBitMap visited = graph.createNodeBitMap(); - List nodes = new ArrayList(graph.getNodes()); - for (Node n : nodes) { - if (n == null) { - continue; - } - if (!n.isDeleted() && !visited.isMarked(n)) { - this.canonicalize(n, visited); - } - } - } - - private void canonicalize(Node n, NodeBitMap visited) { - visited.mark(n); - for (Node input : n.inputs()) { - if (input == null) { - continue; - } - if (!visited.isNew(input) && !visited.isMarked(input)) { - canonicalize(input, visited); - } - } - - CanonicalizerOp op = n.lookup(CanonicalizerOp.class); - if (op != null) { - Node canonical = op.canonical(n); - if (canonical != n) { - n.replace(canonical); - //System.out.println("-->" + n + " canonicalized to " + canonical); - GraalMetrics.NodesCanonicalized++; + NodeWorkList nodeWorkList = graph.createNodeWorkList(true, MAX_ITERATION_PER_NODE); + for (Node node : nodeWorkList) { + CanonicalizerOp op = node.lookup(CanonicalizerOp.class); + if (op != null) { + Node canonical = op.canonical(node); + if (canonical != node) { + node.replace(canonical); + nodeWorkList.replaced(canonical, node, EdgeType.USAGES); + //System.out.println("-->" + n + " canonicalized to " + canonical); + GraalMetrics.NodesCanonicalized++; + } } } } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jun 10 21:52:19 2011 +0200 @@ -38,6 +38,27 @@ this.graph = graph; this.flood = graph.createNodeFlood(); + // remove chained Merges +// for (Merge merge : graph.getNodes(Merge.class)) { +// if (merge.predecessors().size() == 1 && merge.usages().size() == 0) { +// if (merge.successors().get(0) instanceof Merge) { +// Node pred = merge.predecessors().get(0); +// int predIndex = merge.predecessorsIndex().get(0); +// pred.successors().setAndClear(predIndex, merge, 0); +// merge.delete(); +// } +// } +// } +// Node startSuccessor = graph.start().successors().get(0); +// if (startSuccessor instanceof Merge) { +// Merge startMerge = (Merge) startSuccessor; +// if (startMerge.predecessors().size() == 1 && startMerge.usages().size() == 0) { +// int predIndex = startMerge.predecessorsIndex().get(0); +// graph.start().successors().setAndClear(predIndex, startMerge, 0); +// startMerge.delete(); +// } +// } + flood.add(graph.start()); iterateSuccessors(); @@ -96,6 +117,9 @@ private void iterateInputs() { for (Node node : graph.getNodes()) { + if (node instanceof Local) { + flood.add(node); + } if (node != Node.Null && flood.isMarked(node)) { for (Node input : node.inputs()) { if (!isCFG(input)) { diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jun 10 21:52:19 2011 +0200 @@ -31,10 +31,10 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; -import com.oracle.max.graal.compiler.graph.BlockMap.DeoptBlock; import com.oracle.max.graal.compiler.graph.BlockMap.*; import com.oracle.max.graal.compiler.graph.BlockMap.Block; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; @@ -78,11 +78,12 @@ // bci-to-block mapping private Block[] blockFromBci; private ArrayList blockList; + private HashMap branchOverride; private int nextBlockNumber; private Value methodSynchronizedObject; - private CiExceptionHandler syncHandler; + private CiExceptionHandler unwindHandler; private Block unwindBlock; private Block returnBlock; @@ -145,6 +146,7 @@ // 2. compute the block map, setup exception handlers and get the entrypoint(s) BlockMap blockMap = compilation.getBlockMap(method); + this.branchOverride = blockMap.branchOverride; blockList = new ArrayList(blockMap.blocks); blockFromBci = new Block[method.code().length]; @@ -152,7 +154,7 @@ int blockID = nextBlockNumber(); assert blockID == i; Block block = blockList.get(i); - if (block.startBci >= 0) { + if (block.startBci >= 0 && !(block instanceof BlockMap.DeoptBlock)) { blockFromBci[block.startBci] = block; } } @@ -171,13 +173,13 @@ finishStartBlock(startBlock); // 4A.3 setup an exception handler to unlock the root method synchronized object - syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); + unwindHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); } else { // 4B.1 simply finish the start block finishStartBlock(startBlock); if (createUnwind) { - syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); + unwindHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); } } @@ -380,7 +382,7 @@ } if (firstHandler == null) { - firstHandler = syncHandler; + firstHandler = unwindHandler; } if (firstHandler != null) { @@ -435,7 +437,7 @@ // this is a load of class constant which might be unresolved RiType riType = (RiType) con; if (!riType.isResolved()) { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.push(CiKind.Object, append(Constant.forObject(null, graph))); } else { frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph))); @@ -654,9 +656,20 @@ assert !x.isDeleted() && !y.isDeleted(); If ifNode = new If(new Compare(x, cond, y, graph), graph); append(ifNode); - Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState); + BlockMap.BranchOverride override = branchOverride.get(bci()); + Instruction tsucc; + if (override == null || override.taken == false) { + tsucc = createTargetAt(stream().readBranchDest(), frameState); + } else { + tsucc = createTarget(override.block, frameState); + } ifNode.setBlockSuccessor(0, tsucc); - Instruction fsucc = createTargetAt(stream().nextBCI(), frameState); + Instruction fsucc; + if (override == null || override.taken == true) { + fsucc = createTargetAt(stream().nextBCI(), frameState); + } else { + fsucc = createTarget(override.block, frameState); + } ifNode.setBlockSuccessor(1, fsucc); } @@ -727,7 +740,7 @@ NewInstance n = new NewInstance(type, cpi, constantPool, graph); frameState.apush(append(n)); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -746,7 +759,7 @@ NewArray n = new NewObjectArray(type, length, graph); frameState.apush(append(n)); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } @@ -763,7 +776,7 @@ NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph); frameState.apush(append(n)); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -775,7 +788,7 @@ LoadField load = new LoadField(receiver, field, graph); appendOptimizedLoadField(kind, load); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph))); } } @@ -787,7 +800,7 @@ StoreField store = new StoreField(receiver, field, value, graph); appendOptimizedStoreField(store); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); } } @@ -807,7 +820,7 @@ LoadField load = new LoadField(container, field, graph); appendOptimizedLoadField(kind, load); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph))); } } @@ -821,7 +834,7 @@ StoreField store = new StoreField(container, field, value, graph); appendOptimizedStoreField(store); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); } } @@ -829,7 +842,7 @@ if (initialized) { return appendConstant(holder.getEncoding(representation)); } else { - append(new Deoptimize(graph)); + append(new Deoptimize(DeoptAction.InvalidateRecompile, graph)); return null; } } @@ -909,10 +922,15 @@ private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { CiKind resultType = returnKind(target); - Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), method.typeProfile(bci()), graph); - Value result = appendWithBCI(invoke); - invoke.setExceptionEdge(handleException(null, bci())); - frameState.pushReturn(resultType, result); + if (GraalOptions.DeoptALot) { + append(new Deoptimize(DeoptAction.None, graph)); + frameState.pushReturn(resultType, Constant.defaultForKind(resultType, graph)); + } else { + Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), method.typeProfile(bci()), graph); + Value result = appendWithBCI(invoke); + invoke.setExceptionEdge(handleException(null, bci())); + frameState.pushReturn(resultType, result); + } } private RiType getExactType(RiType staticType, Value receiver) { @@ -1096,7 +1114,8 @@ private Instruction createTarget(Block block, FrameStateAccess stateAfter) { assert block != null && stateAfter != null; - assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors"; + assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : + "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next(); if (block.isExceptionEntry) { assert stateAfter.stackSize() == 1; @@ -1188,7 +1207,10 @@ } private void createDeoptBlock(DeoptBlock block) { - append(new Deoptimize(graph)); +// Merge x = new Merge(graph); +// x.setStateBefore(((StateSplit) block.firstInstruction).stateBefore()); +// append(x); + append(new Deoptimize(DeoptAction.InvalidateReprofile, graph)); } private void createUnwindBlock(Block block) { @@ -1225,7 +1247,7 @@ Instruction nextDispatch = createTarget(nextBlock, frameState); append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); } else { - Deoptimize deopt = new Deoptimize(graph); + Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph); deopt.setMessage("unresolved " + block.handler.catchType().name()); append(deopt); Instruction nextDispatch = createTarget(nextBlock, frameState); diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 10 21:52:19 2011 +0200 @@ -273,11 +273,17 @@ Node returnDuplicate = duplicates.get(returnNode); returnDuplicate.inputs().clearAll(); + Merge mergeAfter = new Merge(compilation.graph); + assert returnDuplicate.predecessors().size() == 1; Node returnPred = returnDuplicate.predecessors().get(0); int index = returnDuplicate.predecessorsIndex().get(0); - returnPred.successors().setAndClear(index, invoke, 0); + mergeAfter.successors().setAndClear(0, invoke, 0); + returnPred.successors().set(index, mergeAfter); + returnDuplicate.delete(); + + mergeAfter.setStateBefore(stateAfter); } if (exceptionEdge != null) { @@ -306,8 +312,11 @@ // adjust all frame states that were copied if (frameStates.size() > 0) { FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind); - for (Node frameState : frameStates) { - ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState); + for (Node node : frameStates) { + FrameState frameState = (FrameState) duplicates.get(node); + if (!frameState.isDeleted()) { + frameState.setOuterFrameState(outerFrameState); + } } } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Fri Jun 10 21:52:19 2011 +0200 @@ -2070,6 +2070,27 @@ @Override public void emitDeoptizationStub(DeoptimizationStub stub) { masm.bind(stub.label); + int code; + switch(stub.action) { + case None: + code = 0; + break; + case Recompile: + code = 1; + break; + case InvalidateReprofile: + code = 2; + break; + case InvalidateRecompile: + code = 3; + break; + case InvalidateStopCompiling: + code = 4; + break; + default: + throw Util.shouldNotReachHere(); + } + masm.movq(rscratch1, code); directCall(CiRuntimeCall.Deoptimize, stub.info); shouldNotReachHere(); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jun 10 21:52:19 2011 +0200 @@ -509,6 +509,29 @@ } @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("bci", bci); + properties.put("method", CiUtil.format("%H.%n(%p):%r", method, false)); + StringBuilder str = new StringBuilder(); + for (int i = 0; i < localsSize(); i++) { + str.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).id()); + } + properties.put("locals", str.toString()); + str = new StringBuilder(); + for (int i = 0; i < stackSize(); i++) { + str.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).id()); + } + properties.put("stack", str.toString()); + str = new StringBuilder(); + for (int i = 0; i < locksSize(); i++) { + str.append(i == 0 ? "" : ", ").append(lockAt(i) == null ? "_" : lockAt(i).id()); + } + properties.put("locks", str.toString()); + return properties; + } + + @Override public Node copy(Graph into) { FrameState x = new FrameState(method, bci, localsSize, stackSize, locksSize, into); return x; diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Jun 10 21:52:19 2011 +0200 @@ -58,8 +58,7 @@ int index = 0; if (!isStatic(method.accessFlags())) { // add the receiver and assume it is non null - Local local = new Local(method.holder().kind(), javaIndex, graph); - local.inputs().set(0, graph.start()); + Local local = new Local(method.holder().kind(), javaIndex, graph.start(), graph); local.setDeclaredType(method.holder()); storeLocal(javaIndex, local); javaIndex = 1; @@ -71,8 +70,7 @@ for (int i = 0; i < max; i++) { RiType type = sig.argumentTypeAt(i, accessingClass); CiKind kind = type.kind().stackKind(); - Local local = new Local(kind, index, graph); - local.inputs().set(0, graph.start()); + Local local = new Local(kind, index, graph.start(), graph); if (type.isResolved()) { local.setDeclaredType(type); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java Fri Jun 10 21:52:19 2011 +0200 @@ -84,10 +84,12 @@ } while (nextNode == null || !type.isInstance(nextNode)); } + @Override public boolean hasNext() { return nextNode != null; } + @Override @SuppressWarnings("unchecked") public T next() { try { @@ -97,6 +99,7 @@ } } + @Override public void remove() { throw new UnsupportedOperationException(); } @@ -104,6 +107,7 @@ public Iterable getNodes(final Class type) { return new Iterable() { + @Override public Iterator iterator() { return new TypedNodeIterator(type, nodes.iterator()); } @@ -137,12 +141,21 @@ return new NodeFlood(this); } + public NodeWorkList createNodeWorkList() { + return new NodeWorkList(this); + } + + public NodeWorkList createNodeWorkList(boolean fill, int iterationLimitPerNode) { + return new NodeWorkList(this, fill, iterationLimitPerNode); + } + public Map addDuplicate(Collection nodes, Map replacements) { Map newNodes = new HashMap(); // create node duplicates for (Node node : nodes) { if (node != null && !replacements.containsKey(node)) { assert node.graph != this; + assert !node.isDeleted() : "trying to duplicate deleted node"; Node newNode = node.copy(this); assert newNode.getClass() == node.getClass(); newNodes.put(node, newNode); diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java Fri Jun 10 21:52:19 2011 +0200 @@ -130,7 +130,7 @@ public void delete() { assert !isDeleted(); - assert usages.size() == 0 && predecessors.size() == 0 : "id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size(); + assert checkDeletion(); assert predecessorsIndex.size() == 0; for (int i = 0; i < inputs.size(); ++i) { inputs.set(i, Null); @@ -145,6 +145,23 @@ assert isDeleted(); } + private boolean checkDeletion() { + if (usages.size() != 0 || predecessors.size() != 0) { + System.out.println(this.shortName() + ", id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size()); + System.out.println("usages:"); + for (Node n : usages()) { + System.out.print(n.id() + " (" + n.shortName() + ") "); + } + System.out.println("\npreds:"); + for (Node n : predecessors()) { + System.out.print(n.id() + " (" + n.shortName() + ") "); + } + System.out.println(); + return false; + } + return true; + } + public Node copy() { return copy(graph); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java Fri Jun 10 21:52:19 2011 +0200 @@ -53,6 +53,7 @@ @Override public Node set(int index, Node node) { + assert !self().isDeleted() : "trying to set input/successor of deleted node: " + self().shortName(); assert node == Node.Null || node.graph == self().graph : "node is from different graph: (this=" + self() + ") and (node=" + node + ")"; assert node == Node.Null || node.id() != Node.DeletedID : "inserted node must not be deleted"; Node old = nodes[index]; @@ -145,6 +146,7 @@ } public void setAndClear(int index, Node clearedNode, int clearedIndex) { + assert !self().isDeleted() : "trying to setAndClear successor of deleted node: " + self().shortName(); assert self().successors == this; Node value = clearedNode.successors.get(clearedIndex); assert value != Node.Null; diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeBitMap.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeBitMap.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeBitMap.java Fri Jun 10 21:52:19 2011 +0200 @@ -70,6 +70,10 @@ bitMap.clearAll(); } + public void grow(Node node) { + bitMap.grow(node.id() + 1); + } + private void check(Node node) { assert node.graph == graph : "this node is not part of the graph"; assert !isNew(node) : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")"; diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeWorkList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeWorkList.java Fri Jun 10 21:52:19 2011 +0200 @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.graph; + +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; + + +public class NodeWorkList implements Iterable { + private final NodeBitMap visited; + private final NodeBitMap inQueue; + private final Queue worklist; + private int iterationLimit = Integer.MAX_VALUE; + + NodeWorkList(Graph graph) { + this(graph, false, -1); + } + + NodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { + visited = graph.createNodeBitMap(); + inQueue = graph.createNodeBitMap(); + if (fill) { + ArrayDeque deque = new ArrayDeque(graph.getNodeCount()); + for (Node node : graph.getNodes()) { + if (node != null) { + deque.add(node); + } + } + worklist = deque; + } else { + worklist = new ArrayDeque(); + } + if (iterationLimitPerNode > 0) { + iterationLimit = iterationLimitPerNode * graph.getNodeCount(); + } + } + + public void add(Node node) { + if (node != null && !visited.isMarked(node)) { + doAdd(node); + } + } + + private void doAdd(Node node) { + if (node != null && !inQueue.isMarked(node)) { + visited.mark(node); + inQueue.mark(node); + worklist.add(node); + } + } + + public void replaced(Node newNode, Node oldNode, EdgeType... edges) { + this.replaced(newNode, oldNode, false, edges); + } + + public void replaced(Node newNode, Node oldNode, boolean add, EdgeType... edges) { + visited.grow(newNode); + inQueue.grow(newNode); + worklist.remove(oldNode); + assert !worklist.contains(oldNode); + if (add) { + this.add(newNode); + } + for (EdgeType type : edges) { + switch (type) { + case INPUTS: + for (Node n : newNode.inputs()) { + doAdd(n); + } + break; + case PREDECESSORS: + for (Node n : newNode.predecessors()) { + doAdd(n); + } + break; + case USAGES: + for (Node n : newNode.usages()) { + doAdd(n); + } + break; + case SUCCESSORS: + for (Node n : newNode.successors()) { + doAdd(n); + } + break; + } + } + } + + public boolean isMarked(Node node) { + return visited.isMarked(node); + } + + private class QueueConsumingIterator implements Iterator { + private final Queue queue; + + public QueueConsumingIterator(Queue queue) { + this.queue = queue; + } + + @Override + public boolean hasNext() { + return iterationLimit > 0 && !queue.isEmpty(); + } + + @Override + public Node next() { + if (iterationLimit-- <= 0) { + throw new NoSuchElementException(); + } + Node node = queue.remove(); + inQueue.clear(node); + return node; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public Iterator iterator() { + return new QueueConsumingIterator(worklist); + } + + private static class UnmarkedNodeIterator implements Iterator { + private final NodeBitMap visited; + private Iterator nodes; + private Node nextNode; + + public UnmarkedNodeIterator(NodeBitMap visited, Iterator nodes) { + this.visited = visited; + this.nodes = nodes; + forward(); + } + + private void forward() { + do { + if (!nodes.hasNext()) { + nextNode = null; + return; + } + nextNode = nodes.next(); + } while (visited.isMarked(nextNode)); + } + + @Override + public boolean hasNext() { + return nextNode != null; + } + + @Override + public Node next() { + try { + return nextNode; + } finally { + forward(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + public Iterable unmarkedNodes() { + return new Iterable() { + @Override + public Iterator iterator() { + return new UnmarkedNodeIterator(visited, visited.graph().getNodes().iterator()); + } + }; + } +} diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Fri Jun 10 21:51:42 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Fri Jun 10 21:52:19 2011 +0200 @@ -621,8 +621,8 @@ asm.bindOutOfLine(slowPath); checkSubtype(asm, objHub, objHub, hub); asm.jneq(end, objHub, asm.o(null)); - XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); - asm.mov(scratch, object); + XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10); + asm.mov(scratch, asm.createConstant(CiConstant.forWord(0))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); @@ -711,6 +711,8 @@ asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); if (is(BOUNDS_CHECK, flags)) { asm.bindOutOfLine(failBoundsCheck); + XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10); + asm.mov(scratch, asm.createConstant(CiConstant.forWord(0))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } @@ -902,8 +904,8 @@ asm.bindOutOfLine(slowStoreCheck); checkSubtype(asm, temp, valueHub, compHub); asm.jneq(store, temp, asm.w(0)); - XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); - asm.mov(scratch, valueHub); + XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10); + asm.mov(scratch, asm.createConstant(CiConstant.forWord(0))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.jmp(store); } @@ -986,6 +988,8 @@ // -- out of line ------------------------------------------------------- if (is(BOUNDS_CHECK, flags)) { asm.bindOutOfLine(failBoundsCheck); + XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10); + asm.mov(scratch, asm.createConstant(CiConstant.forWord(0))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } @@ -994,8 +998,8 @@ asm.bindOutOfLine(slowStoreCheck); checkSubtype(asm, temp, valueHub, compHub); asm.jneq(store, temp, asm.w(0)); - XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); - asm.mov(scratch, valueHub); + XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10); + asm.mov(scratch, asm.createConstant(CiConstant.forWord(0))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } diff -r e86e83c5adbc -r c76db61fbb73 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java diff -r e86e83c5adbc -r c76db61fbb73 graal/hotspot/hotspot Default.launch --- a/graal/hotspot/hotspot Default.launch Fri Jun 10 21:51:42 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r e86e83c5adbc -r c76db61fbb73 src/cpu/x86/vm/c1_globals_x86.hpp --- a/src/cpu/x86/vm/c1_globals_x86.hpp Fri Jun 10 21:51:42 2011 +0200 +++ b/src/cpu/x86/vm/c1_globals_x86.hpp Fri Jun 10 21:52:19 2011 +0200 @@ -40,7 +40,7 @@ define_pd_global(bool, ProfileTraps, false); define_pd_global(bool, UseOnStackReplacement, true ); define_pd_global(bool, TieredCompilation, false); -define_pd_global(intx, CompileThreshold, 1500 ); +define_pd_global(intx, CompileThreshold, 5000 ); // changed for GRAAL define_pd_global(intx, BackEdgeThreshold, 100000); define_pd_global(intx, OnStackReplacePercentage, 933 ); diff -r e86e83c5adbc -r c76db61fbb73 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Jun 10 21:51:42 2011 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Jun 10 21:52:19 2011 +0200 @@ -140,6 +140,7 @@ static int rax_offset_in_bytes(void) { return BytesPerInt * rax_off; } static int rdx_offset_in_bytes(void) { return BytesPerInt * rdx_off; } static int rbx_offset_in_bytes(void) { return BytesPerInt * rbx_off; } + static int r10_offset_in_bytes(void) { return BytesPerInt * r10_off; } static int xmm0_offset_in_bytes(void) { return BytesPerInt * xmm0_off; } static int return_offset_in_bytes(void) { return BytesPerInt * return_off; } @@ -2655,6 +2656,7 @@ int jmp_uncommon_trap_offset = __ pc() - start; __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset()))); + __ movptr(rscratch1, 0); int uncommon_trap_offset = __ pc() - start; @@ -2669,8 +2671,15 @@ // fetch_unroll_info needs to call last_java_frame() __ set_last_Java_frame(noreg, noreg, NULL); - __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute); - __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames + + // __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute); + // __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames + + assert(r10 == rscratch1, "scratch register should be r10"); + __ movptr(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes())); + __ orq(c_rarg1, ~(int32_t)Deoptimization::make_trap_request(Deoptimization::Reason_unreached, Deoptimization::Action_none)); + __ notq(c_rarg1); + __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute); __ mov(c_rarg0, r15_thread); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); @@ -2744,7 +2753,7 @@ // or captured in the vframeArray. RegisterSaver::restore_result_registers(masm); - // All of the register save area has been popped of the stack. Only the + // All of the register save area has been poppeset_jmp_uncommon_trap_offsetd of the stack. Only the // return address remains. // Pop all the frames we must move/replace. diff -r e86e83c5adbc -r c76db61fbb73 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Fri Jun 10 21:51:42 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Fri Jun 10 21:52:19 2011 +0200 @@ -98,7 +98,7 @@ graph.setBlock(n, this); final InputNode node = graph.getNode(id); assert node != null; - assert !nodes.contains(node); + assert !nodes.contains(node) : "duplicate : " + node; nodes.add(node); } diff -r e86e83c5adbc -r c76db61fbb73 src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java --- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java Fri Jun 10 21:51:42 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java Fri Jun 10 21:52:19 2011 +0200 @@ -1021,7 +1021,7 @@ for (Figure f : diagram.getFigures()) { FigureWidget w = getWidget(f); - if (w.isVisible()) { + if (w != null && w.isVisible()) { oldVisibleWidgets.add(w); } } diff -r e86e83c5adbc -r c76db61fbb73 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Jun 10 21:51:42 2011 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Jun 10 21:52:19 2011 +0200 @@ -106,7 +106,8 @@ } // TODO: finish this - graal doesn't provide any scope values at the moment -static ScopeValue* get_hotspot_value(oop value, int frame_size) { +static ScopeValue* get_hotspot_value(oop value, int frame_size, ScopeValue* &second) { + second = NULL; if (value == CiValue::IllegalValue()) { return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); } @@ -114,27 +115,61 @@ BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(CiValue::kind(value))); Location::Type locationType = Location::normal; if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop; + if (value->is_a(CiRegisterValue::klass())) { jint number = CiRegister::number(CiRegisterValue::reg(value)); if (number < 16) { - return new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg())); + if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { + locationType = Location::int_in_long; + } else if (type == T_LONG) { + locationType = Location::lng; + } else { + assert(type == T_OBJECT || type == T_ARRAY, "unexpected type in cpu register"); + } + ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg())); + if (type == T_LONG) { + second = value; + } + return value; } else { - return new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); + assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register"); + if (type == T_FLOAT) { + // this seems weird, but the same value is used in c1_LinearScan + locationType = Location::normal; + } else { + locationType = Location::dbl; + } + ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); + if (type == T_DOUBLE) { + second = value; + } + return value; } } else if (value->is_a(CiStackSlot::klass())) { + if (type == T_DOUBLE) { + locationType = Location::dbl; + } else if (type == T_LONG) { + locationType = Location::lng; + } jint index = CiStackSlot::index(value); + ScopeValue* value; if (index >= 0) { - return new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize)); + value = new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize)); } else { int frame_size_bytes = frame_size + 2 * HeapWordSize; - return new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes)); + value = new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes)); } + if (type == T_DOUBLE || type == T_LONG) { + second = value; + } + return value; } else if (value->is_a(CiConstant::klass())){ oop obj = CiConstant::object(value); jlong prim = CiConstant::primitive(value); if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { return new ConstantIntValue(*(jint*)&prim); } else if (type == T_LONG || type == T_DOUBLE) { + second = new ConstantIntValue(0); return new ConstantLongValue(prim); } else if (type == T_OBJECT) { oop obj = CiConstant::object(value); @@ -433,19 +468,32 @@ } for (jint i = 0; i < values->length(); i++) { - ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size); + ScopeValue* second = NULL; + ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size, second); if (i < local_count) { + if (second != NULL) { + locals->append(second); + } locals->append(value); } else if (i < local_count + expression_count) { + if (second != NULL) { + expressions->append(value); + } expressions->append(value); } else { + assert(second == NULL, "monitor cannot occupy two stack slots"); assert(value->is_location(), "invalid monitor location"); LocationValue* loc = (LocationValue*)value; int monitor_offset = loc->location().stack_offset(); LocationValue* obj = new LocationValue(Location::new_stk_loc(Location::oop, monitor_offset + BasicObjectLock::obj_offset_in_bytes())); monitors->append(new MonitorValue(obj, Location::new_stk_loc(Location::normal, monitor_offset + BasicObjectLock::lock_offset_in_bytes()))); } + if (second != NULL) { + i++; + assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue"); + assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue"); + } } DebugToken* locals_token = _debug_recorder->create_scope_values(locals); DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); diff -r e86e83c5adbc -r c76db61fbb73 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Fri Jun 10 21:51:42 2011 +0200 +++ b/src/share/vm/oops/methodOop.cpp Fri Jun 10 21:52:19 2011 +0200 @@ -206,6 +206,12 @@ } address methodOopDesc::bcp_from(int bci) const { +#ifdef ASSERT + if (!((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()))) { + char buf[1024]; + tty->print_cr("bci: %i, size: %i, method: %s", bci, code_size(), const_cast(this)->name_and_sig_as_C_string(buf, 1024)); + } +#endif // ASSERT assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci"); address bcp = code_base() + bci; assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method"); diff -r e86e83c5adbc -r c76db61fbb73 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Jun 10 21:51:42 2011 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Jun 10 21:52:19 2011 +0200 @@ -1221,6 +1221,8 @@ DeoptAction action = trap_request_action(trap_request); jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1 +// tty->print_cr("trap_request: %08x, cpi: %i, pc: %016x", trap_request, unloaded_class_index, fr.pc()); + Events::log("Uncommon trap occurred @" INTPTR_FORMAT " unloaded_class_index = %d", fr.pc(), (int) trap_request); vframe* vf = vframe::new_vframe(&fr, ®_map, thread); compiledVFrame* cvf = compiledVFrame::cast(vf); diff -r e86e83c5adbc -r c76db61fbb73 src/share/vm/runtime/java.cpp