# HG changeset patch # User Gilles Duboscq # Date 1336035946 -7200 # Node ID de571c017f6162fa983b1cbf0add2c89d27ce0b1 # Parent 00803ae428d2c9754b164eb3c578c4578d59edfd# Parent 077ec9468516d89c90b30709eedbda6907583f41 Merge diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu May 03 11:05:46 2012 +0200 @@ -207,6 +207,15 @@ public static boolean OptSafepointElimination = true; /** + * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal. + */ + public static boolean MethodEntryCounters = false; + /** + * Number of caller program counters to distinguish when counting methods. + */ + public static int MethodEntryCountersCallers = 20; + + /** * Flag to turn on SSA-based register allocation, which is currently under development. */ public static boolean AllocSSA = false; @@ -216,6 +225,26 @@ */ public static boolean PrintFlags = false; + /** + * Counts the various paths taken through a compiled checkcast. + */ + public static boolean CheckcastCounters = false; + + /** + * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints}) + * is below this value, the checkcast will be compiled without hints. + */ + public static double CheckcastMinHintHitProbability = 0.5; + + /** + * The maximum number of hint types that will be used when compiling a checkcast for which + * profiling information is available. Note that {@link #CheckcastMinHintHitProbability} + * also influences whether hints are used. + */ + public static int CheckcastMaxHints = 2; + + public static int InstanceOfMaxHints = 1; + static { // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) assert (DetailedAsserts = true) == true; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java Thu May 03 11:05:46 2012 +0200 @@ -82,7 +82,7 @@ return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode); } - public boolean useUseTypeCheckHints() { + public boolean useTypeCheckHints() { return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/debug/package-info.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/debug/package-info.java Fri Apr 27 13:13:06 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ -/** - * A collection of debugging aids for Graal development. - */ -package com.oracle.graal.compiler.debug; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu May 03 11:05:46 2012 +0200 @@ -484,7 +484,7 @@ return !(location instanceof IndexedLocationNode) && location.displacement() < 4096; } - private void emitPrologue() { + protected void emitPrologue() { CiCallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(method), target, false); CiValue[] params = new CiValue[incomingArguments.locations.length]; @@ -509,10 +509,8 @@ @Override public void visitCheckCast(CheckCastNode x) { - if (x.emitCode()) { - XirSnippet snippet = xir.genCheckCast(site(x, x.object()), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact()); - emitXir(snippet, x, state(), true); - } + XirSnippet snippet = xir.genCheckCast(site(x, x.object()), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact()); + emitXir(snippet, x, state(), true); // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it. setResult(x, operand(x.object())); } @@ -914,11 +912,9 @@ protected abstract LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo); @Override - public Variable emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) { + public Variable emitCall(@SuppressWarnings("hiding") Object target, CiKind result, CiKind[] arguments, boolean canTrap, CiValue... args) { LIRDebugInfo info = canTrap ? state() : null; - CiKind result = runtimeCall.resultKind; - CiKind[] arguments = runtimeCall.arguments; CiValue physReg = resultOperandFor(result); List argumentList; @@ -939,7 +935,7 @@ argumentList = Collections.emptyList(); } - emitCall(runtimeCall, physReg, argumentList, CiConstant.forLong(0), info, null); + emitCall(target, physReg, argumentList, CiConstant.forLong(0), info, null); if (isLegal(physReg)) { return emitMove(physReg); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Thu May 03 11:05:46 2012 +0200 @@ -70,7 +70,6 @@ METRIC_PROCESSED_NODES.increment(); if (node instanceof Canonicalizable) { METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - Debug.log("Canonicalizer: work on %s", node); graph.mark(); ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: @@ -85,7 +84,11 @@ // Fixed-connected| 2 | X | 6 | // -------------------------------------------- // X: must not happen (checked with assertions) - if (canonical != node) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); if (node instanceof FloatingNode) { if (canonical == null) { @@ -122,6 +125,7 @@ nodeWorkList.addAll(graph.getNewNodes()); } } else if (node instanceof Simplifiable) { + Debug.log("Canonicalizer: simplifying %s", node); METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); ((Simplifiable) node).simplify(tool); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Thu May 03 11:05:46 2012 +0200 @@ -80,7 +80,7 @@ @SuppressWarnings("unchecked") @Override - protected void run(StructuredGraph graph) { + protected void run(final StructuredGraph graph) { graph.createNodeMap(); if (hints != null) { @@ -91,8 +91,16 @@ } while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { - InlineInfo info = inlineCandidates.remove(); - if (info.invoke.node().isAlive() && inliningPolicy.isWorthInlining(graph, info)) { + final InlineInfo info = inlineCandidates.remove(); + + boolean inline = Debug.scope("InliningDecisions", new Callable() { + @Override + public Boolean call() throws Exception { + return info.invoke.node().isAlive() && inliningPolicy.isWorthInlining(graph, info); + } + }); + + if (inline) { Iterable newNodes = null; try { info.inline(graph, runtime, this); @@ -124,24 +132,35 @@ } if (GraalOptions.Debug && graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) { - Debug.log("inlining cut off by MaximumDesiredSize"); + Debug.scope("InliningDecisions", new Runnable() { + public void run() { + for (InlineInfo info : inlineCandidates) { + Debug.log("not inlining %s because inlining cut off by MaximumDesiredSize", InliningUtil.methodName(info)); + } + } + }); + metricInliningStoppedByMaxDesiredSize.increment(); } } - private void scanInvokes(Iterable newNodes, int level, StructuredGraph graph) { - graph.mark(); - for (Node node : newNodes) { - if (node != null) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - scanInvoke(invoke, level); - } - for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { - scanInvoke((Invoke) usage, level); + private void scanInvokes(final Iterable newNodes, final int level, final StructuredGraph graph) { + Debug.scope("InliningDecisions", new Runnable() { + public void run() { + graph.mark(); + for (Node node : newNodes) { + if (node != null) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + scanInvoke(invoke, level); + } + for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { + scanInvoke((Invoke) usage, level); + } + } } } - } + }); } private void scanInvoke(Invoke invoke, int level) { @@ -282,11 +301,11 @@ double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp; if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) { - Debug.log("not inlining (cut off by weight %e): %s", info.weight, info); + Debug.log("not inlining %s (cut off by weight %e)", InliningUtil.methodName(info), info.weight); return false; } - Debug.log("inlining (weight %f): %s", info.weight, info); + Debug.log("inlining %s (weight %f): %s", InliningUtil.methodName(info), info.weight); return true; } } @@ -361,15 +380,15 @@ private static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { boolean success = info.weight <= maxSize; if (DebugScope.getInstance().isLogEnabled()) { - String formatterString = success ? "inlining invoke at %s@%d (size %f <= %f): %s" : "not inlining invoke at %s@%d (too large %f > %f): %s"; - Debug.log(formatterString, CiUtil.format("%H.%n(%p):%r", info.invoke.stateAfter().method()), info.invoke.bci(), info.weight, maxSize, info); + String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)"; + Debug.log(formatterString, InliningUtil.methodName(info), info.weight, maxSize); } return success; } private static boolean checkCompiledCodeSize(InlineInfo info) { if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) { - Debug.log("not inlining invoke at %s@%d (CompiledCodeSize %d > %d): %s", CiUtil.format("%H.%n(%p):%r", info.invoke.stateAfter().method()), info.invoke.bci(), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize, info); + Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize); return false; } return true; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/UnscheduleNodes.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/UnscheduleNodes.java Fri Apr 27 13:13:06 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.schedule; - -import java.util.*; - -import com.oracle.graal.compiler.graph.*; -import com.oracle.graal.compiler.types.*; -import com.oracle.graal.nodes.*; - -class UnscheduleState implements MergeableState { - - public FixedWithNextNode last; - - @Override - public boolean merge(MergeNode merge, List withStates) { - last = null; - return true; - } - - @Override - public void loopBegin(LoopBeginNode loop) { - last = null; - } - - @Override - public void loopEnds(LoopBeginNode loop, List loopEndStates) { - last = null; - } - - @Override - public void afterSplit(FixedNode node) { - last = null; - } - - @Override - public UnscheduleState clone() { - return new UnscheduleState(); - } -} - -public class UnscheduleNodes extends ScheduledNodeIterator { - - public UnscheduleNodes(FixedNode start) { - super(start, new UnscheduleState()); - } - - @Override - protected void node(ScheduledNode node) { - if (node instanceof FixedNode) { - if (state.last != null) { - state.last.setNext((FixedNode) node); - } - if (node instanceof FixedWithNextNode) { - state.last = (FixedWithNextNode) node; - } - } else { - node.setScheduledNext(null); - } - } -} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java Thu May 03 11:05:46 2012 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.target; + +import com.oracle.graal.compiler.gen.*; + +public interface LIRGenLowerable { + + void generate(LIRGenerator generator); +} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu May 03 11:05:46 2012 +0200 @@ -37,6 +37,7 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirMark; import com.oracle.max.cri.xir.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.compiler.util.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; @@ -102,8 +103,8 @@ @Override protected void emitNode(ValueNode node) { - if (node instanceof AMD64LIRLowerable) { - ((AMD64LIRLowerable) node).generateAmd64(this); + if (node instanceof LIRGenLowerable) { + ((LIRGenLowerable) node).generate(this); } else { super.emitNode(node); } @@ -338,7 +339,7 @@ } @Override - public Variable emitRem(CiValue a, CiValue b) { + public CiValue emitRem(CiValue a, CiValue b) { switch(a.kind) { case Int: emitMove(a, RAX_I); @@ -349,9 +350,9 @@ append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); case Float: - return emitCallToRuntime(CiRuntimeCall.ArithmeticFrem, false, a, b); + return emitCall(CiRuntimeCall.ArithmeticFrem, false, a, b); case Double: - return emitCallToRuntime(CiRuntimeCall.ArithmeticDrem, false, a, b); + return emitCall(CiRuntimeCall.ArithmeticDrem, false, a, b); default: throw GraalInternalError.shouldNotReachHere(); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRLowerable.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRLowerable.java Fri Apr 27 13:13:06 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.target.amd64; - -public interface AMD64LIRLowerable { - - void generateAmd64(AMD64LIRGenerator generator); -} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Thu May 03 11:05:46 2012 +0200 @@ -26,9 +26,6 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.Representation; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.cri.*; @@ -40,7 +37,11 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType; public class InliningUtil { @@ -51,21 +52,35 @@ void recordConcreteMethodAssumption(RiResolvedMethod method, RiResolvedType context, RiResolvedMethod impl); } - private static String methodName(RiResolvedMethod method, Invoke invoke) { - if (Debug.isLogEnabled()) { - if (invoke != null && invoke.stateAfter() != null) { - RiMethod parent = invoke.stateAfter().method(); - return parent.name() + "@" + invoke.bci() + ": " + methodNameAndCodeSize(method); - } else { - return methodNameAndCodeSize(method); - } + public static String methodName(RiResolvedMethod method, Invoke invoke) { + if (!Debug.isLogEnabled()) { + return null; + } else if (invoke != null && invoke.stateAfter() != null) { + return methodName(invoke.stateAfter(), invoke.bci()) + ": " + CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; } else { - return null; + return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; } } - private static String methodNameAndCodeSize(RiResolvedMethod method) { - return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + public static String methodName(InlineInfo info) { + if (!Debug.isLogEnabled()) { + return null; + } else if (info.invoke != null && info.invoke.stateAfter() != null) { + return methodName(info.invoke.stateAfter(), info.invoke.bci()) + ": " + info.toString(); + } else { + return info.toString(); + } + } + + private static String methodName(FrameState frameState, int bci) { + StringBuilder sb = new StringBuilder(); + if (frameState.outerFrameState() != null) { + sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci)); + sb.append("->"); + } + sb.append(CiUtil.format("%h.%n", frameState.method())); + sb.append("@").append(bci); + return sb.toString(); } /** @@ -179,8 +194,8 @@ AnchorNode anchor = graph.add(new AnchorNode()); assert invoke.predecessor() != null; - CheckCastNode checkCast = createAnchoredReceiver(graph, runtime, anchor, type, receiver); - invoke.callTarget().replaceFirstInput(receiver, checkCast); + ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver); + invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); graph.addBeforeFixed(invoke.node(), objectClass); graph.addBeforeFixed(invoke.node(), guard); @@ -209,21 +224,19 @@ */ private static class MultiTypeGuardInlineInfo extends InlineInfo { public final List concretes; - public final RiResolvedType[] types; + public final ProfiledType[] ptypes; public final int[] typesToConcretes; - public final double[] typeProbabilities; public final double notRecordedTypeProbability; - public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List concretes, RiResolvedType[] types, - int[] typesToConcretes, double[] typeProbabilities, double notRecordedTypeProbability) { + public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List concretes, ProfiledType[] ptypes, + int[] typesToConcretes, double notRecordedTypeProbability) { super(invoke, weight, level); - assert concretes.size() > 0 && concretes.size() <= types.length : "must have at least one method but no more than types methods"; - assert types.length == typesToConcretes.length && types.length == typeProbabilities.length : "array length must match"; + assert concretes.size() > 0 && concretes.size() <= ptypes.length : "must have at least one method but no more than types methods"; + assert ptypes.length == typesToConcretes.length : "array lengths must match"; this.concretes = concretes; - this.types = types; + this.ptypes = ptypes; this.typesToConcretes = typesToConcretes; - this.typeProbabilities = typeProbabilities; this.notRecordedTypeProbability = notRecordedTypeProbability; } @@ -291,7 +304,7 @@ for (int j = 0; j < typesToConcretes.length; j++) { if (typesToConcretes[j] == i) { predecessors++; - probability += typeProbabilities[j]; + probability += ptypes[j].probability; } } @@ -334,8 +347,8 @@ RiResolvedType commonType = getLeastCommonType(i); ValueNode receiver = invokeForInlining.callTarget().receiver(); - CheckCastNode checkCast = createAnchoredReceiver(graph, runtime, node, commonType, receiver); - invokeForInlining.callTarget().replaceFirstInput(receiver, checkCast); + ValueNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver); + invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver); RiResolvedMethod concrete = concretes.get(i); StructuredGraph calleeGraph = getGraph(concrete, callback); @@ -350,9 +363,9 @@ for (int i = 0; i < typesToConcretes.length; i++) { if (typesToConcretes[i] == concreteMethodIndex) { if (commonType == null) { - commonType = types[i]; + commonType = ptypes[i].type; } else { - commonType = commonType.leastCommonAncestor(types[i]); + commonType = commonType.leastCommonAncestor(ptypes[i].type); } } } @@ -361,7 +374,7 @@ } private void inlineSingleMethod(StructuredGraph graph, GraalRuntime runtime, InliningCallback callback) { - assert concretes.size() == 1 && types.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; + assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; MergeNode calleeEntryNode = graph.add(new MergeNode()); calleeEntryNode.setProbability(invoke.probability()); @@ -383,15 +396,15 @@ } private FixedNode createDispatchOnType(StructuredGraph graph, ReadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) { - assert types.length > 1; + assert ptypes.length > 1; - int lastIndex = types.length - 1; - double[] branchProbabilities = convertTypeToBranchProbabilities(typeProbabilities, notRecordedTypeProbability); - double nodeProbability = typeProbabilities[lastIndex]; - IfNode nextNode = createTypeCheck(graph, objectClassNode, types[lastIndex], calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability); + int lastIndex = ptypes.length - 1; + double[] branchProbabilities = convertTypeToBranchProbabilities(ptypes, notRecordedTypeProbability); + double nodeProbability = ptypes[lastIndex].probability; + IfNode nextNode = createTypeCheck(graph, objectClassNode, ptypes[lastIndex].type, calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability); for (int i = lastIndex - 1; i >= 0; i--) { - nodeProbability += typeProbabilities[i]; - nextNode = createTypeCheck(graph, objectClassNode, types[i], calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability); + nodeProbability += ptypes[i].probability; + nextNode = createTypeCheck(graph, objectClassNode, ptypes[i].type, calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability); } return nextNode; @@ -411,12 +424,12 @@ return result; } - private static double[] convertTypeToBranchProbabilities(double[] typeProbabilities, double notRecordedTypeProbability) { - double[] result = new double[typeProbabilities.length]; + private static double[] convertTypeToBranchProbabilities(ProfiledType[] ptypes, double notRecordedTypeProbability) { + double[] result = new double[ptypes.length]; double total = notRecordedTypeProbability; - for (int i = typeProbabilities.length - 1; i >= 0; i--) { - total += typeProbabilities[i]; - result[i] = typeProbabilities[i] / total; + for (int i = ptypes.length - 1; i >= 0; i--) { + total += ptypes[i].probability; + result[i] = ptypes[i].probability / total; } assert total > 0.99 && total < 1.01; return result; @@ -483,7 +496,7 @@ @Override public String toString() { StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic"); - builder.append(String.format(", %d methods with %d type checks:", concretes.size(), types.length)); + builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length)); for (int i = 0; i < concretes.size(); i++) { builder.append(CiUtil.format(" %H.%n(%p):%r", concretes.get(i))); } @@ -598,15 +611,13 @@ RiProfilingInfo profilingInfo = parent.profilingInfo(); RiTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci()); if (typeProfile != null) { - RiResolvedType[] types = typeProfile.getTypes(); - double[] probabilities = typeProfile.getProbabilities(); + ProfiledType[] ptypes = typeProfile.getTypes(); - if (types != null && probabilities != null && types.length > 0) { - assert types.length == probabilities.length : "length must match"; + if (ptypes != null && ptypes.length > 0) { double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); - if (types.length == 1 && notRecordedTypeProbability == 0) { + if (ptypes.length == 1 && notRecordedTypeProbability == 0) { if (optimisticOpts.inlineMonomorphicCalls()) { - RiResolvedType type = types[0]; + RiResolvedType type = ptypes[0].type; RiResolvedMethod concrete = type.resolveMethodImpl(targetMethod); if (checkTargetConditions(invoke, concrete, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke); @@ -632,9 +643,9 @@ // determine concrete methods and map type to specific method ArrayList concreteMethods = new ArrayList<>(); - int[] typesToConcretes = new int[types.length]; - for (int i = 0; i < types.length; i++) { - RiResolvedMethod concrete = types[i].resolveMethodImpl(targetMethod); + int[] typesToConcretes = new int[ptypes.length]; + for (int i = 0; i < ptypes.length; i++) { + RiResolvedMethod concrete = ptypes[i].type.resolveMethodImpl(targetMethod); int index = concreteMethods.indexOf(concrete); if (index < 0) { @@ -655,7 +666,7 @@ } if (canInline) { - return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, types, typesToConcretes, probabilities, notRecordedTypeProbability); + return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability); } else { Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke)); return null; @@ -679,11 +690,9 @@ } } - private static CheckCastNode createAnchoredReceiver(StructuredGraph graph, GraalRuntime runtime, FixedNode anchor, RiResolvedType commonType, ValueNode receiver) { + private static ValueNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, RiResolvedType commonType, ValueNode receiver) { // to avoid that floating reads on receiver fields float above the type check - ConstantNode typeConst = graph.unique(ConstantNode.forCiConstant(commonType.getEncoding(Representation.ObjectHub), runtime, graph)); - CheckCastNode checkCast = graph.unique(new CheckCastNode(anchor, typeConst, commonType, receiver, false)); - return checkCast; + return graph.unique(new PiNode(receiver, anchor, StampFactory.declaredNonNull(commonType))); } private static boolean checkInvokeConditions(Invoke invoke) { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java Thu May 03 11:05:46 2012 +0200 @@ -29,9 +29,6 @@ */ public class GraalInternalError extends Error { - /** - * - */ private static final long serialVersionUID = 8776065085829593278L; private Node node; private Graph graph; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Thu May 03 11:05:46 2012 +0200 @@ -63,7 +63,7 @@ } public boolean isMarked(Node node) { - check(node); + assert check(node); return bitMap.get(node.id()); } @@ -72,12 +72,12 @@ } public void mark(Node node) { - check(node); + assert check(node); bitMap.set(node.id()); } public void clear(Node node) { - check(node); + assert check(node); bitMap.clear(node.id()); } @@ -93,10 +93,11 @@ bitMap.grow(graph.nodeIdCount()); } - private void check(Node node) { + private boolean 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() + ")"; - assert node.isAlive() : "node " + node + " is deleted!"; + assert !isNew(node) : "node was added to the graph after creating the node bitmap"; + assert node.isAlive() : "node is deleted!"; + return true; } @Override diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Thu May 03 11:05:46 2012 +0200 @@ -28,9 +28,6 @@ */ public class VerificationError extends GraalInternalError { - /** - * - */ private static final long serialVersionUID = 8459607567446819822L; /** diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerObject.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerObject.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerObject.java Thu May 03 11:05:46 2012 +0200 @@ -29,9 +29,6 @@ * Parent class for all HotSpot Ri... types. */ public abstract class CompilerObject implements Serializable { - /** - * - */ private static final long serialVersionUID = -4551670987101214877L; protected final Compiler compiler; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Thu May 03 11:05:46 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot; +import java.io.*; import java.util.concurrent.*; import com.oracle.graal.compiler.*; @@ -57,7 +58,8 @@ public void run() { if (GraalOptions.Debug) { Debug.enable(); - HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, GraalOptions.LogFile); + PrintStream log = CompilerImpl.getInstance().getVMToCompiler().log(); + HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log); Debug.setConfig(hotspotDebugConfig); } super.run(); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Thu May 03 11:05:46 2012 +0200 @@ -43,10 +43,7 @@ private final List dumpHandlers = new ArrayList<>(); private final PrintStream output; - private static final PrintStream cachedOut = System.out; - - - public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, String logFile) { + public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output) { this.logFilter = DebugFilter.parse(logFilter); this.meterFilter = DebugFilter.parse(meterFilter); this.timerFilter = DebugFilter.parse(timerFilter); @@ -72,15 +69,7 @@ dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort)); } dumpHandlers.add(new CFGPrinterObserver()); - if (logFile == null || logFile.isEmpty()) { - output = cachedOut; - } else { - try { - output = new PrintStream(logFile); - } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't create log file: " + logFile, e); - } - } + this.output = output; } public boolean isLogEnabled() { @@ -163,10 +152,12 @@ Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) { Debug.log("Context obj %s", o); - if (o instanceof Graph && GraalOptions.DumpOnError) { - Graph graph = (Graph) o; - Debug.log("Found graph in context: ", graph); - Debug.dump(o, "Exception graph"); + if (o instanceof Graph) { + if (GraalOptions.DumpOnError) { + Debug.dump(o, "Exception graph"); + } else { + Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error"); + } } } return null; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java Thu May 03 11:05:46 2012 +0200 @@ -34,9 +34,6 @@ */ public final class HotSpotTargetMethod extends CompilerObject { - /** - * - */ private static final long serialVersionUID = 7807321392203253218L; public final CiTargetMethod targetMethod; public final HotSpotMethodResolved method; // used only for methods diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu May 03 11:05:46 2012 +0200 @@ -29,9 +29,6 @@ */ public final class HotSpotVMConfig extends CompilerObject { - /** - * - */ private static final long serialVersionUID = -4744897993263044184L; private HotSpotVMConfig() { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Thu May 03 11:05:46 2012 +0200 @@ -119,5 +119,7 @@ long[] getDeoptedLeafGraphIds(); + String decodePC(long pc); + // Checkstyle: resume } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu May 03 11:05:46 2012 +0200 @@ -171,5 +171,8 @@ @Override public native long[] getDeoptedLeafGraphIds(); + @Override + public native String decodePC(long pc); + // Checkstyle: resume } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Thu May 03 11:05:46 2012 +0200 @@ -23,9 +23,13 @@ package com.oracle.graal.hotspot.bridge; +import java.io.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.hotspot.ri.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.graal.hotspot.ri.*; /** * Calls from HotSpot into Java. @@ -40,6 +44,8 @@ void bootstrap() throws Throwable; + PrintStream log(); + RiMethod createRiMethodUnresolved(String name, String signature, RiType holder); RiSignature createRiSignature(String signature); @@ -59,4 +65,6 @@ CiConstant createCiConstantDouble(double value); CiConstant createCiConstantObject(Object object); + + PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu May 03 11:05:46 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.bridge; +import java.io.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -35,6 +36,7 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; +import com.oracle.graal.hotspot.counters.*; import com.oracle.graal.hotspot.ri.*; import com.oracle.graal.hotspot.server.*; import com.oracle.graal.hotspot.snippets.*; @@ -66,6 +68,8 @@ private ThreadPoolExecutor slowCompileQueue; private AtomicInteger compileTaskIds = new AtomicInteger(); + private PrintStream log = System.out; + public VMToCompilerImpl(Compiler compiler) { this.compiler = compiler; @@ -81,8 +85,16 @@ } public void startCompiler() throws Throwable { - // Make sure TTY is initialized here such that the correct System.out is used for TTY. - TTY.initialize(); + if (GraalOptions.LogFile != null) { + try { + final boolean enableAutoflush = true; + log = new PrintStream(new FileOutputStream(GraalOptions.LogFile), enableAutoflush); + } catch (FileNotFoundException e) { + throw new RuntimeException("couldn't open log file: " + GraalOptions.LogFile, e); + } + } + + TTY.initialize(log); if (GraalOptions.Log == null && GraalOptions.Meter == null && GraalOptions.Time == null && GraalOptions.Dump == null) { if (GraalOptions.MethodFilter != null) { @@ -92,7 +104,7 @@ if (GraalOptions.Debug) { Debug.enable(); - HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, GraalOptions.LogFile); + HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log); Debug.setConfig(hotspotDebugConfig); } // Install intrinsics. @@ -211,6 +223,7 @@ } System.gc(); CiCompilationStatistics.clear("bootstrap2"); + MethodEntryCounters.printCounters(compiler); } private void enqueue(Method m) throws Throwable { @@ -264,6 +277,8 @@ } } CiCompilationStatistics.clear("final"); + MethodEntryCounters.printCounters(compiler); + HotSpotXirGenerator.printCounters(TTY.out().out()); } private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { @@ -349,7 +364,7 @@ final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); int id = compileTaskIds.incrementAndGet(); - CompilationTask task = CompilationTask.create(compiler, createHotSpotSpecificPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); + CompilationTask task = CompilationTask.create(compiler, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); if (blocking) { task.runCompilation(); } else { @@ -461,7 +476,7 @@ } - private PhasePlan createHotSpotSpecificPhasePlan(OptimisticOptimizations optimisticOpts) { + public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) { PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); @@ -470,4 +485,9 @@ } return phasePlan; } + + @Override + public PrintStream log() { + return log; + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java Thu May 03 11:05:46 2012 +0200 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.counters; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import sun.misc.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.Compiler; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.criutils.*; + + +public class MethodEntryCounters { + protected static final class Counter implements Comparable { + protected static ArrayList counters = new ArrayList<>(); + + protected final String method; + protected final long[] counts = new long[GraalOptions.MethodEntryCountersCallers * 2 + 2]; + + protected long sortCount; + + protected Counter(RiResolvedMethod method) { + this.method = CiUtil.format("%H.%n", method); + counters.add(this); + } + + @Override + public int compareTo(Counter o) { + return (int) (o.sortCount - sortCount); + } + } + + + protected static class AMD64MethodEntryOp extends AMD64LIRInstruction { + protected static int codeSize; + + protected final Counter counter; + + protected AMD64MethodEntryOp(Counter counter, CiValue counterArr, CiValue callerPc) { + super("ENTRY_COUNTER", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, new CiValue[] {counterArr, callerPc}); + this.counter = counter; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + int start = masm.codeBuffer.position(); + + CiValue counterArr = temp(0); + CiValue callerPc = temp(1); + + int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class); + int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class); + + AMD64Move.move(tasm, masm, counterArr, CiConstant.forObject(counter.counts)); + AMD64Move.load(tasm, masm, callerPc, new CiAddress(CiKind.Long, AMD64.rbp.asValue(CiKind.Long), 8), null); + + Label done = new Label(); + for (int i = 0; i < counter.counts.length - 2; i += 2) { + CiAddress counterPcAddr = new CiAddress(CiKind.Long, counterArr, i * scale + off); + CiAddress counterValueAddr = new CiAddress(CiKind.Long, counterArr, (i + 1) * scale + off); + + Label skipClaim = new Label(); + masm.cmpq(counterPcAddr, 0); + masm.jccb(ConditionFlag.notEqual, skipClaim); + AMD64Move.store(tasm, masm, counterPcAddr, callerPc, null); + masm.bind(skipClaim); + + Label skipInc = new Label(); + masm.cmpq(counterPcAddr, asRegister(callerPc)); + masm.jccb(ConditionFlag.notEqual, skipInc); + masm.addq(counterValueAddr, 1); + masm.jmp(done); + masm.bind(skipInc); + } + + CiAddress counterValueAddr = new CiAddress(CiKind.Long, counterArr, (counter.counts.length - 1) * scale + off); + masm.addq(counterValueAddr, 1); + masm.bind(done); + + int size = masm.codeBuffer.position() - start; + assert codeSize == 0 || codeSize == size; + codeSize = size; + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Temp && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp && index == 1) { + return EnumSet.of(OperandFlag.Register); + } + throw GraalInternalError.shouldNotReachHere(); + } + } + + + public static void emitCounter(LIRGenerator gen, RiResolvedMethod method) { + if (!GraalOptions.MethodEntryCounters) { + return; + } + gen.append(new AMD64MethodEntryOp(new Counter(method), gen.newVariable(CiKind.Long), gen.newVariable(CiKind.Long))); + } + + public static int getCodeSize() { + if (!GraalOptions.MethodEntryCounters) { + return 0; + } + return AMD64MethodEntryOp.codeSize; + } + + + public static void printCounters(Compiler compiler) { + if (!GraalOptions.MethodEntryCounters) { + return; + } + ArrayList copy = new ArrayList<>(Counter.counters); + long total = 0; + for (Counter counter : copy) { + long sum = 0; + for (int i = 0; i < counter.counts.length; i += 2) { + sum += counter.counts[i + 1]; + } + counter.sortCount = sum; + total += sum; + } + Collections.sort(copy); + + TTY.println(); + TTY.println("** Compiled method invocation counters **"); + for (Counter counter : copy) { + TTY.println("%16d %5.2f%% %s", counter.sortCount, (double) counter.sortCount / total * 100d, counter.method); + + if (counter.counts.length > 2) { + for (int i = 0; i < counter.counts.length; i += 2) { + if (counter.counts[i] != 0 || counter.counts[i + 1] != 0) { + TTY.print(" %16d %5.2f%%", counter.counts[i + 1], (double) counter.counts[i + 1] / counter.sortCount * 100d); + if (counter.counts[i] == 0) { + TTY.println(" [other callers]"); + } else { + TTY.println(" %x %s", counter.counts[i], compiler.getCompilerToVM().decodePC(counter.counts[i])); + } + counter.counts[i] = 0; + counter.counts[i + 1] = 0; + } + } + } + } + TTY.println("** Compiled method invocation counters **"); + TTY.println(); + } +} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotExceptionHandler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotExceptionHandler.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotExceptionHandler.java Thu May 03 11:05:46 2012 +0200 @@ -27,9 +27,6 @@ public final class HotSpotExceptionHandler extends CompilerObject implements RiExceptionHandler { - /** - * - */ private static final long serialVersionUID = 7110038548061733686L; private int startBci; private int endBci; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java Thu May 03 11:05:46 2012 +0200 @@ -38,9 +38,6 @@ */ public class HotSpotField extends CompilerObject implements RiResolvedField { - /** - * - */ private static final long serialVersionUID = 7692985878836955683L; private final RiResolvedType holder; private final String name; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotKlassOop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotKlassOop.java Thu May 03 11:05:46 2012 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.ri; + +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.Compiler; + +/** + * A mechanism for safely conveying a HotSpot klassOop value from the compiler to the C++ code. + * Such values should not be directly exposed to Java code as they are not real Java + * objects. For instance, invoking a method on them or using them in an instanceof + * expression will most likely crash the VM. + */ +public class HotSpotKlassOop extends CompilerObject { + + private static final long serialVersionUID = -5445542223575839143L; + + /** + * The Java object from which the klassOop value can be derived (by the C++ code). + */ + public final Class javaMirror; + + HotSpotKlassOop(Compiler compiler, Class javaMirror) { + super(compiler); + this.javaMirror = javaMirror; + } +} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java Thu May 03 11:05:46 2012 +0200 @@ -28,9 +28,6 @@ public abstract class HotSpotMethod extends CompilerObject implements RiMethod { - /** - * - */ private static final long serialVersionUID = 7167491397941960839L; protected String name; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java Thu May 03 11:05:46 2012 +0200 @@ -30,13 +30,11 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiTypeProfile.*; public final class HotSpotMethodData extends CompilerObject { - /** - * - */ private static final long serialVersionUID = -8873133496591225071L; static { @@ -335,8 +333,8 @@ public RiTypeProfile getTypeProfile(HotSpotMethodData data, int position) { int typeProfileWidth = config.typeProfileWidth; - RiResolvedType[] sparseTypes = new RiResolvedType[typeProfileWidth]; - double[] counts = new double[typeProfileWidth]; + RiResolvedType[] types = new RiResolvedType[typeProfileWidth]; + long[] counts = new long[typeProfileWidth]; long totalCount = 0; int entries = 0; @@ -349,7 +347,9 @@ graalMirror = CompilerImpl.getInstance().getCompilerToVM().getType(javaClass); assert graalMirror != null : "must not return null"; } - sparseTypes[entries] = (RiResolvedType) graalMirror; + + + types[entries] = (RiResolvedType) graalMirror; long count = data.readUnsignedInt(position, getCountOffset(i)); totalCount += count; @@ -360,7 +360,7 @@ } totalCount += getTypesNotRecordedExecutionCount(data, position); - return createRiTypeProfile(sparseTypes, counts, totalCount, entries); + return createRiTypeProfile(types, counts, totalCount, entries); } protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { @@ -369,29 +369,24 @@ return getCounterValue(data, position); } - private static RiTypeProfile createRiTypeProfile(RiResolvedType[] sparseTypes, double[] counts, long totalCount, int entries) { - RiResolvedType[] types; - double[] probabilities; - + private static RiTypeProfile createRiTypeProfile(RiResolvedType[] types, long[] counts, long totalCount, int entries) { if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) { return null; - } else if (entries < sparseTypes.length) { - types = Arrays.copyOf(sparseTypes, entries); - probabilities = new double[entries]; - } else { - types = sparseTypes; - probabilities = counts; } + ProfiledType[] ptypes = new ProfiledType[entries]; double totalProbability = 0.0; for (int i = 0; i < entries; i++) { - double p = counts[i] / totalCount; - probabilities[i] = p; + double p = counts[i]; + p = p / totalCount; totalProbability += p; + ptypes[i] = new ProfiledType(types[i], p); } + Arrays.sort(ptypes); + double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability)); - return new RiTypeProfile(types, notRecordedTypeProbability, probabilities); + return new RiTypeProfile(ptypes, notRecordedTypeProbability); } private static int getReceiverOffset(int row) { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java Thu May 03 11:05:46 2012 +0200 @@ -29,7 +29,6 @@ public interface HotSpotMethodResolved extends RiResolvedMethod, Remote { RiResolvedMethod uniqueConcreteMethod(); - void dumpProfile(); int vtableEntryOffset(); void setCurrentTask(CompilationTask task); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Thu May 03 11:05:46 2012 +0200 @@ -27,12 +27,13 @@ import java.util.*; import java.util.concurrent.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.counters.*; +import com.oracle.graal.java.bytecode.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.criutils.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.java.bytecode.*; /** * Implementation of RiMethod for resolved HotSpot methods. @@ -186,7 +187,12 @@ } public int compiledCodeSize() { - return compiler.getCompilerToVM().RiMethod_getCompiledCodeSize(this); + int result = compiler.getCompilerToVM().RiMethod_getCompiledCodeSize(this); + if (result > 0) { + assert result > MethodEntryCounters.getCodeSize(); + result = result - MethodEntryCounters.getCodeSize(); + } + return result; } @Override @@ -248,62 +254,6 @@ } @Override - public void dumpProfile() { - TTY.println("profile info for %s", this); - TTY.println("canBeStaticallyBound: " + canBeStaticallyBound()); - TTY.println("invocationCount: " + invocationCount()); - RiProfilingInfo profilingInfo = this.profilingInfo(); - for (int i = 0; i < codeSize(); i++) { - if (profilingInfo.getExecutionCount(i) != -1) { - TTY.println(" executionCount@%d: %d", i, profilingInfo.getExecutionCount(i)); - } - - if (profilingInfo.getBranchTakenProbability(i) != -1) { - TTY.println(" branchProbability@%d: %f", i, profilingInfo.getBranchTakenProbability(i)); - } - - double[] switchProbabilities = profilingInfo.getSwitchProbabilities(i); - if (switchProbabilities != null) { - TTY.print(" switchProbabilities@%d:", i); - for (int j = 0; j < switchProbabilities.length; j++) { - TTY.print(" %f", switchProbabilities[j]); - } - TTY.println(); - } - - if (profilingInfo.getExceptionSeen(i) != RiExceptionSeen.FALSE) { - TTY.println(" exceptionSeen@%d: %s", i, profilingInfo.getExceptionSeen(i).name()); - } - - RiTypeProfile typeProfile = profilingInfo.getTypeProfile(i); - if (typeProfile != null) { - RiResolvedType[] types = typeProfile.getTypes(); - double[] probabilities = typeProfile.getProbabilities(); - if (types != null && probabilities != null) { - assert types.length == probabilities.length : "length must match"; - TTY.print(" types@%d:", i); - for (int j = 0; j < types.length; j++) { - TTY.print(" %s (%f)", types[j], probabilities[j]); - } - TTY.println(" not recorded (%f)", typeProfile.getNotRecordedProbability()); - } - } - } - - boolean firstDeoptReason = true; - for (RiDeoptReason reason: RiDeoptReason.values()) { - int count = profilingInfo.getDeoptimizationCount(reason); - if (count > 0) { - if (firstDeoptReason) { - TTY.println("Deopt History"); - firstDeoptReason = false; - } - TTY.println(" %s: %d", reason.name(), count); - } - } - } - - @Override public Annotation[][] getParameterAnnotations() { if (isConstructor()) { Constructor javaConstructor = toJavaConstructor(); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java Thu May 03 11:05:46 2012 +0200 @@ -29,9 +29,6 @@ * Implementation of RiMethod for unresolved HotSpot methods. */ public final class HotSpotMethodUnresolved extends HotSpotMethod { - /** - * - */ private static final long serialVersionUID = 5610263481791970079L; private final RiSignature signature; protected RiType holder; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java Thu May 03 11:05:46 2012 +0200 @@ -30,9 +30,6 @@ public final class HotSpotProfilingInfo extends CompilerObject implements RiProfilingInfo { - /** - * - */ private static final long serialVersionUID = -8307682725047864875L; private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData"); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Thu May 03 11:05:46 2012 +0200 @@ -28,8 +28,6 @@ import java.util.*; import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.graal.compiler.target.*; import com.oracle.graal.cri.*; import com.oracle.graal.graph.*; @@ -37,7 +35,6 @@ import com.oracle.graal.hotspot.Compiler; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.target.amd64.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -495,10 +492,8 @@ @Override public CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph) { - final PhasePlan plan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, OptimisticOptimizations.ALL); + OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; + return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts); } @Override diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java Thu May 03 11:05:46 2012 +0200 @@ -35,9 +35,6 @@ */ public class HotSpotSignature extends CompilerObject implements RiSignature { - /** - * - */ private static final long serialVersionUID = -2890917956072366116L; private final List arguments = new ArrayList<>(); private final String returnType; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java Thu May 03 11:05:46 2012 +0200 @@ -30,9 +30,6 @@ * Common interface for all HotSpot RiType-implementations. */ public abstract class HotSpotType extends CompilerObject implements RiType { - /** - * - */ private static final long serialVersionUID = -4252886265301910771L; protected String name; @@ -44,4 +41,10 @@ public final String name() { return name; } + + /** + * Gets the object representing the C++ klassOop for this type. + * Such a value cannot be safely exposed to Java code. + */ + public abstract HotSpotKlassOop klassOop(); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java Thu May 03 11:05:46 2012 +0200 @@ -35,17 +35,15 @@ */ public final class HotSpotTypePrimitive extends HotSpotType implements RiResolvedType { - /** - * - */ private static final long serialVersionUID = -6208552348908071473L; private CiKind kind; - + private final HotSpotKlassOop klassOop; public HotSpotTypePrimitive(Compiler compiler, CiKind kind) { super(compiler); this.kind = kind; this.name = String.valueOf(Character.toUpperCase(kind.typeChar)); + this.klassOop = new HotSpotKlassOop(compiler, kind.toJavaClass()); } @Override @@ -178,4 +176,9 @@ public RiResolvedType resolve(RiResolvedType accessingClass) { return this; } + + @Override + public HotSpotKlassOop klassOop() { + return klassOop; + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java Thu May 03 11:05:46 2012 +0200 @@ -35,4 +35,5 @@ RiField createRiField(String name, RiType type, int offset, int flags); + HotSpotKlassOop klassOop(); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Thu May 03 11:05:46 2012 +0200 @@ -118,11 +118,9 @@ case JavaClass: return CiConstant.forObject(javaMirror); case ObjectHub: - return CiConstant.forObject(this); + return CiConstant.forObject(klassOop()); case StaticFields: return CiConstant.forObject(javaMirror); - case TypeInfo: - return CiConstant.forObject(this); default: return null; } @@ -220,7 +218,7 @@ long id = offset + ((long) flags << 32); - // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are equal. + // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical. if (fieldCache == null) { fieldCache = new HashMap<>(8); } else { @@ -265,4 +263,15 @@ public RiResolvedType resolve(RiResolvedType accessingClass) { return this; } + + // (dnsimon) this value may require identity semantics + private HotSpotKlassOop klassOopCache; + + @Override + public synchronized HotSpotKlassOop klassOop() { + if (klassOopCache == null) { + klassOopCache = new HotSpotKlassOop(compiler, javaMirror); + } + return klassOopCache; + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java Thu May 03 11:05:46 2012 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.Compiler; /** @@ -119,4 +120,9 @@ public RiResolvedType resolve(RiResolvedType accessingClass) { return (RiResolvedType) compiler.lookupType(name, (HotSpotTypeResolved) accessingClass, true); } + + @Override + public HotSpotKlassOop klassOop() { + throw GraalInternalError.shouldNotReachHere("HotSpotTypeUnresolved.klassOop"); + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Thu May 03 11:05:46 2012 +0200 @@ -25,9 +25,12 @@ import static com.oracle.graal.hotspot.ri.TemplateFlag.*; import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.io.*; import java.util.*; import java.util.concurrent.*; +import sun.misc.*; + import com.oracle.graal.compiler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; @@ -288,7 +291,7 @@ @Override protected XirTemplate create(CiXirAssembler asm, long flags, int size) { XirOperand result = asm.restart(target.wordKind); - XirOperand type = asm.createInputParameter("type", CiKind.Object); + XirOperand hub = asm.createInputParameter("hub", CiKind.Object); XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); XirOperand temp1o = asm.createRegister("temp1o", CiKind.Object, AMD64.rcx); @@ -299,7 +302,7 @@ XirLabel resume = asm.createInlineLabel("resume"); // check if the class is already initialized - asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false); + asm.pload(CiKind.Int, temp2i, hub, asm.i(config.klassStateOffset), false); asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); @@ -312,9 +315,9 @@ asm.bindInline(resume); - asm.pload(target.wordKind, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); + asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); asm.pstore(target.wordKind, result, temp1, false); - asm.mov(temp1o, type); // need a temporary register since Intel cannot store 64-bit constants to memory + asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false); if (size > 2 * target.wordSize) { @@ -327,7 +330,7 @@ // -- out of line ------------------------------------------------------- asm.bindOutOfLine(tlabFull); XirOperand arg = asm.createRegisterTemp("runtime call argument", CiKind.Object, AMD64.rdx); - asm.mov(arg, type); + asm.mov(arg, hub); useRegisters(asm, AMD64.rax); asm.callRuntime(config.newInstanceStub, result); asm.jmp(resume); @@ -460,56 +463,115 @@ } }; + enum CheckcastCounter { + hintsHit("hit a hint type"), + hintsMissed("missed the hint types"), + exact("tested type is (statically) final"), + noHints_class("profile information is not used (test type is a class)"), + noHints_iface("profile information is not used (test type is an interface)"), + noHints_unknown("test type is not a compile-time constant"), + isNull("object tested is null"), + exception("type test failed with a ClassCastException"); + + public final String desc; + + private CheckcastCounter(String desc) { + this.desc = desc; + } + + static final CheckcastCounter[] VALUES = values(); + } + + private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length]; + private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { + private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) { + int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class); + Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class)); + XirConstant index = asm.i(offset.ordinal()); + asm.pload(CiKind.Long, counter, counters, index, disp, scale, false); + asm.add(counter, counter, asm.i(1)); + asm.pstore(CiKind.Long, counters, index, counter, disp, scale, false); + } + @Override protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); + boolean exact = is(EXACT_HINTS, flags); + XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", CiKind.Object) : null; XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object); + final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", CiKind.Object); XirOperand objHub = asm.createTemp("objHub", CiKind.Object); + XirOperand counter = counters != null ? asm.createTemp("counter", CiKind.Long) : null; - XirLabel end = asm.createInlineLabel("end"); + XirLabel success = asm.createInlineLabel("success"); XirLabel slowPath = asm.createOutOfLineLabel("slow path"); if (is(NULL_CHECK, flags)) { // null can be cast to anything - asm.jeq(end, object, asm.o(null)); + if (counters != null) { + XirLabel isNotNull = asm.createInlineLabel("isNull"); + asm.jneq(isNotNull, object, asm.o(null)); + incCounter(asm, counter, counters, CheckcastCounter.isNull); + asm.jmp(success); + asm.bindInline(isNotNull); + } else { + asm.jeq(success, object, asm.o(null)); + } + } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); if (hintCount == 0) { - assert !is(EXACT_HINTS, flags); + assert !exact; + if (counters != null) { + incCounter(asm, counter, counters, is(NULL_TYPE, flags) ? CheckcastCounter.noHints_unknown : is(INTERFACE_TYPE, flags) ? CheckcastCounter.noHints_iface : CheckcastCounter.noHints_class); + } + checkSubtype(asm, objHub, objHub, hub); asm.jeq(slowPath, objHub, asm.o(null)); - asm.bindInline(end); + asm.bindInline(success); // -- out of line ------------------------------------------------------- asm.bindOutOfLine(slowPath); } else { + XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess"); + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); // if we get an exact match: succeed immediately - XirOperand hintHub = asm.createTemp("hintHub", CiKind.Object); for (int i = 0; i < hintCount; i++) { - XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object); - asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false); + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); if (i < hintCount - 1) { - asm.jeq(end, objHub, hintHub); + asm.jeq(hintsSuccess, objHub, scratchObject); } else { - asm.jneq(slowPath, objHub, hintHub); + asm.jneq(slowPath, objHub, scratchObject); } } - asm.bindInline(end); + + if (counters != null) { + asm.bindInline(hintsSuccess); + incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit); + } + + asm.bindInline(success); // -- out of line ------------------------------------------------------- asm.bindOutOfLine(slowPath); - if (!is(EXACT_HINTS, flags)) { + if (!exact) { + if (counters != null) { + incCounter(asm, counter, counters, CheckcastCounter.hintsMissed); + } checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); + asm.jneq(success, objHub, asm.o(null)); } } - RiDeoptReason deoptReason = is(EXACT_HINTS, flags) ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException; + if (counters != null) { + incCounter(asm, counter, counters, CheckcastCounter.exception); + } + RiDeoptReason deoptReason = exact ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException; XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); @@ -545,21 +607,21 @@ asm.jmp(trueSucc); } else { XirLabel slowPath = null; - XirOperand hintHub = asm.createTemp("hintHub", CiKind.Object); + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); // if we get an exact match: succeed immediately for (int i = 0; i < hintCount; i++) { - XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object); - asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false); + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); if (i < hintCount - 1) { - asm.jeq(trueSucc, objHub, hintHub); + asm.jeq(trueSucc, objHub, scratchObject); } else { if (is(EXACT_HINTS, flags)) { - asm.jneq(falseSucc, objHub, hintHub); + asm.jneq(falseSucc, objHub, scratchObject); asm.jmp(trueSucc); } else { slowPath = asm.createOutOfLineLabel("slow path"); - asm.jneq(slowPath, objHub, hintHub); + asm.jneq(slowPath, objHub, scratchObject); asm.jmp(trueSucc); } } @@ -610,20 +672,20 @@ asm.bindInline(end); } else { XirLabel slowPath = null; - XirOperand hintHub = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); // if we get an exact match: succeed immediately for (int i = 0; i < hintCount; i++) { - XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object); - asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false); + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); if (i < hintCount - 1) { - asm.jeq(end, objHub, hintHub); + asm.jeq(end, objHub, scratchObject); } else { if (is(EXACT_HINTS, flags)) { - asm.jeq(end, objHub, hintHub); + asm.jeq(end, objHub, scratchObject); } else { slowPath = asm.createOutOfLineLabel("slow path"); - asm.jeq(end, objHub, hintHub); + asm.jeq(end, objHub, scratchObject); asm.jmp(slowPath); } } @@ -645,166 +707,6 @@ } }; - private KindTemplates arrayCopyTemplates = new KindTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - asm.restart(CiKind.Void); - XirParameter src = asm.createInputParameter("src", CiKind.Object); - XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true); - XirParameter dest = asm.createInputParameter("dest", CiKind.Object); - XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true); - XirParameter length = asm.createInputParameter("length", CiKind.Int, true); - - XirOperand tempSrc = asm.createTemp("tempSrc", target.wordKind); - XirOperand tempDest = asm.createTemp("tempDest", target.wordKind); - XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax); - - XirOperand compHub = null; - XirOperand valueHub = null; - XirOperand temp = null; - XirLabel store = null; - XirLabel slowStoreCheck = null; - - if (is(STORE_CHECK, flags) && kind == CiKind.Object) { - valueHub = asm.createRegisterTemp("valueHub", target.wordKind, AMD64.rdi); - compHub = asm.createRegisterTemp("compHub", target.wordKind, AMD64.rsi); - temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); - } - - // Calculate the factor for the repeat move instruction. - int elementSize = target.sizeInBytes(kind); - int factor; - boolean wordSize; - if (elementSize >= target.wordSize) { - assert elementSize % target.wordSize == 0; - wordSize = true; - factor = elementSize / target.wordSize; - } else { - factor = elementSize; - wordSize = false; - } - - // Adjust the length if the factor is not 1. - if (factor != 1) { - asm.shl(lengthOperand, length, asm.i(CiUtil.log2(factor))); - } else { - asm.mov(lengthOperand, length); - } - - // Set the start and the end pointer. - asm.lea(tempSrc, src, srcPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - - XirLabel reverse = null; - XirLabel normal = null; - - if (is(STORE_CHECK, flags)) { - reverse = asm.createInlineLabel("reverse"); - asm.jneq(reverse, src, dest); - } - - if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { - normal = asm.createInlineLabel("normal"); - asm.jneq(normal, src, dest); - } - - if (!is(INPUTS_DIFFERENT, flags)) { - if (reverse == null) { - reverse = asm.createInlineLabel("reverse"); - } - asm.jlt(reverse, srcPos, destPos); - } - - if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { - asm.bindInline(normal); - } - - // Everything set up => repeat mov. - if (wordSize) { - asm.repmov(tempSrc, tempDest, lengthOperand); - } else { - asm.repmovb(tempSrc, tempDest, lengthOperand); - } - - if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) { - - XirLabel end = asm.createInlineLabel("end"); - asm.jmp(end); - - // Implement reverse copy, because srcPos < destPos and src == dest. - asm.bindInline(reverse); - - if (is(STORE_CHECK, flags)) { - asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false); - asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); - } - - CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte; - XirOperand tempValue = asm.createTemp("tempValue", copyKind); - XirLabel start = asm.createInlineLabel("start"); - asm.bindInline(start); - asm.sub(lengthOperand, lengthOperand, asm.i(1)); - asm.jlt(end, lengthOperand, asm.i(0)); - - Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1; - asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false); - - if (is(STORE_CHECK, flags)) { - slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); - store = asm.createInlineLabel("store"); - asm.jeq(store, tempValue, asm.o(null)); // first check if value is null - asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false); - asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub - asm.bindInline(store); - } - - asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false); - - asm.jmp(start); - asm.bindInline(end); - } - - if (kind == CiKind.Object) { - // Do write barriers - asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.shr(tempDest, tempDest, asm.i(config.cardtableShift)); - asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDest, asm.b(false), false); - - XirOperand tempDestEnd = tempSrc; // Reuse src temp - asm.lea(tempDestEnd, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.add(tempDestEnd, tempDestEnd, length); - asm.shr(tempDestEnd, tempDestEnd, asm.i(config.cardtableShift)); - - // Jump to out-of-line write barrier loop if the array is big. - XirLabel writeBarrierLoop = asm.createOutOfLineLabel("writeBarrierLoop"); - asm.jneq(writeBarrierLoop, tempDest, tempSrc); - XirLabel back = asm.createInlineLabel("back"); - asm.bindInline(back); - - asm.bindOutOfLine(writeBarrierLoop); - asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDestEnd, asm.b(false), false); - asm.sub(tempDestEnd, tempDestEnd, asm.i(1)); - asm.jneq(writeBarrierLoop, tempDestEnd, tempDest); - asm.jmp(back); - } - - if (is(STORE_CHECK, flags)) { - assert kind == CiKind.Object; - useRegisters(asm, AMD64.rax); - asm.bindOutOfLine(slowStoreCheck); - checkSubtype(asm, temp, valueHub, compHub); - asm.jneq(store, temp, wordConst(asm, 0)); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ClassCastException))); - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.jmp(store); - } - - return asm.finishTemplate("arraycopy<" + kind + ">"); - } - }; - private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { @Override protected XirTemplate create(CiXirAssembler asm, long flags) { @@ -871,43 +773,57 @@ @Override public XirSnippet genNewInstance(XirSite site, RiType type) { - int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); - return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type)); + HotSpotTypeResolved resolvedType = (HotSpotTypeResolved) type; + int instanceSize = resolvedType.instanceSize(); + return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop())); } @Override public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { if (elementKind == CiKind.Object) { assert arrayType instanceof RiResolvedType; - return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); + return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotType) arrayType).klassOop())); } else { assert arrayType == null; RiType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind); - return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(primitiveArrayType)); + return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotType) primitiveArrayType).klassOop())); } } @Override public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); - params[lengths.length] = XirArgument.forObject(type); + params[lengths.length] = XirArgument.forObject(((HotSpotType) type).klassOop()); return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); } @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) { + public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact) { + final boolean useCounters = GraalOptions.CheckcastCounters; if (hints == null || hints.length == 0) { - return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + if (useCounters) { + if (type == null) { + return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); + } else if (type.isInterface()) { + return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); + } else { + return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub); + } + } else { + return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + } } else { - XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)]; + XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hints.length + (hintsExact ? 1 : 2)]; int i = 0; + if (useCounters) { + params[i++] = XirArgument.forObject(checkcastCounters); + } params[i++] = receiver; if (!hintsExact) { params[i++] = hub; } for (RiResolvedType hint : hints) { - Object hintMirror = hint.toJava(); - params[i++] = XirArgument.forObject(hintMirror); + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); } XirTemplate template = hintsExact ? checkCastTemplates.get(site, hints.length, EXACT_HINTS) : checkCastTemplates.get(site, hints.length); return new XirSnippet(template, params); @@ -926,8 +842,7 @@ params[i++] = hub; } for (RiResolvedType hint : hints) { - Object hintMirror = hint.toJava(); - params[i++] = XirArgument.forObject(hintMirror); + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); } XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hints.length, EXACT_HINTS) : instanceOfTemplates.get(site, hints.length); return new XirSnippet(template, params); @@ -948,8 +863,7 @@ params[i++] = trueValue; params[i++] = falseValue; for (RiResolvedType hint : hints) { - Object hintMirror = hint.toJava(); - params[i++] = XirArgument.forObject(hintMirror); + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); } XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hints.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hints.length); return new XirSnippet(template, params); @@ -957,23 +871,6 @@ } @Override - public XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent) { - if (elementType == null) { - return null; - } - assert !inputsDifferent || !inputsSame; - XirTemplate template = null; - if (inputsDifferent) { - template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_DIFFERENT); - } else if (inputsSame) { - template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_SAME); - } else { - template = arrayCopyTemplates.get(site, elementType.kind(true)); - } - return new XirSnippet(template, src, srcPos, dest, destPos, length); - } - - @Override public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, RiType type) { assert type instanceof RiResolvedType; return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub); @@ -1096,4 +993,43 @@ return getInternal(getBits(kind.ordinal(), site, flags)); } } + + private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) { + double percent = ((double) (count * 100)) / total; + out.println(String.format("%16s: %5.2f%%%10d // %s", name, percent, count, name.desc)); + } + + public static void printCheckcastCounters(PrintStream out) { + class Count implements Comparable { + long c; + CheckcastCounter name; + Count(long c, CheckcastCounter name) { + this.c = c; + this.name = name; + } + public int compareTo(Count o) { + return (int) (o.c - c); + } + } + + long total = 0; + Count[] counters = new Count[checkcastCounters.length]; + for (int i = 0; i < counters.length; i++) { + counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]); + total += checkcastCounters[i]; + } + Arrays.sort(counters); + + out.println(); + out.println("** Checkcast counters **"); + for (Count c : counters) { + printCounter(out, c.name, c.c, total); + } + } + + public static void printCounters(PrintStream out) { + if (GraalOptions.CheckcastCounters) { + printCheckcastCounters(out); + } + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java Thu May 03 11:05:46 2012 +0200 @@ -23,7 +23,19 @@ package com.oracle.graal.hotspot.ri; enum TemplateFlag { - NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS; + NULL_CHECK, + READ_BARRIER, + WRITE_BARRIER, + STORE_CHECK, + BOUNDS_CHECK, + GIVEN_LENGTH, + INPUTS_DIFFERENT, + INPUTS_SAME, + STATIC_METHOD, + SYNCHRONIZED, + INTERFACE_TYPE, + NULL_TYPE, + EXACT_HINTS; private static final long FIRST_FLAG = 0x0000000100000000L; public static final long FLAGS_MASK = 0x0000FFFF00000000L; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/server/ReplacingStreams.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/server/ReplacingStreams.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/server/ReplacingStreams.java Thu May 03 11:05:46 2012 +0200 @@ -74,9 +74,6 @@ public static class Placeholder implements Serializable { - /** - * - */ private static final long serialVersionUID = 6071894297788156945L; public final int id; @@ -92,9 +89,6 @@ public static class NewRemoteCallPlaceholder implements Serializable { - /** - * - */ private static final long serialVersionUID = 3084101671389500206L; public final Class[] interfaces; @@ -104,10 +98,6 @@ } public static class NewDummyPlaceholder implements Serializable { - - /** - * - */ private static final long serialVersionUID = 2692666726573532288L; } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Thu May 03 11:05:46 2012 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.compiler.target.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.counters.*; import com.oracle.graal.hotspot.ri.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; @@ -75,6 +76,12 @@ emitStore(pcAddress, CiConstant.LONG_0, false); setResult(x, exception); } + + @Override + protected void emitPrologue() { + super.emitPrologue(); + MethodEntryCounters.emitCounter(this, method); + } }; } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu May 03 11:05:46 2012 +0200 @@ -46,6 +46,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.ri.RiType.Representation; +import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType; import com.oracle.max.criutils.*; /** @@ -146,7 +147,8 @@ } if (GraalOptions.PrintProfilingInformation) { - method.dumpProfile(); + TTY.println("Profiling info for " + method); + TTY.println(CiUtil.indent(CiUtil.profileAsString(method), " ")); } // compute the block map, setup exception handlers and get the entrypoint(s) @@ -591,7 +593,7 @@ private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0]; private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) { - if (!optimisticOpts.useUseTypeCheckHints() || Util.isFinalClass(type)) { + if (!optimisticOpts.useTypeCheckHints() || Util.isFinalClass(type)) { return new RiResolvedType[] {type}; } else { RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype(); @@ -601,17 +603,24 @@ RiTypeProfile typeProfile = profilingInfo.getTypeProfile(bci()); if (typeProfile != null) { double notRecordedTypes = typeProfile.getNotRecordedProbability(); - RiResolvedType[] types = typeProfile.getTypes(); - - if (notRecordedTypes == 0 && types != null && types.length > 0 && types.length <= maxHints) { - RiResolvedType[] hints = new RiResolvedType[types.length]; + ProfiledType[] ptypes = typeProfile.getTypes(); + if (notRecordedTypes < (1D - GraalOptions.CheckcastMinHintHitProbability) && ptypes != null && ptypes.length > 0) { + RiResolvedType[] hints = new RiResolvedType[ptypes.length]; int hintCount = 0; - for (RiResolvedType hint : types) { + double totalHintProbability = 0.0d; + for (ProfiledType ptype : ptypes) { + RiResolvedType hint = ptype.type; if (hint.isSubtypeOf(type)) { hints[hintCount++] = hint; + totalHintProbability += ptype.probability; } } - return Arrays.copyOf(hints, Math.min(maxHints, hintCount)); + if (totalHintProbability >= GraalOptions.CheckcastMinHintHitProbability) { + if (hints.length == hintCount && hintCount <= maxHints) { + return hints; + } + return Arrays.copyOf(hints, Math.min(maxHints, hintCount)); + } } } return EMPTY_TYPE_ARRAY; @@ -629,7 +638,7 @@ AnchorNode anchor = currentGraph.add(new AnchorNode()); append(anchor); CheckCastNode checkCast; - RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, 2); + RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, GraalOptions.CheckcastMaxHints); checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object, hints, Util.isFinalClass((RiResolvedType) type))); append(currentGraph.add(new ValueAnchorNode(checkCast))); frameState.apush(checkCast); @@ -648,7 +657,7 @@ RiResolvedType resolvedType = (RiResolvedType) type; ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub)); - RiResolvedType[] hints = getTypeCheckHints(resolvedType, 1); + RiResolvedType[] hints = getTypeCheckHints(resolvedType, GraalOptions.InstanceOfMaxHints); InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hints, Util.isFinalClass(resolvedType), false); frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Thu May 03 11:05:46 2012 +0200 @@ -30,17 +30,17 @@ public class PiNode extends FloatingNode implements LIRLowerable { @Input private ValueNode object; - @Input private BeginNode anchor; + @Input(notDataflow = true) private final FixedNode anchor; public ValueNode object() { return object; } - public BeginNode anchor() { + public FixedNode anchor() { return anchor; } - public PiNode(ValueNode object, BeginNode anchor, Stamp stamp) { + public PiNode(ValueNode object, FixedNode anchor, Stamp stamp) { super(stamp); this.object = object; this.anchor = anchor; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu May 03 11:05:46 2012 +0200 @@ -73,6 +73,27 @@ this(null, method); } + @Override + public String toString() { + StringBuilder buf = new StringBuilder(getClass().getSimpleName() + ":" + graphId); + String sep = "{"; + if (name != null) { + buf.append(sep); + buf.append(name); + sep = ", "; + } + if (method != null) { + buf.append(sep); + buf.append(method); + sep = ", "; + } + + if (!sep.equals("{")) { + buf.append("}"); + } + return buf.toString(); + } + public BeginNode start() { return start; } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Thu May 03 11:05:46 2012 +0200 @@ -46,6 +46,6 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.emitCallToRuntime(CiRuntimeCall.UnwindException, false, gen.operand(exception())); + gen.emitCall(CiRuntimeCall.UnwindException, false, gen.operand(exception())); } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NullCheckNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NullCheckNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NullCheckNode.java Thu May 03 11:05:46 2012 +0200 @@ -28,6 +28,10 @@ import com.oracle.graal.nodes.spi.types.*; import com.oracle.graal.nodes.type.*; +/** + * A NullCheckNode will be true if the supplied value is non-null, and false if it is null. + * This behavior can be inverted by setting {@link #expectedNull} to true. + */ public final class NullCheckNode extends BooleanNode implements Canonicalizable, LIRLowerable, ConditionalTypeFeedbackProvider, TypeCanonicalizable { @Input private ValueNode object; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Thu May 03 11:05:46 2012 +0200 @@ -40,16 +40,11 @@ public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable { @Input(notDataflow = true) protected final FixedNode anchor; - protected final boolean emitCode; public FixedNode anchor() { return anchor; } - public boolean emitCode() { - return emitCode; - } - /** * Creates a new CheckCast instruction. * @@ -61,18 +56,9 @@ this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false); } - public CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean emitCode) { - this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false, emitCode); - } - public CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact) { - this(anchor, targetClassInstruction, targetClass, object, hints, hintsExact, true); - } - - private CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, boolean emitCode) { super(targetClassInstruction, targetClass, object, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); this.anchor = anchor; - this.emitCode = emitCode; } @Override @@ -82,12 +68,16 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { + assert object() != null : this; + RiResolvedType objectDeclaredType = object().declaredType(); RiResolvedType targetClass = targetClass(); if (objectDeclaredType != null && targetClass != null && objectDeclaredType.isSubtypeOf(targetClass)) { + // we don't have to check for null types here because they will also pass the checkcast. freeAnchor(); return object(); } + CiConstant constant = object().asConstant(); if (constant != null) { assert constant.kind == CiKind.Object; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Thu May 03 11:05:46 2012 +0200 @@ -22,14 +22,13 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.types.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; /** * The {@code InstanceOfNode} represents an instanceof test. @@ -66,17 +65,44 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { assert object() != null : this; + RiResolvedType exact = object().exactType(); if (exact != null) { - boolean result = exact.isSubtypeOf(targetClass()); - if (result != negated) { - // The instanceof check reduces to a null check. - return graph().unique(new NullCheckNode(object(), false)); + boolean subType = exact.isSubtypeOf(targetClass()); + + if (subType) { + if (object().stamp().nonNull()) { + // the instanceOf matches, so return true (or false, for the negated case) + return ConstantNode.forBoolean(!negated, graph()); + } else { + // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness. + return graph().unique(new NullCheckNode(object(), negated)); + } } else { - // The instanceof check can never succeed. - return ConstantNode.forBoolean(false, graph()); + // since this type check failed for an exact type we know that it can never succeed at run time. + // we also don't care about null values, since they will also make the check fail. + // so return false (or true, for the negated case) + return ConstantNode.forBoolean(negated, graph()); + } + } else { + RiResolvedType declared = object().declaredType(); + if (declared != null) { + boolean subType = declared.isSubtypeOf(targetClass()); + + if (subType) { + if (object().stamp().nonNull()) { + // the instanceOf matches, so return true (or false, for the negated case) + return ConstantNode.forBoolean(!negated, graph()); + } else { + // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness. + return graph().unique(new NullCheckNode(object(), negated)); + } + } else { + // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time... + } } } + CiConstant constant = object().asConstant(); if (constant != null) { assert constant.kind == CiKind.Object; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu May 03 11:05:46 2012 +0200 @@ -46,7 +46,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.emitCallToRuntime(CiRuntimeCall.RegisterFinalizer, true, gen.operand(object())); + gen.emitCall(CiRuntimeCall.RegisterFinalizer, true, gen.operand(object())); } @Override diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Thu May 03 11:05:46 2012 +0200 @@ -81,7 +81,10 @@ public abstract void emitMembar(int barriers); public abstract void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo); public abstract void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId); - public abstract CiValue emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args); + public abstract CiValue emitCall(Object target, CiKind result, CiKind[] arguments, boolean canTrap, CiValue... args); + public final CiValue emitCall(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) { + return emitCall(runtimeCall, runtimeCall.resultKind, runtimeCall.arguments, canTrap, args); + } public abstract void emitIf(IfNode i); public abstract void emitConditional(ConditionalNode i); diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Thu May 03 11:05:46 2012 +0200 @@ -232,7 +232,7 @@ public static Stamp declared(final RiResolvedType type) { assert type != null; assert type.kind(false) == CiKind.Object; - return new BasicValueStamp(CiKind.Object, false, type, null); + return new BasicValueStamp(CiKind.Object, false, type, type.exactType()); } public static Stamp declaredNonNull(final RiResolvedType type) { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java Thu May 03 11:05:46 2012 +0200 @@ -27,13 +27,16 @@ import com.oracle.graal.nodes.extended.*; /** - * Snippets for {@link NodeClass} methods. + * Snippets for improving the performance of some critical methods in {@link NodeClass} methods. + * These snippets improve the performance by forcing the relevant methods to be inlined + * (intrinsification being a special form of inlining) and removing a checked cast. + * The latter cannot be done directly in Java code as {@link UnsafeCastNode} + * is not available to the project containing {@link NodeClass}. */ @SuppressWarnings("unused") @ClassSubstitution(NodeClass.class) public class NodeClassSnippets implements SnippetsInterface { - private static Node getNode(Node node, long offset) { return UnsafeCastNode.cast(UnsafeLoadNode.load(node, 0, offset, CiKind.Object), Node.class); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Thu May 03 11:05:46 2012 +0200 @@ -24,8 +24,8 @@ import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; -import com.oracle.max.cri.ci.*; -import com.oracle.graal.compiler.target.amd64.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg; @@ -34,8 +34,9 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.snippets.target.amd64.*; +import com.oracle.max.cri.ci.*; -public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, AMD64LIRLowerable { +public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, LIRGenLowerable { @Input private ValueNode x; private final Operation operation; @@ -60,7 +61,7 @@ } @Override - public void generateAmd64(AMD64LIRGenerator gen) { + public void generate(LIRGenerator gen) { Variable input = gen.load(gen.operand(x())); Variable result = gen.newVariable(kind()); switch (operation()) { diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfCanonicalizerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfCanonicalizerTest.java Thu May 03 11:05:46 2012 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.tests; + +import org.junit.*; + +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; + +public class InstanceOfCanonicalizerTest extends GraphTest { + + /** + * The problem tested here is the following: When canonicalizing a negated instanceof for which the exact type + * suggests that the instanceof is true, we still need to check if the value is null. (because this would make the + * instanceof false, and thus the negated instanceof true). + * + * This test case is constructed by replacing an instanceof with its negated counterpart, since negated instanceof + * operations will only be created in complicated cases. + */ + @Test + public void test1() { + StructuredGraph graph = parse("testSnippet1"); + Debug.dump(graph, "Graph"); + for (Node node : graph.getNodes().snapshot()) { + if (node instanceof InstanceOfNode) { + graph.replaceFloating((InstanceOfNode) node, ((InstanceOfNode) node).negate()); + } + } + new CanonicalizerPhase(null, runtime(), null).apply(graph); + Debug.dump(graph, "Graph"); + for (Node node : graph.getNodes()) { + if (node instanceof InstanceOfNode) { + Assert.fail("InstanceOfNode should have been canonicalized"); + } else if (node instanceof ReturnNode) { + ReturnNode ret = (ReturnNode) node; + Assert.assertTrue("return value should be a MaterializeNode " + ret.result(), ret.result() instanceof MaterializeNode); + MaterializeNode materialize = (MaterializeNode) ret.result(); + Assert.assertTrue("return value should depend on nullness of parameter " + materialize.condition(), materialize.condition() instanceof NullCheckNode); + } + + } + } + + @SuppressWarnings("all") + public static boolean testSnippet1(String s) { + return s instanceof String; + } +} diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiDebugInfo.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiDebugInfo.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiDebugInfo.java Thu May 03 11:05:46 2012 +0200 @@ -30,9 +30,6 @@ */ public class CiDebugInfo implements Serializable { - /** - * - */ private static final long serialVersionUID = -6047206624915812516L; /** diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiRegister.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiRegister.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiRegister.java Thu May 03 11:05:46 2012 +0200 @@ -30,9 +30,6 @@ */ public final class CiRegister implements Comparable, Serializable { - /** - * - */ private static final long serialVersionUID = -7213269157816016300L; /** diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java Thu May 03 11:05:46 2012 +0200 @@ -34,18 +34,12 @@ */ public class CiTargetMethod implements Serializable { - /** - * - */ private static final long serialVersionUID = -1319947729753702434L; /** * Represents a code position with associated additional information. */ public abstract static class Site implements Serializable { - /** - * - */ private static final long serialVersionUID = -8214214947651979102L; /** * The position (or offset) of this site with respect to the start of the target method. @@ -61,9 +55,6 @@ * Represents a safepoint with associated debug info. */ public static class Safepoint extends Site implements Comparable { - /** - * - */ private static final long serialVersionUID = 2479806696381720162L; public final CiDebugInfo debugInfo; @@ -96,9 +87,6 @@ * Represents a call in the code. */ public static final class Call extends Safepoint { - /** - * - */ private static final long serialVersionUID = 1440741241631046954L; /** @@ -145,9 +133,6 @@ * Represents a reference to data from the code. The associated data can be any constant. */ public static final class DataPatch extends Site { - /** - * - */ private static final long serialVersionUID = 5771730331604867476L; public final CiConstant constant; public final int alignment; @@ -169,9 +154,6 @@ * This is optional information that can be used to enhance a disassembly of the code. */ public abstract static class CodeAnnotation implements Serializable { - /** - * - */ private static final long serialVersionUID = -7903959680749520748L; public final int position; @@ -204,9 +186,6 @@ * Labels some inline data in the code. */ public static final class InlineData extends CodeAnnotation { - /** - * - */ private static final long serialVersionUID = 305997507263827108L; public final int size; public InlineData(int position, int size) { @@ -228,9 +207,6 @@ * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high} inclusive. */ public static final class JumpTable extends CodeAnnotation { - /** - * - */ private static final long serialVersionUID = 2222194398353801831L; /** @@ -267,9 +243,6 @@ * based on a key value from a sparse value set (e.g. the {@code lookupswitch} JVM instruction). */ public static final class LookupTable extends CodeAnnotation { - /** - * - */ private static final long serialVersionUID = 8367952567559116160L; /** @@ -305,9 +278,6 @@ * well as the caught exception type. */ public static final class ExceptionHandler extends Site { - /** - * - */ private static final long serialVersionUID = 4897339464722665281L; public final int handlerPos; @@ -323,9 +293,6 @@ } public static final class Mark extends Site { - /** - * - */ private static final long serialVersionUID = 3612943150662354844L; public final Object id; public final Mark[] references; diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java Thu May 03 11:05:46 2012 +0200 @@ -28,6 +28,7 @@ import java.util.*; import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType; /** * Miscellaneous collection of utility methods used in the {@code CRI} project. @@ -736,4 +737,64 @@ } return result; } + + /** + * Formats the profiling information associated with a given method to a string. + */ + public static String profileAsString(RiResolvedMethod method) { + StringBuilder buf = new StringBuilder(100); + buf.append(String.format("canBeStaticallyBound: %b%n", method.canBeStaticallyBound())). + append(String.format("invocationCount: %d%n", method.invocationCount())); + RiProfilingInfo profilingInfo = method.profilingInfo(); + if (profilingInfo != null) { + for (int i = 0; i < method.codeSize(); i++) { + if (profilingInfo.getExecutionCount(i) != -1) { + buf.append(String.format("executionCount@%d: %d%n", i, profilingInfo.getExecutionCount(i))); + } + + if (profilingInfo.getBranchTakenProbability(i) != -1) { + buf.append(String.format("branchProbability@%d: %.3f%n", i, profilingInfo.getBranchTakenProbability(i))); + } + + double[] switchProbabilities = profilingInfo.getSwitchProbabilities(i); + if (switchProbabilities != null) { + buf.append(String.format("switchProbabilities@%d:", i)); + for (int j = 0; j < switchProbabilities.length; j++) { + buf.append(String.format(" %.3f", switchProbabilities[j])); + } + buf.append(NEW_LINE); + } + + if (profilingInfo.getExceptionSeen(i) != RiExceptionSeen.FALSE) { + buf.append(String.format("exceptionSeen@%d: %s%n", i, profilingInfo.getExceptionSeen(i).name())); + } + + RiTypeProfile typeProfile = profilingInfo.getTypeProfile(i); + if (typeProfile != null) { + ProfiledType[] ptypes = typeProfile.getTypes(); + if (ptypes != null) { + buf.append(String.format("types@%d:%n", i)); + for (int j = 0; j < ptypes.length; j++) { + ProfiledType ptype = ptypes[j]; + buf.append(String.format(" %.3f %s%n", ptype.probability, ptype.type)); + } + buf.append(String.format(" %.3f %n", typeProfile.getNotRecordedProbability())); + } + } + } + + boolean firstDeoptReason = true; + for (RiDeoptReason reason: RiDeoptReason.values()) { + int count = profilingInfo.getDeoptimizationCount(reason); + if (count > 0) { + if (firstDeoptReason) { + buf.append("deoptimization history").append(NEW_LINE); + firstDeoptReason = false; + } + buf.append(String.format(" %s: %d%n", reason.name(), count)); + } + } + } + return buf.toString(); + } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java Thu May 03 11:05:46 2012 +0200 @@ -224,9 +224,4 @@ * @return {@code true} if this method can be inlined */ boolean canBeInlined(); - - /** - * Dumps the recorded profiling information to TTY. - */ - void dumpProfile(); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java Thu May 03 11:05:46 2012 +0200 @@ -50,13 +50,7 @@ * The runtime representation of the "hub" of this type--that is, the closest part of the type * representation which is typically stored in the object header. */ - ObjectHub, - - /** - * The runtime representation of the type information for an object, which is typically used - * for subtype tests. - */ - TypeInfo + ObjectHub } /** diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiTypeProfile.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiTypeProfile.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiTypeProfile.java Thu May 03 11:05:46 2012 +0200 @@ -30,27 +30,52 @@ * decisions like speculative inlining, etc. */ public final class RiTypeProfile implements Serializable { - /** - * - */ + private static final long serialVersionUID = -6877016333706838441L; - private final RiResolvedType[] types; - private final double notRecordedProbability; - private final double[] probabilities; + /** + * A profiled type that has a probability. Profiled types are naturally sorted in + * descending order of their probabilities. + */ + public static class ProfiledType implements Comparable { + public final RiResolvedType type; + public final double probability; - public RiTypeProfile(RiResolvedType[] types, double notRecordedProbability, double[] probabilites) { - this.types = types; - this.notRecordedProbability = notRecordedProbability; - this.probabilities = probabilites; + public ProfiledType(RiResolvedType type, double probability) { + this.type = type; + this.probability = probability; + } + + @Override + public int compareTo(ProfiledType o) { + if (probability > o.probability) { + return -1; + } else if (probability < o.probability) { + return 1; + } + return 0; + } } + private final double notRecordedProbability; + private final ProfiledType[] ptypes; + /** - * The estimated probabilities of the different receivers. This array needs to have the same length as the array returned by - * {@link RiTypeProfile#types}. + * Determines if an array of profiled types are sorted in descending order of their probabilities. */ - public double[] getProbabilities() { - return probabilities; + public static boolean isSorted(ProfiledType[] ptypes) { + for (int i = 1; i < ptypes.length; i++) { + if (ptypes[i - 1].probability < ptypes[i].probability) { + return false; + } + } + return true; + } + + public RiTypeProfile(ProfiledType[] ptypes, double notRecordedProbability) { + this.ptypes = ptypes; + this.notRecordedProbability = notRecordedProbability; + assert isSorted(ptypes); } /** @@ -62,10 +87,9 @@ } /** - * A list of receivers for which the runtime has recorded probability information. This array needs to have the same - * length as {@link RiTypeProfile#probabilities}. + * A list of types for which the runtime has recorded probability information. */ - public RiResolvedType[] getTypes() { - return types; + public ProfiledType[] getTypes() { + return ptypes; } } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java Thu May 03 11:05:46 2012 +0200 @@ -871,7 +871,7 @@ return createConstant(CiConstant.forInt(v)); } - public XirConstant l(int v) { + public XirConstant l(long v) { return createConstant(CiConstant.forLong(v)); } diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Thu May 03 11:05:46 2012 +0200 @@ -49,14 +49,12 @@ XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type); - XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact); + XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact); XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact); XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact); - XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent); - /** * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of * an object is identical to a given hub constant. In pseudo code: diff -r 077ec9468516 -r de571c017f61 graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java --- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java Fri Apr 27 13:13:06 2012 +0200 +++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java Thu May 03 11:05:46 2012 +0200 @@ -89,12 +89,10 @@ } } - public static final String MAX_TTY_LOG_FILE_PROPERTY = "max.tty.file"; - public static PrintStream cachedOut; - public static void initialize() { - cachedOut = System.out; + public static void initialize(PrintStream ps) { + cachedOut = ps; } private static LogStream createLog() { @@ -102,16 +100,7 @@ // In case initialize() was not called. cachedOut = System.out; } - PrintStream newOut = cachedOut; - String value = System.getProperty(MAX_TTY_LOG_FILE_PROPERTY); - if (value != null) { - try { - newOut = new PrintStream(new FileOutputStream(value)); - } catch (FileNotFoundException e) { - System.err.println("Could not open log file " + value + ": " + e); - } - } - return new LogStream(newOut); + return new LogStream(cachedOut); } private static final ThreadLocal out = new ThreadLocal() { diff -r 077ec9468516 -r de571c017f61 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu May 03 11:05:46 2012 +0200 @@ -189,6 +189,7 @@ \ /* Support for Graal */ \ template(HotSpotTypeResolved_klass, com_oracle_graal_hotspot_HotSpotTypeResolved, Opt) \ + template(HotSpotKlassOop_klass, com_oracle_graal_hotspot_HotSpotKlassOop, Opt) \ template(HotSpotType_klass, com_oracle_graal_hotspot_HotSpotType, Opt) \ template(HotSpotField_klass, com_oracle_graal_hotspot_HotSpotField, Opt) \ template(HotSpotCompiledMethod_klass, com_oracle_graal_hotspot_HotSpotCompiledMethod, Opt) \ diff -r 077ec9468516 -r de571c017f61 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu May 03 11:05:46 2012 +0200 @@ -279,6 +279,7 @@ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ template(com_oracle_graal_hotspot_HotSpotTypeResolved, "com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl") \ template(com_oracle_graal_hotspot_HotSpotType, "com/oracle/graal/hotspot/ri/HotSpotType") \ + template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/ri/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotExceptionHandler, "com/oracle/graal/hotspot/ri/HotSpotExceptionHandler") \ template(com_oracle_graal_hotspot_HotSpotProxy, "com/oracle/graal/hotspot/HotSpotProxy") \ template(com_oracle_graal_hotspot_Compiler, "com/oracle/graal/hotspot/Compiler") \ diff -r 077ec9468516 -r de571c017f61 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu May 03 11:05:46 2012 +0200 @@ -743,8 +743,7 @@ case 's': case 'c': case 'i': - fatal("int-sized values not expected in DataPatch") - ; + fatal("int-sized values not expected in DataPatch"); break; case 'f': case 'j': @@ -773,9 +772,9 @@ address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); Handle obj = CiConstant::object(constant); - if (obj->is_a(HotSpotTypeResolved::klass())) { + if (obj->is_a(HotSpotKlassOop::klass())) { assert(!obj.is_null(), ""); - *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj))); + *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotKlassOop::javaMirror(obj))); _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); TRACE_graal_3("relocating (HotSpotType) at %016x/%016x", instruction, operand); } else { diff -r 077ec9468516 -r de571c017f61 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu May 03 11:05:46 2012 +0200 @@ -1111,6 +1111,30 @@ return JNIHandles::make_local(array); } +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_decodePC(JNIEnv *, jobject, jlong pc) { + TRACE_graal_3("CompilerToVM::decodePC"); + + VM_ENTRY_MARK; + + stringStream(st); + CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc); + if (blob == NULL) { + st.print("[unidentified pc]"); + } else { + st.print(blob->name()); + + nmethod* nm = blob->as_nmethod_or_null(); + if (nm != NULL && nm->method() != NULL) { + st.print(" %s.", nm->method()->method_holder()->klass_part()->external_name()); + nm->method()->name()->print_symbol_on(&st); + st.print(" @ %d", pc - (jlong) nm->entry_point()); + } + } + Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); + return JNIHandles::make_local(result()); + +} + #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_##f)) @@ -1179,6 +1203,7 @@ {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"RiMethod_vtableEntryOffset", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_vtableEntryOffset)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, + {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, }; int CompilerToVM_methods_count() { diff -r 077ec9468516 -r de571c017f61 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu May 03 11:05:46 2012 +0200 @@ -58,6 +58,9 @@ boolean_field(HotSpotTypeResolved, isInterface) \ int_field(HotSpotTypeResolved, instanceSize) \ end_class \ + start_class(HotSpotKlassOop) \ + oop_field(HotSpotKlassOop, javaMirror, "Ljava/lang/Class;") \ + end_class \ start_class(HotSpotMethodResolved) \ oop_field(HotSpotMethodResolved, compiler, "Lcom/oracle/graal/hotspot/Compiler;") \ oop_field(HotSpotMethodResolved, name, "Ljava/lang/String;") \ diff -r 077ec9468516 -r de571c017f61 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Fri Apr 27 13:13:06 2012 +0200 +++ b/src/share/vm/runtime/frame.cpp Thu May 03 11:05:46 2012 +0200 @@ -740,8 +740,9 @@ } else if (_cb->is_nmethod()) { methodOop m = ((nmethod *)_cb)->method(); if (m != NULL) { + address code = _cb->code_begin(); m->name_and_sig_as_C_string(buf, buflen); - st->print("J %s", buf); + st->print("J %s [" PTR_FORMAT "+%d]", buf, code, pc() - code); } else { st->print("J " PTR_FORMAT, pc()); } diff -r 077ec9468516 -r de571c017f61 src/share/vm/runtime/globals.hpp