# HG changeset patch # User Lukas Stadler # Date 1312381685 -7200 # Node ID ccf5e0d9eb61751e64439a7ad657d9e39b73dfa9 # Parent a6c1f49a7319e9945101ba756a3f92afe0867149# Parent b9f76db5ac535e3f122b89e7d92132d7f5a0c4a1 merge diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java Wed Aug 03 16:28:05 2011 +0200 @@ -41,6 +41,10 @@ public static int InlinedFinalizerChecks; public static int InlineForcedMethods; public static int InlineForbiddenMethods; + public static int InlineConsidered; + public static int InlinePerformed; + public static int InlineUncompiledConsidered; + public static int InlineUncompiledPerformed; public static int BlocksDeleted; public static int BytecodesCompiled; public static int CodeBytesEmitted; diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Wed Aug 03 16:28:05 2011 +0200 @@ -46,9 +46,12 @@ public static int MaximumInstructionCount = 3000; public static float MaximumInlineRatio = 0.90f; public static int MaximumInlineSize = 35; + public static int MaximumInlineCompSize = 350; public static int MaximumFreqInlineSize = 200; + public static int MaximumFreqInlineCompSize = 1500; public static int FreqInlineRatio = 20; public static int MaximumTrivialSize = 6; + public static int MaximumTrivialCompSize = 120; public static int MaximumInlineLevel = 9; public static int MaximumRecursiveInlineLevel = 2; public static int MaximumDesiredSize = 8000; @@ -166,9 +169,10 @@ public static boolean OptReadElimination = ____; public static boolean OptGVN = ____; public static boolean Rematerialize = ____; + public static boolean SplitMaterialization = ____; public static boolean OptCanonicalizer = true; public static boolean OptLoops = ____; - public static boolean OptOptimisticSchedule = ____; + public static boolean ScheduleOutOfLoops = true; public static boolean OptReorderLoops = ____; public static boolean LoopPeeling = ____; public static boolean LoopInversion = ____; diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Wed Aug 03 16:28:05 2011 +0200 @@ -122,12 +122,21 @@ stream.printf(" %n", escape(title)); noBlockNodes.clear(); IdentifyBlocksPhase schedule = null; - try { - schedule = new IdentifyBlocksPhase(true); - schedule.apply(graph, false, false); - } catch (Throwable t) { - // nothing to do here... - //t.printStackTrace(); + if (debugObjects != null) { + for (Object obj : debugObjects.values()) { + if (obj instanceof IdentifyBlocksPhase) { + schedule = (IdentifyBlocksPhase) obj; + } + } + } + if (schedule == null) { + try { + schedule = new IdentifyBlocksPhase(true, false); + schedule.apply(graph, false, false); + } catch (Throwable t) { + // nothing to do here... + //t.printStackTrace(); + } } List loops = null; try { diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Aug 03 16:28:05 2011 +0200 @@ -504,9 +504,11 @@ lir.branch(cond, trueSuccessor); } - public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) { + public void emitBooleanBranch(BooleanNode node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) { if (node instanceof NegateBooleanNode) { emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info); + } else if (node instanceof IsNonNull) { + emitIsNonNullBranch((IsNonNull) node, trueSuccessor, falseSuccessor); } else if (node instanceof Compare) { emitCompare((Compare) node, trueSuccessor, falseSuccessor); } else if (node instanceof InstanceOf) { @@ -518,6 +520,25 @@ } } + private void emitIsNonNullBranch(IsNonNull node, LIRBlock trueSuccessor, LIRBlock falseSuccessor) { + Condition cond = Condition.NE; + if (trueSuccessor == null) { + cond = cond.negate(); + trueSuccessor = falseSuccessor; + falseSuccessor = null; + } + + LIRItem xitem = new LIRItem(node.object(), this); + xitem.loadItem(); + + lir.cmp(cond, xitem.result(), CiConstant.NULL_OBJECT); + lir.branch(cond, trueSuccessor); + + if (falseSuccessor != null) { + lir.jump(falseSuccessor); + } + } + private void emitInstanceOf(TypeCheck x, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) { XirArgument obj = toXirArgument(x.object()); XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass()); diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/globalstub/GlobalStub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/globalstub/GlobalStub.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/globalstub/GlobalStub.java Wed Aug 03 16:28:05 2011 +0200 @@ -40,9 +40,6 @@ public class GlobalStub { public enum Id { - - fneg(Float, Float), - dneg(Double, Double), f2i(Int, Float), f2l(Long, Float), d2i(Int, Double), diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Wed Aug 03 16:28:05 2011 +0200 @@ -131,7 +131,7 @@ new GlobalValueNumberingPhase().apply(graph); if (GraalOptions.Rematerialize) { //new Rematerialization2Phase().apply(graph); - new RematerializationPhase().apply(graph); + //new RematerializationPhase().apply(graph); } graph.stopRecordModifications(); } @@ -143,7 +143,7 @@ graph.recordModifications(EdgeType.USAGES); new GlobalValueNumberingPhase().apply(graph); if (GraalOptions.Rematerialize) { - new RematerializationPhase().apply(graph); + //new RematerializationPhase().apply(graph); } graph.stopRecordModifications(); } @@ -156,6 +156,12 @@ schedule.apply(graph); compilation.stats.loopCount = schedule.loopCount(); + if (compilation.compiler.isObserved()) { + Map debug = new HashMap(); + debug.put("schedule", schedule); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After IdentifyBlocksPhase", graph, true, false, debug)); + } + List blocks = schedule.getBlocks(); List lirBlocks = new ArrayList(); diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Wed Aug 03 16:28:05 2011 +0200 @@ -156,7 +156,12 @@ @Override public Node canonical(Node node) { Compare compare = (Compare) node; - if (compare.x().isConstant() && compare.y().isConstant()) { + if (compare.x().isConstant() && !compare.y().isConstant()) { // move constants to the left (y) + Value x = compare.x(); + compare.setX(compare.y()); + compare.setY(x); + compare.condition = compare.condition.mirror(); + } else if (compare.x().isConstant() && compare.y().isConstant()) { CiConstant constX = compare.x().asConstant(); CiConstant constY = compare.y().asConstant(); Boolean result = compare.condition().foldCondition(constX, constY, ((CompilerGraph) node.graph()).runtime()); @@ -170,18 +175,36 @@ TTY.println("if not removed %s %s %s (%s %s)", constX, compare.condition(), constY, constX.kind, constY.kind); } } - } else if (compare.x().isConstant() && compare.y() instanceof MaterializeNode) { - return optimizeMaterialize(compare, compare.x().asConstant(), (MaterializeNode) compare.y()); - } else if (compare.y().isConstant() && compare.x() instanceof MaterializeNode) { - return optimizeMaterialize(compare, compare.y().asConstant(), (MaterializeNode) compare.x()); - } else if (compare.x().isConstant() && compare.y() instanceof NormalizeCompare) { - return optimizeNormalizeCmp(compare, compare.x().asConstant(), (NormalizeCompare) compare.y()); - } else if (compare.y().isConstant() && compare.x() instanceof NormalizeCompare) { - return optimizeNormalizeCmp(compare, compare.y().asConstant(), (NormalizeCompare) compare.x()); } + + if (compare.y().isConstant()) { + if (compare.x() instanceof MaterializeNode) { + return optimizeMaterialize(compare, compare.y().asConstant(), (MaterializeNode) compare.x()); + } else if (compare.x() instanceof NormalizeCompare) { + return optimizeNormalizeCmp(compare, compare.y().asConstant(), (NormalizeCompare) compare.x()); + } + } + if (compare.x() == compare.y() && compare.x().kind != CiKind.Float && compare.x().kind != CiKind.Double) { return Constant.forBoolean(compare.condition().check(1, 1), compare.graph()); } + if ((compare.condition == Condition.NE || compare.condition == Condition.EQ) && compare.x().kind == CiKind.Object) { + Value object = null; + if (compare.x().isNullConstant()) { + object = compare.y(); + } else if (compare.y().isNullConstant()) { + object = compare.x(); + } + if (object != null) { + IsNonNull nonNull = new IsNonNull(object, compare.graph()); + if (compare.condition == Condition.NE) { + return nonNull; + } else { + assert compare.condition == Condition.EQ; + return new NegateBooleanNode(nonNull, compare.graph()); + } + } + } return compare; } @@ -192,7 +215,7 @@ if (compare.condition == Condition.NE) { isFalseCheck = !isFalseCheck; } - Value result = materializeNode.value(); + BooleanNode result = materializeNode.value(); if (isFalseCheck) { result = new NegateBooleanNode(result, compare.graph()); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java Wed Aug 03 16:28:05 2011 +0200 @@ -136,7 +136,7 @@ return new Iterable() { @Override public Iterator iterator() { - return new StateSplit.FilteringIterator(dataUsages, LoopBegin.class); + return new StateSplit.FilteringIterator(dataUsages, LoopEnd.class); } }; } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java Wed Aug 03 16:28:05 2011 +0200 @@ -70,11 +70,6 @@ } @Override - public String toString() { - return "LoopEnd:" + super.toString(); - } - - @Override public Iterable< ? extends Node> dataInputs() { return Collections.emptyList(); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Wed Aug 03 16:28:05 2011 +0200 @@ -32,18 +32,18 @@ public final class MaterializeNode extends FloatingNode { @NodeInput - private Value value; + private BooleanNode value; - public Value value() { + public BooleanNode value() { return value; } - public void setValue(Value x) { + public void setValue(BooleanNode x) { updateUsages(value, x); value = x; } - public MaterializeNode(Value value, Graph graph) { + public MaterializeNode(BooleanNode value, Graph graph) { super(CiKind.Int, graph); setValue(value); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java Wed Aug 03 16:28:05 2011 +0200 @@ -114,7 +114,7 @@ case Double: return Constant.forDouble(-x.asConstant().asDouble(), graph); } } - if (x instanceof Negate && (x.kind == CiKind.Int || x.kind == CiKind.Long)) { + if (x instanceof Negate) { return ((Negate) x).x(); } return negate; diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Wed Aug 03 16:28:05 2011 +0200 @@ -30,18 +30,18 @@ public final class NegateBooleanNode extends BooleanNode { @NodeInput - private Value value; + private BooleanNode value; - public Value value() { + public BooleanNode value() { return value; } - public void setValue(Value x) { + public void setValue(BooleanNode x) { updateUsages(value, x); value = x; } - public NegateBooleanNode(Value value, Graph graph) { + public NegateBooleanNode(BooleanNode value, Graph graph) { super(CiKind.Int, graph); setValue(value); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java Wed Aug 03 16:28:05 2011 +0200 @@ -104,9 +104,8 @@ append(new LIRLabel(lbl)); } - public void negate(CiValue src, CiValue dst, GlobalStub globalStub) { + public void negate(CiValue src, CiValue dst) { LIRNegate op = new LIRNegate(src, dst); - op.globalStub = globalStub; append(op); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRNegate.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRNegate.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRNegate.java Wed Aug 03 16:28:05 2011 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.max.graal.compiler.lir; -import com.oracle.max.graal.compiler.globalstub.*; import com.sun.cri.ci.*; /** @@ -33,8 +32,6 @@ */ public class LIRNegate extends LIROp1 { - public GlobalStub globalStub; - /** * Constructs a new instruction LIRNegate for a given operand. * diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Wed Aug 03 16:28:05 2011 +0200 @@ -83,6 +83,13 @@ newInvokes = new ArrayDeque(); for (Invoke invoke : queue) { if (!invoke.isDeleted()) { + if (GraalOptions.Meter) { + GraalMetrics.InlineConsidered++; + if (!invoke.target.hasCompiledCode()) { + GraalMetrics.InlineUncompiledConsidered++; + } + } + RiMethod code = inlineInvoke(invoke, iterations, ratio); if (code != null) { if (graph.getNodeCount() > GraalOptions.MaximumInstructionCount) { @@ -97,6 +104,12 @@ methodCount.put(code, methodCount.get(code) + 1); } } + if (GraalOptions.Meter) { + GraalMetrics.InlinePerformed++; + if (!invoke.target.hasCompiledCode()) { + GraalMetrics.InlineUncompiledPerformed++; + } + } } } } @@ -303,6 +316,7 @@ private boolean checkSizeConditions(RiMethod caller, int iterations, RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) { int maximumSize = GraalOptions.MaximumTrivialSize; + int maximumCompiledSize = GraalOptions.MaximumTrivialCompSize; double ratio = 0; if (profile != null && profile.count > 0) { RiMethod parent = invoke.stateAfter().method(); @@ -313,16 +327,27 @@ } if (ratio >= GraalOptions.FreqInlineRatio) { maximumSize = GraalOptions.MaximumFreqInlineSize; + maximumCompiledSize = GraalOptions.MaximumFreqInlineCompSize; } else if (ratio >= 1 * (1 - adjustedRatio)) { maximumSize = GraalOptions.MaximumInlineSize; + maximumCompiledSize = GraalOptions.MaximumInlineCompSize; } } if (hints != null && hints.contains(invoke)) { maximumSize = GraalOptions.MaximumFreqInlineSize; + maximumCompiledSize = GraalOptions.MaximumFreqInlineCompSize; } - if (method.codeSize() > maximumSize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) { + boolean oversize; + int compiledSize = method.compiledCodeSize(); + if (compiledSize < 0) { + oversize = (method.codeSize() > maximumSize); + } else { + oversize = (compiledSize > maximumCompiledSize); + } + if (oversize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) { if (GraalOptions.TraceInlining) { - TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s) or inling level", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); + TTY.println("not inlining %s because of size (bytecode: %d, bytecode max: %d, compiled: %d, compiled max: %d, ratio %5.3f, %s) or inlining level", + methodName(method, invoke), method.codeSize(), maximumSize, compiledSize, maximumCompiledSize, ratio, profile); } if (GraalOptions.Extend) { boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, false); diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Wed Aug 03 16:28:05 2011 +0200 @@ -34,13 +34,15 @@ private int blockID; private final List successors = new ArrayList(); private final List predecessors = new ArrayList(); + private final List dominated = new ArrayList(); private List instructions = new ArrayList(); private Block dominator; private Block javaBlock; - private final List dominators = new ArrayList(); private Anchor anchor; + private EndNode end; private int loopDepth = 0; private int loopIndex = -1; + private double probability; private Node firstNode; private Node lastNode; @@ -54,6 +56,14 @@ this.anchor = null; } + public EndNode end() { + return end; + } + + public void setEnd(EndNode end) { + this.end = end; + } + public Block javaBlock() { return javaBlock; } @@ -82,6 +92,17 @@ loopIndex = i; } + public double probability() { + return probability; + } + + + public void setProbability(double probability) { + if (probability > this.probability) { + this.probability = probability; + } + } + public Anchor createAnchor() { if (anchor == null) { if (firstNode instanceof Anchor) { @@ -133,11 +154,11 @@ assert this.dominator == null; assert dominator != null; this.dominator = dominator; - dominator.dominators.add(this); + dominator.dominated.add(this); } - public List getDominators() { - return Collections.unmodifiableList(dominators); + public List getDominated() { + return Collections.unmodifiableList(dominated); } public List getInstructions() { diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Aug 03 16:28:05 2011 +0200 @@ -30,19 +30,34 @@ import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.NodeClass.*; import com.oracle.max.graal.graph.collections.*; public class IdentifyBlocksPhase extends Phase { + private static final double LIVE_RANGE_COST_FACTOR = 0.05; + private static final double MATERIALIZATION_COST_FACTOR = 1.0 - LIVE_RANGE_COST_FACTOR; + private final List blocks = new ArrayList(); private NodeMap nodeToBlock; + private NodeMap earliestCache; private Graph graph; private boolean scheduleAllNodes; + private boolean splitMaterialization; private int loopCount; public IdentifyBlocksPhase(boolean scheduleAllNodes) { + this(scheduleAllNodes, GraalOptions.SplitMaterialization && filter()); + } + + public static boolean filter() { + return true; //GraalCompilation.compilation().method.name().contains("mergeOrClone"); + } + + public IdentifyBlocksPhase(boolean scheduleAllNodes, boolean splitMaterialization) { super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false); this.scheduleAllNodes = scheduleAllNodes; + this.splitMaterialization = splitMaterialization; } @@ -50,6 +65,7 @@ protected void run(Graph graph) { this.graph = graph; nodeToBlock = graph.createNodeMap(); + earliestCache = graph.createNodeMap(); identifyBlocks(); } @@ -92,6 +108,10 @@ } } + if (n instanceof EndNode) { + assert b.end() == null || n == b.end(); + b.setEnd((EndNode) n); + } if (b.lastNode() == null) { b.setFirstNode(n); b.setLastNode(n); @@ -119,7 +139,7 @@ System.out.println(nodeToBlock); System.out.println("Blocks :"); for (Block b : blocks) { - System.out.println(b + " [S:" + b.getSuccessors() + ", P:" + b.getPredecessors() + ", D:" + b.getDominators()); + System.out.println(b + " [S:" + b.getSuccessors() + ", P:" + b.getPredecessors() + ", D:" + b.getDominated()); System.out.println(" f " + b.firstNode()); for (Node n : b.getInstructions()) { System.out.println(" - " + n); @@ -141,6 +161,9 @@ block = null; } block = assignBlockNew(currentNode, block); + if (currentNode instanceof FixedNode) { + block.setProbability(((FixedNode) currentNode).probability()); + } if (currentNode.predecessor() == null) { // Either dead code or at a merge node => stop iteration. break; @@ -176,7 +199,7 @@ if (scheduleAllNodes) { computeLoopInformation(); // Will make the graph cyclic. - assignLatestPossibleBlockToNodes(); + assignBlockToNodes(); sortNodesWithinBlocks(); } else { computeJavaBlocks(); @@ -284,132 +307,357 @@ } } - private void assignLatestPossibleBlockToNodes() { + private void assignBlockToNodes() { for (Node n : graph.getNodes()) { - assignLatestPossibleBlockToNode(n); + assignBlockToNode(n); } } - private Block assignLatestPossibleBlockToNode(Node n) { + private void assignBlockToNode(Node n) { if (n == null) { - return null; + return; } assert !n.isDeleted(); Block prevBlock = nodeToBlock.get(n); if (prevBlock != null) { - return prevBlock; - } - - Block block = null; - for (Node succ : n.successors()) { - block = getCommonDominator(block, assignLatestPossibleBlockToNode(succ)); + return; } - for (Node usage : n.usages()) { - if (usage instanceof Phi) { - Phi phi = (Phi) usage; - Merge merge = phi.merge(); - Block mergeBlock = nodeToBlock.get(merge); - assert mergeBlock != null : "no block for merge " + merge.id(); - for (int i = 0; i < phi.valueCount(); ++i) { - if (phi.valueAt(i) == n) { - if (mergeBlock.getPredecessors().size() <= i) { - TTY.println(merge.toString()); - TTY.println(phi.toString()); - TTY.println(merge.phiPredecessors().toString()); - TTY.println(phi.inputs().toString()); - TTY.println("value count: " + phi.valueCount()); - } - block = getCommonDominator(block, mergeBlock.getPredecessors().get(i)); - } - } - } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) { - Merge merge = ((FrameState) usage).block(); - for (Node pred : merge.cfgPredecessors()) { - block = getCommonDominator(block, nodeToBlock.get(pred)); - } - } else if (usage instanceof LoopCounter) { - LoopCounter counter = (LoopCounter) usage; - if (n == counter.init() || n == counter.stride()) { - LoopBegin loopBegin = counter.loopBegin(); - Block mergeBlock = nodeToBlock.get(loopBegin); - block = getCommonDominator(block, mergeBlock.dominator()); - } + //TTY.println("Earliest for " + n + " : " + earliest); + // if in CFG, schedule at the latest position possible in the outermost loop possible + // if floating, use rematerialization to place the node, it tries to compute the value only when it will be used, + // in the block with the smallest probability (outside of loops), while minimizing live ranges + if (!splitMaterialization || noRematerialization(n) || n.predecessor() != null || nonNullSuccessorCount(n) > 0) { + Block latestBlock = latestBlock(n); + //TTY.println("Latest for " + n + " : " + latestBlock); + Block block; + if (latestBlock == null) { + block = earliestBlock(n); + } else if (GraalOptions.ScheduleOutOfLoops) { + block = scheduleOutOfLoops(n, latestBlock, earliestBlock(n)); } else { - block = getCommonDominator(block, assignLatestPossibleBlockToNode(usage)); + block = latestBlock; + } + nodeToBlock.set(n, block); + block.getInstructions().add(n); + } else { + GraalTimers timer = GraalTimers.get("earliest"); + timer.start(); + Block earliest = earliestBlock(n); + timer.stop(); + Map> usages = computeUsages(n, earliest); + if (usages.isEmpty()) { + nodeToBlock.set(n, earliest); + earliest.getInstructions().add(n); + } else { + maybeMaterialize(n, earliest, usages, false); } } + } + + private int nonNullSuccessorCount(Node n) { + int suxCount = 0; + for (Node sux : n.successors()) { + if (sux != null) { + suxCount++; + } + } + return suxCount; + } - if (block != null) { - if (GraalOptions.OptOptimisticSchedule) { - block = scheduleOutOfLoops(n, block); + private void maybeMaterialize(Node node, Block block, Map> usages, boolean materializedInDominator) { + Set blockUsages = usages.get(block); + if (blockUsages == null || blockUsages.isEmpty()) { + return; + } + boolean forced = false; + if (!materializedInDominator) { + for (Usage usage : blockUsages) { + if (usage.block == block) { + forced = true; + break; + } } + } + //TODO (gd) if materializedInDominator, compare cost of materialization to cost of current live range instead + if (forced || materializationCost(block, blockUsages) < materializationCostAtChildren(block, usages)) { + Node n; + if (nodeToBlock.get(node) == null) { + n = node; + } else { + n = node.copy(node.graph()); + for (NodeClassIterator iter = node.inputs().iterator(); iter.hasNext();) { + Position pos = iter.nextPosition(); + n.getNodeClass().set(n, pos, node.getNodeClass().get(node, pos)); + } + for (Usage usage : blockUsages) { + patch(usage, node, n); + } + //TTY.println("> Rematerialized " + node + " (new node id = " + n.id() + ") in " + block); + GraalMetrics.Rematerializations++; + nodeToBlock.grow(n); + } + materializedInDominator = true; nodeToBlock.set(n, block); block.getInstructions().add(n); } - return block; + if (!materializedInDominator || GraalOptions.Rematerialize) { + for (Block child : block.getDominated()) { + maybeMaterialize(node, child, usages, materializedInDominator); + } + } } - private Block scheduleOutOfLoops(Node n, Block latestBlock) { - Block cur = latestBlock; - while (cur.loopDepth() != 0) { - if (cur.isLoopHeader()) { - assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size(); - if (canSchedule(n, cur.getPredecessors().get(0))) { - // TTY.println("can schedule out of loop!" + n); - return scheduleOutOfLoops(n, cur.getPredecessors().get(0)); - } else { - break; - } - } - Block prev = cur; - cur = cur.dominator(); - - // This must be a loop exit. - if (cur.loopDepth() > prev.loopDepth()) { -// TTY.println("break out because of different loop depth"); - break; + private double materializationCostAtChildren(Block block, Map> usages) { + double cost = 0.0; + for (Block child : block.getDominated()) { + Set blockUsages = usages.get(child); + if (blockUsages != null && !blockUsages.isEmpty()) { // XXX should never be empty if not null + cost += materializationCost(child, blockUsages); } } - return latestBlock; + return cost; + } + + private double materializationCost(Block block, Set usages) { + //TODO node cost + return /*LIVE_RANGE_COST_FACTOR * liveRange(block, usages) + MATERIALIZATION_COST_FACTOR **/ block.probability() * 1.0; } - private boolean canSchedule(Node n, Block block) { - Set allowedBlocks = new HashSet(); - Block cur = block; - while (cur != null) { - allowedBlocks.add(cur); - cur = cur.dominator(); + + private Block latestBlock(Node n) { + Block block = null; + for (Node succ : n.successors()) { + if (succ == null) { + continue; + } + assignBlockToNode(succ); + block = getCommonDominator(block, nodeToBlock.get(succ)); } - // Now we know the allowed blocks for inputs and predecessors. - return checkNodesAbove(allowedBlocks, n); + ensureScheduledUsages(n); + CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block); + for (Node usage : n.usages()) { + blocksForUsage(n, usage, cdbc); + } + return cdbc.block; } - private boolean checkNodesAbove(Set allowedBlocks, Node n) { - if (n == null) { - return true; + private class CommonDominatorBlockClosure implements BlockClosure { + public Block block; + public CommonDominatorBlockClosure(Block block) { + this.block = block; } - - if (nodeToBlock.get(n) != null) { - return allowedBlocks.contains(nodeToBlock.get(n)); - } else { - assert !(n instanceof Phi) : ((Phi) n).merge(); - for (Node input : n.inputs()) { - if (!checkNodesAbove(allowedBlocks, input)) { - return false; - } - } - if (n.predecessor() != null) { - if (!checkNodesAbove(allowedBlocks, n.predecessor())) { - return false; - } - } - return true; + @Override + public void apply(Block block) { + this.block = getCommonDominator(this.block, block); } } + private Block earliestBlock(Node n) { + Block earliest = nodeToBlock.get(n); + if (earliest != null) { + return earliest; + } + earliest = earliestCache.get(n); + if (earliest != null) { + return earliest; + } + BitMap bits = new BitMap(blocks.size()); + ArrayList before = new ArrayList(); + if (n.predecessor() != null) { + before.add(n.predecessor()); + } + for (Node input : n.inputs()) { + before.add(input); + } + for (Node pred : before) { + if (pred == null) { + continue; + } + Block b = earliestBlock(pred); + if (!bits.get(b.blockID())) { + earliest = b; + do { + bits.set(b.blockID()); + b = b.dominator(); + } while(b != null && !bits.get(b.blockID())); + } + } + if (earliest == null) { + Block start = nodeToBlock.get(graph.start()); + assert start != null; + return start; + } + earliestCache.set(n, earliest); + return earliest; + } + + + private Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { + assert latestBlock != null : "no latest : " + n; + Block cur = latestBlock; + Block prevDepth = latestBlock; + while (cur.loopDepth() != 0 && cur != earliest && cur.dominator() != null && cur.dominator().loopDepth() <= cur.loopDepth()) { + Block dom = cur.dominator(); + if (dom.loopDepth() < prevDepth.loopDepth()) { + prevDepth = dom; + } + cur = dom; + } + return prevDepth; + } + + private void blocksForUsage(Node node, Node usage, BlockClosure closure) { + if (usage instanceof Phi) { + Phi phi = (Phi) usage; + Merge merge = phi.merge(); + Block mergeBlock = nodeToBlock.get(merge); + assert mergeBlock != null : "no block for merge " + merge.id(); + for (int i = 0; i < phi.valueCount(); ++i) { + if (phi.valueAt(i) == node) { + if (mergeBlock.getPredecessors().size() <= i) { + TTY.println(merge.toString()); + TTY.println(phi.toString()); + TTY.println(merge.phiPredecessors().toString()); + TTY.println(phi.inputs().toString()); + TTY.println("value count: " + phi.valueCount()); + } + closure.apply(mergeBlock.getPredecessors().get(i)); + } + } + } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) { + Merge merge = ((FrameState) usage).block(); + Block block = null; + for (Node pred : merge.cfgPredecessors()) { + block = getCommonDominator(block, nodeToBlock.get(pred)); + } + closure.apply(block); + } else if (usage instanceof LoopCounter) { + LoopCounter counter = (LoopCounter) usage; + if (node == counter.init() || node == counter.stride()) { + LoopBegin loopBegin = counter.loopBegin(); + Block mergeBlock = nodeToBlock.get(loopBegin); + closure.apply(mergeBlock.dominator()); + } + } else { + assignBlockToNode(usage); + closure.apply(nodeToBlock.get(usage)); + } + } + + private void patch(Usage usage, Node original, Node patch) { + if (usage.node instanceof Phi) { + Phi phi = (Phi) usage.node; + Node pred; + Block phiBlock = nodeToBlock.get(phi); + if (phiBlock.isLoopHeader()) { + LoopBegin loopBegin = (LoopBegin) phiBlock.firstNode(); + if (usage.block == phiBlock.dominator()) { + pred = loopBegin.forwardEdge(); + } else { + assert usage.block == nodeToBlock.get(loopBegin.loopEnd()); + pred = loopBegin.loopEnd(); + } + } else { + pred = usage.block.end(); + } + int index = phi.merge().phiPredecessorIndex(pred); + phi.setValueAt(index, (Value) patch); + } else { + usage.node.inputs().replace(original, patch); + } + } + + private void ensureScheduledUsages(Node node) { + // assign block to all usages to ensure that any splitting/rematerialization is done on them + for (Node usage : node.usages().snapshot()) { + assignBlockToNode(usage); + } + // now true usages are ready + } + + private Map> computeUsages(Node node, final Block from) { //TODO use a List instead of a Set here ? + final Map> blockUsages = new HashMap>(); + ensureScheduledUsages(node); + for (final Node usage : node.dataUsages()) { + blocksForUsage(node, usage, new BlockClosure() { + @Override + public void apply(Block block) { + addUsageToTree(usage, block, from, blockUsages); + } + }); + } + /*TTY.println("Usages for " + node + " from " + from); + for (Entry> entry : blockUsages.entrySet()) { + TTY.println(" - " + entry.getKey() + " :"); + for (Usage usage : entry.getValue()) { + TTY.println(" + " + usage.node + " in " + usage.block); + } + }*/ + return blockUsages; + } + + private void addUsageToTree(Node usage, Block usageBlock, Block from, Map> blockUsages) { + Block current = usageBlock; + while (current != null) { + Set usages = blockUsages.get(current); + if (usages == null) { + usages = new HashSet(); + blockUsages.put(current, usages); + } + usages.add(new Usage(usageBlock, usage)); + if (current == from) { + current = null; + } else { + current = current.dominator(); + } + } + } + + private static class Usage { + public final Block block; + public final Node node; + public Usage(Block block, Node node) { + this.block = block; + this.node = node; + } + } + + private boolean noRematerialization(Node n) { + return n instanceof Local || n instanceof LocationNode || n instanceof Constant || n instanceof StateSplit || n instanceof FrameState; + } + + private double liveRange(Block from, Set usages) { + BitMap subTree = new BitMap(blocks.size()); + markSubTree(from, subTree); + double range = 0.0; + for (Usage usage : usages) { + range += markRangeUp(usage.block, subTree); + } + return range; + } + + private void markSubTree(Block from, BitMap subTree) { + subTree.set(from.blockID()); + for (Block b : from.getDominated()) { + markSubTree(b, subTree); + } + } + + private double markRangeUp(Block from, BitMap subTree) { + int blockID = from.blockID(); + if (!subTree.get(blockID)) { + return 0.0; + } + subTree.clear(blockID); + double range = from.probability() * (from.getInstructions().size() + 2); + for (Block pred : from.getPredecessors()) { + range += markRangeUp(pred, subTree); + } + return range; + } private Block getCommonDominator(Block a, Block b) { if (a == null) { @@ -445,7 +693,7 @@ int idx = sortedInstructions.indexOf(b.lastNode()); boolean canNotMove = false; for (int i = idx + 1; i < sortedInstructions.size(); i++) { - if (sortedInstructions.get(i).inputContains(b.lastNode())) { + if (sortedInstructions.get(i).inputs().contains(b.lastNode())) { canNotMove = true; break; } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java Wed Aug 03 16:28:05 2011 +0200 @@ -46,8 +46,6 @@ private static final long DoubleSignFlip = 0x8000000000000000L; private static final CiRegister convertArgument = AMD64.xmm0; private static final CiRegister convertResult = AMD64.rax; - private static final CiRegister negateArgument = AMD64.xmm0; - private static final CiRegister negateTemp = AMD64.xmm1; private TargetMethodAssembler tasm; private AMD64MacroAssembler asm; @@ -118,12 +116,6 @@ case d2l: emitD2L(); break; - case fneg: - emitFNEG(); - break; - case dneg: - emitDNEG(); - break; } String name = "stub-" + stub; @@ -251,30 +243,6 @@ return result; } - private void negatePrologue() { - partialSavePrologue(negateArgument, negateTemp); - loadArgument(0, negateArgument); - } - - private void negateEpilogue() { - storeArgument(0, negateArgument); - epilogue(); - } - - private void emitDNEG() { - negatePrologue(); - asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(DoubleSignFlip))); - asm.xorpd(negateArgument, negateTemp); - negateEpilogue(); - } - - private void emitFNEG() { - negatePrologue(); - asm.movsd(negateTemp, tasm.recordDataReferenceInCode(CiConstant.forLong(FloatSignFlip))); - asm.xorps(negateArgument, negateTemp); - negateEpilogue(); - } - private void convertPrologue() { partialSavePrologue(convertArgument, convertResult); loadArgument(0, convertArgument); diff -r a6c1f49a7319 -r ccf5e0d9eb61 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 Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Wed Aug 03 16:28:05 2011 +0200 @@ -1517,14 +1517,12 @@ if (asXmmFloatReg(left) != asXmmFloatReg(dest)) { masm.movflt(asXmmFloatReg(dest), asXmmFloatReg(left)); } - callGlobalStub(op.globalStub, null, asXmmFloatReg(dest), dest); - + masm.xorps(asXmmFloatReg(dest), tasm.recordDataReferenceInCode(CiConstant.forLong(0x8000000080000000L))); } else if (dest.kind.isDouble()) { if (asXmmDoubleReg(left) != asXmmDoubleReg(dest)) { masm.movdbl(asXmmDoubleReg(dest), asXmmDoubleReg(left)); } - - callGlobalStub(op.globalStub, null, asXmmDoubleReg(dest), dest); + masm.xorpd(asXmmDoubleReg(dest), tasm.recordDataReferenceInCode(CiConstant.forLong(0x8000000000000000L))); } else { CiRegister lreg = left.asRegister(); CiRegister dreg = dest.asRegister(); diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Aug 03 16:28:05 2011 +0200 @@ -126,13 +126,7 @@ value.setDestroysRegister(); value.loadItem(); CiVariable reg = newVariable(x.kind); - GlobalStub globalStub = null; - if (x.kind == CiKind.Float) { - globalStub = stubFor(GlobalStub.Id.fneg); - } else if (x.kind == CiKind.Double) { - globalStub = stubFor(GlobalStub.Id.dneg); - } - lir.negate(value.result(), reg, globalStub); + lir.negate(value.result(), reg); setResult(x, reg); } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Wed Aug 03 16:28:05 2011 +0200 @@ -170,9 +170,7 @@ } public boolean hasCompiledCode() { - // TODO: needs a VMEntries to go cache the result of that method. - // This isn't used by GRAAL for now, so this is enough.throwoutCount - return false; + return compiler.getVMEntries().RiMethod_hasCompiledCode(this); } @Override @@ -210,6 +208,11 @@ return compiler.getVMEntries().RiMethod_switchProbability(this, bci); } + @Override + public int compiledCodeSize() { + return compiler.getVMEntries().RiMethod_compiledCodeSize(this); + } + public void dumpProfile() { TTY.println("profile info for %s", this); TTY.println("canBeStaticallyBound: " + canBeStaticallyBound()); diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Wed Aug 03 16:28:05 2011 +0200 @@ -181,4 +181,9 @@ public double[] switchProbability(int bci) { return null; } + + @Override + public int compiledCodeSize() { + return -1; + } } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java Wed Aug 03 16:28:05 2011 +0200 @@ -101,5 +101,9 @@ RiField[] RiType_fields(HotSpotTypeResolved klass); + boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); + + int RiMethod_compiledCodeSize(HotSpotMethodResolved method); + // Checkstyle: resume } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java Wed Aug 03 16:28:05 2011 +0200 @@ -147,5 +147,11 @@ @Override public native RiField[] RiType_fields(HotSpotTypeResolved klass); + @Override + public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); + + @Override + public native int RiMethod_compiledCodeSize(HotSpotMethodResolved method); + // Checkstyle: resume } diff -r a6c1f49a7319 -r ccf5e0d9eb61 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java Wed Aug 03 12:07:11 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java Wed Aug 03 16:28:05 2011 +0200 @@ -30,6 +30,7 @@ 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.graph.*; import com.oracle.max.graal.runtime.logging.*; import com.oracle.max.graal.runtime.server.*; import com.sun.cri.ci.*; @@ -85,7 +86,6 @@ @Override public void run() { if (GraalOptions.Meter) { - GraalMetrics.print(); } if (GraalOptions.Time) { diff -r a6c1f49a7319 -r ccf5e0d9eb61 src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Wed Aug 03 12:07:11 2011 +0200 +++ b/src/share/vm/graal/graalVMEntries.cpp Wed Aug 03 16:28:05 2011 +0200 @@ -183,7 +183,7 @@ return method->invocation_count(); } -// public native int RiMethod_throwoutCount(long vmId); +// public native int RiMethod_exceptionProbability(long vmId, int bci); JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { TRACE_graal_3("VMEntries::RiMethod_exceptionProbability"); ciMethod* cimethod; @@ -337,6 +337,23 @@ } } +// public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); +JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("VMEntries::RiMethod_hasCompiledCode"); + methodOop method = getMethodFromHotSpotMethod(hotspot_method); + return method->has_compiled_code(); +} + +// public native boolean RiMethod_compiledCodeSize(HotSpotMethodResolved method); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1compiledCodeSize(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("VMEntries::RiMethod_compiledCodeSize"); + nmethod* code = getMethodFromHotSpotMethod(hotspot_method)->code(); + if (code != NULL) { + return code->insts_end() - code->verified_entry_point(); + } + return -1; +} + // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { TRACE_graal_3("VMEntries::RiSignature_lookupType"); @@ -901,6 +918,8 @@ {CC"RiMethod_switchProbability", CC"("RESOLVED_METHOD"I)[D", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2switchProbability)}, {CC"RiMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount)}, {CC"RiMethod_exceptionProbability", CC"("RESOLVED_METHOD"I)I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability)}, + {CC"RiMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasCompiledCode)}, + {CC"RiMethod_compiledCodeSize", CC"("RESOLVED_METHOD")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1compiledCodeSize)}, {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)}, {CC"RiConstantPool_lookupConstant", CC"("PROXY"I)"OBJECT, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)}, {CC"RiConstantPool_lookupMethod", CC"("PROXY"IB)"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)},