# HG changeset patch # User Lukas Stadler # Date 1332325702 -3600 # Node ID ab038e0d6b430ea71df76febd52105578fc3039f # Parent 51111665eda6a102019f319b8c82788f2bacade8# Parent 7b2efb5ff2eaf7f5157d711cacf36c5a87abfb9a Merge diff -r 51111665eda6 -r ab038e0d6b43 .hgignore --- a/.hgignore Wed Mar 21 10:47:02 2012 +0100 +++ b/.hgignore Wed Mar 21 11:28:22 2012 +0100 @@ -1,4 +1,5 @@ ^mx/env +^mx/ecj.jar ^mx/includes ^build/ ^dist/ @@ -49,5 +50,6 @@ ^visualizer/build/ ^visualizer/dist/ ^visualizer/nbplatform/ +^src/share/tools/IdealGraphVisualizer/nbplatform/ ^.hgtip .DS_Store diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,10 +26,6 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.max.asm.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.xir.*; import com.oracle.graal.alloc.simple.*; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.gen.*; @@ -44,6 +40,10 @@ import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; +import com.oracle.max.asm.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.xir.*; public class GraalCompiler { @@ -74,11 +74,7 @@ this.backend = backend; } - public CiTargetMethod compileMethod(RiResolvedMethod method, int osrBCI, PhasePlan plan) { - return compileMethod(method, new StructuredGraph(method), osrBCI, plan); - } - - public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final PhasePlan plan) { + public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) { assert (method.accessFlags() & Modifier.NATIVE) == 0 : "compiling native methods is not supported"; if (osrBCI != -1) { throw new CiBailout("No OSR supported"); @@ -89,7 +85,7 @@ final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null; final LIR lir = Debug.scope("FrontEnd", new Callable() { public LIR call() { - return emitHIR(graph, assumptions, plan); + return emitHIR(graph, assumptions, plan, optimisticOpts); } }); final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable() { @@ -126,7 +122,7 @@ /** * Builds the graph, optimizes it. */ - public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, PhasePlan plan) { + public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) { if (graph.start().next() == null) { plan.runPhases(PhasePosition.AFTER_PARSING, graph); @@ -137,6 +133,10 @@ new PhiStampPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } + if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) { new ComputeProbabilityPhase().apply(graph); } @@ -154,7 +154,7 @@ } if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { - new InliningPhase(target, runtime, null, assumptions, plan).apply(graph); + new InliningPhase(target, runtime, null, assumptions, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); new PhiStampPhase().apply(graph); } @@ -174,7 +174,7 @@ } if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) { - new EscapeAnalysisPhase(target, runtime, assumptions, plan).apply(graph); + new EscapeAnalysisPhase(target, runtime, assumptions, plan, optimisticOpts).apply(graph); new PhiStampPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Wed Mar 21 11:28:22 2012 +0100 @@ -44,9 +44,9 @@ public static boolean Inline = true; public static boolean Intrinsify = true; public static boolean CacheGraphs = ____; - public static boolean InlineMonomorphicCalls = true; - public static boolean InlinePolymorphicCalls = true; - public static boolean InlineMegamorphicCalls = ____; + static boolean InlineMonomorphicCalls = true; + static boolean InlinePolymorphicCalls = true; + static boolean InlineMegamorphicCalls = ____; public static int InliningPolicy = 4; public static int WeightComputationPolicy = 2; public static int MaximumTrivialSize = 10; @@ -81,6 +81,8 @@ public static int LoopFrequencyPropagationPolicy = -2; // profiling information + public static int DeoptsToDisableOptimisticOptimization = 40; + public static boolean PrintDisabledOptimisticOptimizations = true; public static int MatureExecutionsBranch = 1; public static int MatureExecutionsPerSwitchCase = 1; public static int MatureExecutionsTypeProfile = 1; @@ -140,6 +142,7 @@ public static int TraceLIRGeneratorLevel = 0; public static boolean TraceEscapeAnalysis = ____; public static int TraceBytecodeParserLevel = 0; + public static boolean PrintBailouts = true; public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; @@ -148,13 +151,14 @@ // Code generator settings public static boolean PropagateTypes = ____; - public static boolean UseBranchPrediction = true; - public static boolean UseExceptionProbability = true; + public static boolean UseProfilingInformation = true; + static boolean RemoveNeverExecutedCode = true; + static boolean UseExceptionProbability = true; public static boolean AllowExplicitExceptionChecks = true; public static boolean OmitHotExceptionStacktrace = ____; public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; - public static boolean UseTypeCheckHints = true; + static boolean UseTypeCheckHints = true; public static boolean InlineVTableStubs = ____; public static boolean AlwaysInlineVTableStubs = ____; diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java Wed Mar 21 11:28:22 2012 +0100 @@ -0,0 +1,117 @@ +/* + * 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; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.criutils.*; + + + +public final class OptimisticOptimizations { + public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class)); + public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class)); + private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts"); + + private static enum Optimization { + RemoveNeverExecutedCode, + UseTypeCheckedInlining, + UseTypeCheckHints, + UseExceptionProbability + } + + private final Set enabledOpts; + + public OptimisticOptimizations(RiResolvedMethod method) { + this.enabledOpts = EnumSet.noneOf(Optimization.class); + + RiProfilingInfo profilingInfo = method.profilingInfo(); + if (checkDeoptimizations(profilingInfo, RiDeoptReason.UnreachedCode)) { + enabledOpts.add(Optimization.RemoveNeverExecutedCode); + } + if (checkDeoptimizations(profilingInfo, RiDeoptReason.TypeCheckedInliningViolated)) { + enabledOpts.add(Optimization.UseTypeCheckedInlining); + } + if (checkDeoptimizations(profilingInfo, RiDeoptReason.OptimizedTypeCheckViolated)) { + enabledOpts.add(Optimization.UseTypeCheckHints); + } + if (checkDeoptimizations(profilingInfo, RiDeoptReason.NotCompiledExceptionHandler)) { + enabledOpts.add(Optimization.UseExceptionProbability); + } + } + + private OptimisticOptimizations(Set enabledOpts) { + this.enabledOpts = enabledOpts; + } + + public void log(RiMethod method) { + for (Optimization opt: Optimization.values()) { + if (!enabledOpts.contains(opt)) { + if (GraalOptions.PrintDisabledOptimisticOptimizations) { + TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), CiUtil.format("%H.%n(%p)", method)); + } + disabledOptimisticOptsMetric.increment(); + } + } + } + + public boolean removeNeverExecutedCode() { + return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode); + } + + public boolean useUseTypeCheckHints() { + return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints); + } + + public boolean inlineMonomorphicCalls() { + return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); + } + + public boolean inlinePolymorphicCalls() { + return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); + } + + public boolean inlineMegamorphicCalls() { + return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); + } + + public boolean useExceptionProbability() { + return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability); + } + + public boolean lessOptimisticThan(OptimisticOptimizations other) { + for (Optimization opt: Optimization.values()) { + if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) { + return true; + } + } + return false; + } + + private static boolean checkDeoptimizations(RiProfilingInfo profilingInfo, RiDeoptReason reason) { + return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization; + } +} diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Mar 21 11:28:22 2012 +0100 @@ -56,7 +56,6 @@ import com.oracle.graal.lir.StandardOp.PhiLabelOp; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -750,7 +749,7 @@ } @Override - public void emitGuardCheck(BooleanNode comp, long leafGraphId) { + public void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId) { if (comp instanceof NullCheckNode && !((NullCheckNode) comp).expectedNull) { emitNullCheckGuard((NullCheckNode) comp, leafGraphId); } else if (comp instanceof ConstantNode && comp.asConstant().asBoolean()) { @@ -759,7 +758,7 @@ } else { // Fall back to a normal branch. LIRDebugInfo info = state(leafGraphId); - LabelRef stubEntry = createDeoptStub(DeoptAction.InvalidateReprofile, info, comp); + LabelRef stubEntry = createDeoptStub(RiDeoptAction.InvalidateReprofile, deoptReason, info, comp); emitBranch(comp, null, stubEntry, info); } } @@ -991,7 +990,8 @@ return argList; } - protected abstract LabelRef createDeoptStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo); + + protected abstract LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo); @Override public Variable emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) { diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java Wed Mar 21 11:28:22 2012 +0100 @@ -49,25 +49,30 @@ } for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) { - visitDeoptBranch(findBeginNode(d), d, graph); + visitDeoptBegin(findBeginNode(d), d, graph); } new DeadCodeEliminationPhase().apply(graph); } - private void visitDeoptBranch(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) { + private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) { if (deoptBegin instanceof MergeNode) { MergeNode mergeNode = (MergeNode) deoptBegin; - Debug.log("Eliminating %s followed by %s", mergeNode, deopt); + Debug.log("Visiting %s followed by %s", mergeNode, deopt); List ends = mergeNode.forwardEnds().snapshot(); for (EndNode end : ends) { if (!end.isDeleted()) { BeginNode beginNode = findBeginNode(end); - visitDeoptBranch(beginNode, deopt, graph); + if (!(beginNode instanceof MergeNode)) { + visitDeoptBegin(beginNode, deopt, graph); + } } } - if (!deopt.isDeleted()) { - visitDeoptBranch(findBeginNode(deopt), deopt, graph); + if (mergeNode.isDeleted()) { + if (!deopt.isDeleted()) { + Debug.log("Merge deleted, deopt moved to %s", findBeginNode(deopt)); + visitDeoptBegin(findBeginNode(deopt), deopt, graph); + } } } else if (deoptBegin.predecessor() instanceof IfNode) { IfNode ifNode = (IfNode) deoptBegin.predecessor(); @@ -79,7 +84,7 @@ } BeginNode ifBlockBegin = findBeginNode(ifNode); Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.leafGraphId())); + FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.leafGraphId())); otherBegin.replaceAtUsages(ifBlockBegin); FixedNode next = otherBegin.next(); otherBegin.setNext(null); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Wed Mar 21 11:28:22 2012 +0100 @@ -215,12 +215,14 @@ private final GraalRuntime runtime; private final CiAssumptions assumptions; private final PhasePlan plan; + private final OptimisticOptimizations optimisticOpts; - public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, PhasePlan plan) { + public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) { this.runtime = runtime; this.target = target; this.assumptions = assumptions; this.plan = plan; + this.optimisticOpts = optimisticOpts; } public static class EscapeRecord { @@ -387,7 +389,7 @@ if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { TTY.println("Trying inlining to get a non-escaping object for %s", node); } - new InliningPhase(target, runtime, invokes, assumptions, plan).apply(graph); + new InliningPhase(target, runtime, invokes, assumptions, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); if (node.isDeleted()) { if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Wed Mar 21 11:28:22 2012 +0100 @@ -56,18 +56,20 @@ private final PhasePlan plan; private final WeightComputationPolicy weightComputationPolicy; private final InliningPolicy inliningPolicy; + private final OptimisticOptimizations optimisticOpts; // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered"); private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); - public InliningPhase(CiTarget target, GraalRuntime runtime, Collection hints, CiAssumptions assumptions, PhasePlan plan) { + public InliningPhase(CiTarget target, GraalRuntime runtime, Collection hints, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) { this.target = target; this.runtime = runtime; this.hints = hints; this.assumptions = assumptions; this.plan = plan; + this.optimisticOpts = optimisticOpts; this.weightComputationPolicy = createWeightComputationPolicy(); this.inliningPolicy = createInliningPolicy(); } @@ -139,7 +141,7 @@ } private void scanInvoke(Invoke invoke, int level) { - InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this); + InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts); if (info != null) { assert level == -1 || computeInliningLevel(invoke) == level : "outer FramesStates must match inlining level"; metricInliningConsidered.increment(); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Wed Mar 21 11:28:22 2012 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.max.cri.ri.*; public class LoweringPhase extends Phase { @@ -59,7 +60,7 @@ } @Override - public Node createGuard(Node condition, long leafGraphId) { + public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) { // TODO (thomaswue): Document why this must not be called on floating nodes. throw new UnsupportedOperationException(); } @@ -117,7 +118,7 @@ } @Override - public Node createGuard(Node condition, long leafGraphId) { + public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) { FixedNode guardAnchor = (FixedNode) getGuardAnchor(); if (GraalOptions.OptEliminateGuards) { for (Node usage : condition.usages()) { @@ -126,7 +127,7 @@ } } } - GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, leafGraphId)); + GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, leafGraphId)); activeGuards.grow(); activeGuards.mark(newGuard); return newGuard; diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java Wed Mar 21 11:28:22 2012 +0100 @@ -53,11 +53,8 @@ LOW_LEVEL } - public static final PhasePlan DEFAULT = new PhasePlan(); - @SuppressWarnings("unchecked") private final ArrayList[] phases = new ArrayList[PhasePosition.values().length]; - private final Set> disabledPhases = new HashSet<>(); public void addPhase(PhasePosition pos, Phase phase) { diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Wed Mar 21 11:28:22 2012 +0100 @@ -24,29 +24,29 @@ import java.util.*; +import com.oracle.graal.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.cri.ci.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; +import com.oracle.max.cri.ri.*; public class AMD64DeoptimizationStub extends AMD64SlowPath { public final Label label = new Label(); public final LIRDebugInfo info; - public final DeoptAction action; + public final RiDeoptAction action; + public final RiDeoptReason reason; public final Object deoptInfo; - public AMD64DeoptimizationStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo) { + public AMD64DeoptimizationStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo) { this.action = action; + this.reason = reason; this.info = info; this.deoptInfo = deoptInfo; } - private static ArrayList keepAlive = new ArrayList<>(); @Override @@ -62,28 +62,9 @@ // TODO Make this an explicit calling convention instead of using a scratch register AMD64Call.directCall(tasm, masm, CiRuntimeCall.SetDeoptInfo, info); } - int code; - switch(action) { - case None: - code = 0; - break; - case Recompile: - code = 1; - break; - case InvalidateReprofile: - code = 2; - break; - case InvalidateRecompile: - code = 3; - break; - case InvalidateStopCompiling: - code = 4; - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - masm.movq(scratch, code); - // TODO Make this an explicit calling convention instead of using a scratch register + + masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason)); + // TODO Make this an explicit calling convention instead of using a scratch register AMD64Call.directCall(tasm, masm, CiRuntimeCall.Deoptimize, info); AMD64Call.shouldNotReachHere(tasm, masm); } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Mar 21 11:28:22 2012 +0100 @@ -66,7 +66,6 @@ import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp; import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -498,19 +497,20 @@ return result; } + @Override - public void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo) { + public void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo) { assert cond != null; LIRDebugInfo info = state(); - LabelRef stubEntry = createDeoptStub(action, info, deoptInfo); + LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); append(new BranchOp(cond, stubEntry, info)); } @Override - public void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId) { + public void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId) { LIRDebugInfo info = state(leafGraphId); - LabelRef stubEntry = createDeoptStub(action, info, deoptInfo); + LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); append(new JumpOp(stubEntry, info)); } @@ -551,9 +551,9 @@ } @Override - protected LabelRef createDeoptStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo) { + protected LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo) { assert info.topFrame.bci >= 0 : "invalid bci for deopt framestate"; - AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, info, deoptInfo); + AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo); lir.deoptimizationStubs.add(stub); return LabelRef.forLabel(stub.label); } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Wed Mar 21 11:28:22 2012 +0100 @@ -35,7 +35,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -52,23 +51,23 @@ void recordConcreteMethodAssumption(RiResolvedMethod method, RiResolvedType context, RiResolvedMethod impl); } - public static String methodName(RiResolvedMethod method) { - return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; - } - 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() + ": " + CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + return parent.name() + "@" + invoke.bci() + ": " + methodNameAndCodeSize(method); } else { - return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + return methodNameAndCodeSize(method); } } else { return null; } } + private static String methodNameAndCodeSize(RiResolvedMethod method) { + return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + } + /** * Represents an opportunity for inlining at the given invoke, with the given weight and level. * The weight is the amortized weight of the additional code - so smaller is better. @@ -176,7 +175,7 @@ ValueNode receiver = invoke.callTarget().receiver(); ReadHubNode objectClass = graph.add(new ReadHubNode(receiver)); IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClass, type)); - FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, invoke.leafGraphId())); + FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId())); AnchorNode anchor = graph.add(new AnchorNode()); assert invoke.predecessor() != null; @@ -304,7 +303,7 @@ if (shouldFallbackToInvoke()) { unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false); } else { - unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, invoke.leafGraphId())); + unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId())); } // replace the invoke exception edge @@ -369,7 +368,7 @@ ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver())); graph.addBeforeFixed(invoke.node(), objectClassNode); - FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, invoke.leafGraphId())); + FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId())); FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, new BeginNode[] {calleeEntryNode}, unknownTypeNode); FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); @@ -541,19 +540,19 @@ * @param callback a callback that is used to determine the weight of a specific inlining * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke */ - public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalRuntime runtime, CiAssumptions assumptions, InliningCallback callback) { - if (!checkInvokeConditions(invoke)) { - return null; - } + public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalRuntime runtime, CiAssumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) { RiResolvedMethod parent = invoke.stateAfter().method(); MethodCallTargetNode callTarget = invoke.callTarget(); RiResolvedMethod targetMethod = callTarget.targetMethod(); - if (targetMethod == null) { return null; } + if (!checkInvokeConditions(invoke)) { + return null; + } + if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) { - if (checkTargetConditions(invoke, targetMethod)) { + if (checkTargetConditions(invoke, targetMethod, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, targetMethod, invoke); return new ExactInlineInfo(invoke, weight, level, targetMethod); } @@ -563,7 +562,7 @@ RiResolvedType exact = callTarget.receiver().exactType(); assert exact.isSubtypeOf(targetMethod.holder()) : exact + " subtype of " + targetMethod.holder() + " for " + targetMethod; RiResolvedMethod resolved = exact.resolveMethodImpl(targetMethod); - if (checkTargetConditions(invoke, resolved)) { + if (checkTargetConditions(invoke, resolved, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke); return new ExactInlineInfo(invoke, weight, level, resolved); } @@ -583,7 +582,7 @@ if (assumptions != null) { RiResolvedMethod concrete = holder.uniqueConcreteMethod(targetMethod); if (concrete != null) { - if (checkTargetConditions(invoke, concrete)) { + if (checkTargetConditions(invoke, concrete, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke); return new AssumptionInlineInfo(invoke, weight, level, holder, concrete); } @@ -592,6 +591,10 @@ } // type check based inlining + return getTypeCheckedInlineInfo(invoke, level, callback, parent, targetMethod, optimisticOpts); + } + + private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, int level, InliningCallback callback, RiResolvedMethod parent, RiResolvedMethod targetMethod, OptimisticOptimizations optimisticOpts) { RiProfilingInfo profilingInfo = parent.profilingInfo(); RiTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci()); if (typeProfile != null) { @@ -602,10 +605,10 @@ assert types.length == probabilities.length : "length must match"; double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); if (types.length == 1 && notRecordedTypeProbability == 0) { - if (GraalOptions.InlineMonomorphicCalls) { + if (optimisticOpts.inlineMonomorphicCalls()) { RiResolvedType type = types[0]; RiResolvedMethod concrete = type.resolveMethodImpl(targetMethod); - if (checkTargetConditions(invoke, concrete)) { + if (checkTargetConditions(invoke, concrete, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke); return new TypeGuardInlineInfo(invoke, weight, level, concrete, type); } @@ -618,7 +621,7 @@ } } else { invoke.setMegamorph(true); - if (GraalOptions.InlinePolymorphicCalls && notRecordedTypeProbability == 0 || GraalOptions.InlineMegamorphicCalls && notRecordedTypeProbability > 0) { + if (optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0 || optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { // TODO (chaeubl) inlining of multiple methods should work differently // 1. check which methods can be inlined // 2. for those methods, use weight and probability to compute which of them should be inlined @@ -644,7 +647,7 @@ double totalWeight = 0; boolean canInline = true; for (RiResolvedMethod concrete: concreteMethods) { - if (!checkTargetConditions(invoke, concrete)) { + if (!checkTargetConditions(invoke, concrete, optimisticOpts)) { canInline = false; break; } @@ -658,7 +661,7 @@ return null; } } else { - if (!GraalOptions.InlinePolymorphicCalls && notRecordedTypeProbability == 0) { + if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) { Debug.log("not inlining %s because GraalOptions.InlinePolymorphicCalls == false", methodName(targetMethod, invoke)); } else { Debug.log("not inlining %s because GraalOptions.InlineMegamorphicCalls == false", methodName(targetMethod, invoke)); @@ -699,7 +702,7 @@ return true; } - private static boolean checkTargetConditions(Invoke invoke, RiMethod method) { + private static boolean checkTargetConditions(Invoke invoke, RiMethod method, OptimisticOptimizations optimisticOpts) { if (method == null) { Debug.log("not inlining because method is not resolved"); return false; @@ -710,23 +713,28 @@ } RiResolvedMethod resolvedMethod = (RiResolvedMethod) method; if (Modifier.isNative(resolvedMethod.accessFlags())) { - Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod, invoke)); return false; } if (Modifier.isAbstract(resolvedMethod.accessFlags())) { - Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod, invoke)); return false; } if (!resolvedMethod.holder().isInitialized()) { - Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod)); + Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod, invoke)); return false; } if (!resolvedMethod.canBeInlined()) { - Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod, invoke)); return false; } if (computeRecursiveInliningLevel(invoke.stateAfter(), (RiResolvedMethod) method) > GraalOptions.MaximumRecursiveInlining) { - Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod)); + Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod, invoke)); + return false; + } + OptimisticOptimizations calleeOpts = new OptimisticOptimizations(resolvedMethod); + if (calleeOpts.lessOptimisticThan(optimisticOpts)) { + Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(resolvedMethod, invoke)); return false; } @@ -812,7 +820,7 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); - DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptAction.InvalidateRecompile, invoke.leafGraphId()); + DeoptimizeNode deoptimizeNode = new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.NotCompiledExceptionHandler, invoke.leafGraphId()); unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode)); // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state // (because there is no "after exception" frame state!) @@ -900,7 +908,7 @@ NodeInputList parameters = callTarget.arguments(); ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.stamp().nonNull()) { - graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), invoke.leafGraphId()))); + graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), RiDeoptReason.ClassCastException, invoke.leafGraphId()))); } } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Wed Mar 21 11:28:22 2012 +0100 @@ -57,7 +57,7 @@ @Override public boolean add(T node) { - assert !node.isDeleted(); + assert node == null || !node.isDeleted(); self.incModCount(); return super.add(node); } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Mar 21 11:28:22 2012 +0100 @@ -76,6 +76,7 @@ // methodData information public int methodDataOopDataOffset; + public int methodDataOopTrapHistoryOffset; public int dataLayoutHeaderSize; public int dataLayoutTagOffset; public int dataLayoutFlagsOffset; diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Mar 21 11:28:22 2012 +0100 @@ -27,9 +27,6 @@ import java.util.*; import java.util.concurrent.*; -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.compiler.phases.*; import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; @@ -41,7 +38,11 @@ import com.oracle.graal.hotspot.server.*; import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.snippets.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.criutils.*; /** * Exits from the HotSpot VM into Java code. @@ -122,10 +123,10 @@ @Override public void run() { VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); - GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT); + GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget()); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets()); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets()); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets()); } }); @@ -298,15 +299,15 @@ public void run() { try { - final PhasePlan plan = getDefaultPhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime()); - plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); + final PhasePlan plan = createHotSpotSpecificPhasePlan(optimisticOpts); long startTime = System.nanoTime(); int index = compiledMethodCount++; final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed(); if (printCompilation) { TTY.println(String.format("Graal %4d %-70s %-45s %-50s ...", index, method.holder().name(), method.name(), method.signature().asString())); } + optimisticOpts.log(method); CiTargetMethod result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); @@ -315,7 +316,8 @@ result = Debug.scope("Compiling", new Callable() { @Override public CiTargetMethod call() throws Exception { - return compiler.getCompiler().compileMethod(method, -1, plan); + StructuredGraph graph = new StructuredGraph(method); + return compiler.getCompiler().compileMethod(method, graph, -1, plan, optimisticOpts); } }); } finally { @@ -330,9 +332,13 @@ compiler.getRuntime().installMethod(method, result); } catch (CiBailout bailout) { Debug.metric("Bailouts").increment(); - if (GraalOptions.ExitVMOnBailout) { + if (GraalOptions.PrintBailouts || GraalOptions.ExitVMOnBailout) { + TTY.println("WARN: Compilation bailout"); bailout.printStackTrace(TTY.cachedOut); - System.exit(-1); + + if (GraalOptions.ExitVMOnBailout) { + System.exit(-1); + } } } catch (Throwable t) { if (GraalOptions.ExitVMOnException) { @@ -444,8 +450,10 @@ return CiConstant.forObject(object); } - private PhasePlan getDefaultPhasePlan() { + private PhasePlan createHotSpotSpecificPhasePlan(OptimisticOptimizations optimisticOpts) { PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); if (GraalOptions.Intrinsify) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy); } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,10 +26,10 @@ import sun.misc.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.compiler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; +import com.oracle.max.cri.ri.*; public final class HotSpotMethodData extends CompilerObject { @@ -80,6 +80,11 @@ return position >= 0 && position < normalDataSize + extraDataSize; } + public int getDeoptimizationCount(RiDeoptReason reason) { + int reasonIndex = compiler.getRuntime().convertDeoptReason(reason); + return unsafe.getByte(hotspotMirror, (long) config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF; + } + public HotSpotMethodDataAccessor getNormalData(int position) { if (position >= normalDataSize) { return null; diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Wed Mar 21 11:28:22 2012 +0100 @@ -30,6 +30,7 @@ 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.java.bytecode.*; /** @@ -213,12 +214,13 @@ @Override public RiProfilingInfo profilingInfo() { - if (methodData == null) { + if (GraalOptions.UseProfilingInformation && methodData == null) { methodData = compiler.getVMEntries().RiMethod_methodData(this); } if (methodData == null) { - return new HotSpotNoProfilingInfo(compiler); + // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization. + return BaseProfilingInfo.get(RiExceptionSeen.FALSE); } else { return new HotSpotProfilingInfo(compiler, methodData); } @@ -279,6 +281,18 @@ } } } + + 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 diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotNoProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotNoProfilingInfo.java Wed Mar 21 10:47:02 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * 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.max.cri.ri.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.Compiler; - -/** - * Dummy profiling information in case that a method was not executed frequently enough so that - * no profiling information does exist yet. - */ -public final class HotSpotNoProfilingInfo extends CompilerObject implements RiProfilingInfo { - /** - * - */ - private static final long serialVersionUID = 4357945025049704109L; - // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization. - private static final HotSpotMethodDataAccessor noData = HotSpotMethodData.getNoDataAccessor(false); - - public HotSpotNoProfilingInfo(Compiler compiler) { - super(compiler); - } - - @Override - public RiTypeProfile getTypeProfile(int bci) { - return noData.getTypeProfile(null, -1); - } - - @Override - public double getBranchTakenProbability(int bci) { - return noData.getBranchTakenProbability(null, -1); - } - - @Override - public double[] getSwitchProbabilities(int bci) { - return noData.getSwitchProbabilities(null, -1); - } - - @Override - public RiExceptionSeen getExceptionSeen(int bci) { - return noData.getExceptionSeen(null, -1); - } - - @Override - public int getExecutionCount(int bci) { - return noData.getExecutionCount(null, -1); - } -} diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java Wed Mar 21 11:28:22 2012 +0100 @@ -79,6 +79,11 @@ return dataAccessor.getExecutionCount(methodData, position); } + @Override + public int getDeoptimizationCount(RiDeoptReason reason) { + return methodData.getDeoptimizationCount(reason); + } + private void findBCI(int targetBCI, boolean searchExtraData) { assert targetBCI >= 0 : "invalid BCI"; diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Wed Mar 21 11:28:22 2012 +0100 @@ -229,7 +229,7 @@ int displacement = ((HotSpotField) field.field()).offset(); assert field.kind() != CiKind.Illegal; ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph), field.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixedWithFixed(field, memoryRead); } else if (n instanceof StoreFieldNode) { StoreFieldNode storeField = (StoreFieldNode) n; @@ -238,7 +238,7 @@ } HotSpotField field = (HotSpotField) storeField.field(); WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph))); - memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); + memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID)); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); @@ -277,7 +277,7 @@ } else { AnchorNode anchor = graph.add(new AnchorNode()); graph.addBeforeFixed(storeIndexed, anchor); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), StructuredGraph.INVALID_GRAPH_ID); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID); ReadNode arrayClass = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull())); arrayClass.setGuard(guard); graph.addBeforeFixed(storeIndexed, arrayClass); @@ -300,7 +300,7 @@ IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph); location.setIndexScalingEnabled(false); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; @@ -318,7 +318,7 @@ ReadHubNode objectClassNode = (ReadHubNode) n; LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph); ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull())); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), StructuredGraph.INVALID_GRAPH_ID)); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixed(objectClassNode, memoryRead); } } @@ -328,7 +328,7 @@ } private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) { - return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), leafGraphId); + return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException, leafGraphId); } @Override @@ -349,7 +349,7 @@ StructuredGraph graph = new StructuredGraph(); LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); - ReadNode result = graph.add(new ReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull())); + FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull())); ReturnNode ret = graph.add(new ReturnNode(result)); graph.start().setNext(klassOop); klassOop.setNext(ret); @@ -424,13 +424,55 @@ @Override public CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph) { final PhasePlan plan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime()); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - return compiler.getCompiler().compileMethod(method, graph, -1, plan); + return compiler.getCompiler().compileMethod(method, graph, -1, plan, OptimisticOptimizations.ALL); } @Override public long[] getDeoptedLeafGraphIds() { return compiler.getVMEntries().getDeoptedLeafGraphIds(); } + + @Override + public int encodeDeoptActionAndReason(RiDeoptAction action, RiDeoptReason reason) { + final int actionShift = 0; + final int reasonShift = 3; + + int actionValue = convertDeoptAction(action); + int reasonValue = convertDeoptReason(reason); + return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); + } + + @Override + public int convertDeoptAction(RiDeoptAction action) { + switch(action) { + case None: return 0; + case RecompileIfTooManyDeopts: return 1; + case InvalidateReprofile: return 2; + case InvalidateRecompile: return 3; + case InvalidateStopCompiling: return 4; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public int convertDeoptReason(RiDeoptReason reason) { + switch(reason) { + case None: return 0; + case NullCheckException: return 1; + case BoundsCheckException: return 2; + case ClassCastException: return 3; + case ArrayStoreException: return 4; + case UnreachedCode: return 5; + case TypeCheckedInliningViolated: return 6; + case OptimizedTypeCheckViolated: return 7; + case NotCompiledExceptionHandler: return 8; + case Unresolved: return 9; + case JavaSubroutineMismatch: return 10; + case ArithmeticException: return 11; + case RuntimeConstraint: return 12; + default: throw GraalInternalError.shouldNotReachHere(); + } + } } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,25 +22,29 @@ */ package com.oracle.graal.hotspot.ri; +import static com.oracle.graal.hotspot.ri.TemplateFlag.*; import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.graal.hotspot.ri.TemplateFlag.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiAddress.*; -import com.oracle.max.cri.ci.CiRegister.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.*; -import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; import com.oracle.graal.compiler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.CiAddress.Scale; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiRegister.RegisterFlag; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.Representation; +import com.oracle.max.cri.xir.*; +import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; +import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; +import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; public class HotSpotXirGenerator implements RiXirGenerator { @@ -73,6 +77,7 @@ private final RiRegisterConfig registerConfig; private final Compiler compiler; + private CiXirAssembler globalAsm; public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig, Compiler compiler) { @@ -710,10 +715,10 @@ asm.jneq(end, objHub, asm.o(null)); } } + + RiDeoptReason deoptReason = is(EXACT_HINTS, flags) ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException; XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - - asm.mov(scratch, wordConst(asm, 2)); - + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); @@ -891,7 +896,7 @@ if (is(BOUNDS_CHECK, flags)) { asm.bindOutOfLine(failBoundsCheck); XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.BoundsCheckException))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } @@ -1081,7 +1086,7 @@ 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, 0)); + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ClassCastException))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.jmp(store); } @@ -1162,7 +1167,7 @@ if (is(BOUNDS_CHECK, flags)) { asm.bindOutOfLine(failBoundsCheck); XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.BoundsCheckException))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } @@ -1172,7 +1177,7 @@ 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, 0)); + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ArrayStoreException))); asm.callRuntime(CiRuntimeCall.Deoptimize, null); asm.shouldNotReachHere(); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,14 +26,13 @@ import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.bytecode.*; import com.oracle.graal.nodes.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; /** * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow @@ -183,35 +182,28 @@ * The blocks found in this method, in reverse postorder. */ public final List blocks; - public final RiResolvedMethod method; - - private final BytecodeStream stream; - - private final RiExceptionHandler[] exceptionHandlers; - - private Block[] blockMap; - public final BitSet canTrap; - public boolean hasJsrBytecodes; - public Block startBlock; - public final boolean useBranchPrediction; + private final OptimisticOptimizations optimisticOpts; + private final BytecodeStream stream; + private final RiExceptionHandler[] exceptionHandlers; + private Block[] blockMap; /** * Creates a new BlockMap instance from bytecode of the given method . * @param method the compiler interface method containing the code */ - public BciBlockMapping(RiResolvedMethod method, boolean useBranchPrediction) { + public BciBlockMapping(RiResolvedMethod method, OptimisticOptimizations optimisticOpts) { this.method = method; + this.optimisticOpts = optimisticOpts; exceptionHandlers = method.exceptionHandlers(); stream = new BytecodeStream(method.code()); this.blockMap = new Block[method.codeSize()]; this.canTrap = new BitSet(blockMap.length); this.blocks = new ArrayList<>(); - this.useBranchPrediction = useBranchPrediction; } public RiExceptionHandler[] exceptionHandlers() { @@ -383,8 +375,10 @@ case SALOAD: case PUTFIELD: case GETFIELD: { - if (GraalOptions.AllowExplicitExceptionChecks && profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE) { - canTrap.set(bci); + if (GraalOptions.AllowExplicitExceptionChecks) { + if (!optimisticOpts.useExceptionProbability() || profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE) { + canTrap.set(bci); + } } } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,19 +22,19 @@ */ package com.oracle.graal.java; +import static com.oracle.graal.graph.iterators.NodePredicates.*; import static com.oracle.graal.nodes.ValueUtil.*; import static java.lang.reflect.Modifier.*; import java.util.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; public class FrameStateBuilder { private final RiResolvedMethod method; @@ -169,7 +169,7 @@ } else if (block.isPhiAtMerge(currentValue)) { if (otherValue == null || currentValue.kind() != otherValue.kind()) { - deletePhi(currentValue); + deletePhi((PhiNode) currentValue); return null; } ((PhiNode) currentValue).addInput(otherValue); @@ -194,19 +194,19 @@ } } - private void deletePhi(Node phi) { + private void deletePhi(PhiNode phi) { if (phi.isDeleted()) { return; } // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles). - List phiUsages = phi.usages().filter(NodePredicates.isA(PhiNode.class)).snapshot(); + List phiUsages = phi.usages().filter(PhiNode.class).snapshot(); // Remove the phi function from all FrameStates where it is used and then delete it. - assert phi.usages().filter(NodePredicates.isNotA(FrameState.class)).filter(NodePredicates.isNotA(PhiNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; + assert phi.usages().filter(isNotA(FrameState.class).nor(PhiNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; phi.replaceAtUsages(null); phi.safeDelete(); - for (Node phiUsage : phiUsages) { + for (PhiNode phiUsage : phiUsages) { deletePhi(phiUsage); } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,9 +22,8 @@ */ package com.oracle.graal.java; +import com.oracle.graal.compiler.phases.*; import com.oracle.max.cri.ri.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; public class GraphBuilderConfiguration { @@ -32,22 +31,15 @@ Default, EagerForSnippets, Eager, } - private final boolean useBranchPrediction; private final ResolvePolicy resolving; private final PhasePlan plan; private RiResolvedType[] skippedExceptionTypes; - public GraphBuilderConfiguration(boolean useBranchPrediction, ResolvePolicy resolving, PhasePlan plan) { - this.useBranchPrediction = useBranchPrediction; + public GraphBuilderConfiguration(ResolvePolicy resolving, PhasePlan plan) { this.resolving = resolving; this.plan = plan; } - public boolean useBranchPrediction() { - return useBranchPrediction; - } - - public void setSkippedExceptionTypes(RiResolvedType[] skippedExceptionTypes) { this.skippedExceptionTypes = skippedExceptionTypes; } @@ -73,7 +65,7 @@ } public static GraphBuilderConfiguration getDefault(PhasePlan plan) { - return new GraphBuilderConfiguration(GraalOptions.UseBranchPrediction, ResolvePolicy.Default, plan); + return new GraphBuilderConfiguration(ResolvePolicy.Default, plan); } public static GraphBuilderConfiguration getSnippetDefault() { @@ -81,6 +73,6 @@ } public static GraphBuilderConfiguration getSnippetDefault(PhasePlan plan) { - return new GraphBuilderConfiguration(false, ResolvePolicy.EagerForSnippets, plan); + return new GraphBuilderConfiguration(ResolvePolicy.EagerForSnippets, plan); } } diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 21 11:28:22 2012 +0100 @@ -29,11 +29,6 @@ import java.util.*; import java.util.concurrent.atomic.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.Representation; -import com.oracle.max.criutils.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.util.*; @@ -43,13 +38,16 @@ import com.oracle.graal.java.BciBlockMapping.ExceptionBlock; import com.oracle.graal.java.bytecode.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; 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.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.Representation; +import com.oracle.max.criutils.*; /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. @@ -90,7 +88,8 @@ private BitSet canTrapBitSet; - private final GraphBuilderConfiguration config; + private final GraphBuilderConfiguration graphBuilderConfig; + private final OptimisticOptimizations optimisticOpts; private long graphId; @@ -106,13 +105,9 @@ } } - - public GraphBuilderPhase(RiRuntime runtime) { - this(runtime, GraphBuilderConfiguration.getDefault()); - } - - public GraphBuilderPhase(RiRuntime runtime, GraphBuilderConfiguration config) { - this.config = config; + public GraphBuilderPhase(RiRuntime runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + this.graphBuilderConfig = graphBuilderConfig; + this.optimisticOpts = optimisticOpts; this.runtime = runtime; this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; } @@ -130,7 +125,7 @@ methodSynchronizedObject = null; exceptionHandlers = null; this.currentGraph = graph; - this.frameState = new FrameStateBuilder(method, graph, config.eagerResolving()); + this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); build(); } @@ -140,7 +135,7 @@ } private BciBlockMapping createBlockMap() { - BciBlockMapping map = new BciBlockMapping(method, config.useBranchPrediction()); + BciBlockMapping map = new BciBlockMapping(method, optimisticOpts); map.build(); Debug.dump(map, CiUtil.format("After block building %f %R %H.%n(%P)", method)); @@ -191,7 +186,7 @@ connectLoopEndToBegin(); - // remove Placeholders (except for loop exits) + // remove Placeholders for (BlockPlaceholderNode n : currentGraph.getNodes(BlockPlaceholderNode.class)) { currentGraph.removeFixed(n); } @@ -252,7 +247,7 @@ private BeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; - if (GraalOptions.UseExceptionProbability) { + if (optimisticOpts.useExceptionProbability()) { // be conservative if information was not recorded (could result in endless recompiles otherwise) if (bci != FrameState.BEFORE_BCI && exceptionObject == null && profilingInfo.getExceptionSeen(bci) == RiExceptionSeen.FALSE) { return null; @@ -325,7 +320,7 @@ if (riType instanceof RiResolvedType) { frameState.push(CiKind.Object, append(ConstantNode.forCiConstant(((RiResolvedType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph))); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.push(CiKind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); } } else if (con instanceof CiConstant) { @@ -584,7 +579,7 @@ private void genThrow(int bci) { ValueNode exception = frameState.apop(); - FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), graphId)); + FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), RiDeoptReason.NullCheckException, graphId)); append(node); append(handleException(exception, bci)); } @@ -592,39 +587,39 @@ private RiType lookupType(int cpi, int bytecode) { eagerResolvingForSnippets(cpi, bytecode); RiType result = constantPool.lookupType(cpi, bytecode); - assert !config.eagerResolvingForSnippets() || result instanceof RiResolvedType; + assert !graphBuilderConfig.eagerResolvingForSnippets() || result instanceof RiResolvedType; return result; } private RiMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); RiMethod result = constantPool.lookupMethod(cpi, opcode); - assert !config.eagerResolvingForSnippets() || ((result instanceof RiResolvedMethod) && ((RiResolvedMethod) result).holder().isInitialized()); + assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof RiResolvedMethod) && ((RiResolvedMethod) result).holder().isInitialized()); return result; } private RiField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); RiField result = constantPool.lookupField(cpi, opcode); - assert !config.eagerResolvingForSnippets() || (result instanceof RiResolvedField && ((RiResolvedField) result).holder().isInitialized()); + assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof RiResolvedField && ((RiResolvedField) result).holder().isInitialized()); return result; } private Object lookupConstant(int cpi, int opcode) { eagerResolving(cpi, opcode); Object result = constantPool.lookupConstant(cpi); - assert !config.eagerResolving() || !(result instanceof RiType) || (result instanceof RiResolvedType); + assert !graphBuilderConfig.eagerResolving() || !(result instanceof RiType) || (result instanceof RiResolvedType); return result; } private void eagerResolving(int cpi, int bytecode) { - if (config.eagerResolving()) { + if (graphBuilderConfig.eagerResolving()) { constantPool.loadReferencedType(cpi, bytecode); } } private void eagerResolvingForSnippets(int cpi, int bytecode) { - if (config.eagerResolvingForSnippets()) { + if (graphBuilderConfig.eagerResolvingForSnippets()) { constantPool.loadReferencedType(cpi, bytecode); } } @@ -632,7 +627,7 @@ private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0]; private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) { - if (!GraalOptions.UseTypeCheckHints || Util.isFinalClass(type)) { + if (!optimisticOpts.useUseTypeCheckHints() || Util.isFinalClass(type)) { return new RiResolvedType[] {type}; } else { RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype(); @@ -676,7 +671,7 @@ frameState.apush(checkCast); } else { ValueNode object = frameState.apop(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), graphId))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), RiDeoptReason.Unresolved, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -694,7 +689,7 @@ frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)); IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1)); append(ifNode); lastInstr = trueSucc; @@ -708,7 +703,7 @@ NewInstanceNode n = currentGraph.add(new NewInstanceNode((RiResolvedType) type)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -749,7 +744,7 @@ NewArrayNode n = currentGraph.add(new NewObjectArrayNode((RiResolvedType) type, length)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } @@ -766,7 +761,7 @@ FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((RiResolvedType) type, dims)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); } } @@ -780,7 +775,7 @@ LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (RiResolvedField) field)); appendOptimizedLoadField(kind, load); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.push(kind.stackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); } } @@ -881,7 +876,7 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (RiResolvedField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); } } @@ -923,7 +918,7 @@ if (initialized) { return appendConstant(((RiResolvedType) holder).getEncoding(representation)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); return null; } } @@ -984,7 +979,7 @@ } private void genInvokeDeopt(RiMethod unresolvedTarget, boolean withReceiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId))); + append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId))); frameState.popArguments(unresolvedTarget.signature().argumentSlots(withReceiver), unresolvedTarget.signature().argumentCount(withReceiver)); CiKind kind = unresolvedTarget.signature().returnKind(false); if (kind != CiKind.Void) { @@ -1021,7 +1016,7 @@ private void appendInvoke(InvokeKind invokeKind, RiResolvedMethod targetMethod, ValueNode[] args) { CiKind resultType = targetMethod.signature().returnKind(false); if (GraalOptions.DeoptALot) { - DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptAction.None, StructuredGraph.INVALID_GRAPH_ID)); + DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(RiDeoptAction.None, RiDeoptReason.RuntimeConstraint, StructuredGraph.INVALID_GRAPH_ID)); deoptimize.setMessage("invoke " + targetMethod.name()); append(deoptimize); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); @@ -1110,7 +1105,7 @@ ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), graphId))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), RiDeoptReason.JavaSubroutineMismatch, graphId))); if (!successor.jsrScope.equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); } @@ -1195,8 +1190,8 @@ private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1; - if (probability == 0 && config.useBranchPrediction()) { - return currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile, graphId)); + if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) { + return currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.UnreachedCode, graphId)); } else { return createTarget(block, stateAfter); } @@ -1337,7 +1332,7 @@ currentGraph.reduceDegenerateLoopBegin(begin); } else { // Delete unnecessary loop phi functions, i.e., phi functions where all inputs are either the same or the phi itself. - for (PhiNode phi : begin.stateAfter().values().filter(PhiNode.class).snapshot()) { + for (PhiNode phi : begin.phis().snapshot()) { checkRedundantPhi(phi); } } @@ -1400,13 +1395,13 @@ assert frameState.stackSize() == 1 : frameState; RiType catchType = block.handler.catchType(); - if (config.eagerResolving()) { + if (graphBuilderConfig.eagerResolving()) { catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF); } boolean initialized = (catchType instanceof RiResolvedType); - if (initialized && config.getSkippedExceptionTypes() != null) { + if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) { RiResolvedType resolvedCatchType = (RiResolvedType) catchType; - for (RiResolvedType skippedType : config.getSkippedExceptionTypes()) { + for (RiResolvedType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { initialized &= !resolvedCatchType.isSubtypeOf(skippedType); if (!initialized) { break; diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopInline.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopInline.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopInline.java Wed Mar 21 11:28:22 2012 +0100 @@ -24,9 +24,6 @@ import org.junit.*; -/* - * This test is meaningful only if you run it with 'forced' inlinning because running it in the harness with -Xcomp will not trigger any normal inlining - */ public class LoopInline { public static int test(int arg) { diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java Wed Mar 21 11:28:22 2012 +0100 @@ -23,10 +23,11 @@ package com.oracle.graal.cri; import com.oracle.graal.graph.*; +import com.oracle.max.cri.ri.*; public interface CiLoweringTool { GraalRuntime getRuntime(); Node getGuardAnchor(); - Node createGuard(Node condition, long leafGraphId); + Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -25,29 +25,21 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; @NodeInfo(shortName = "Deopt") public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { - public static enum DeoptAction { - None, // just interpret, do not invalidate nmethod - Recompile, // recompile the nmethod; need not invalidate - InvalidateReprofile, // invalidate the nmethod, reset IC, maybe recompile - InvalidateRecompile, // invalidate the nmethod, recompile (probably) - InvalidateStopCompiling, // invalidate the nmethod and do not compile - } - @Data private String message; - @Data private final DeoptAction action; + @Data private final RiDeoptAction action; + @Data private final RiDeoptReason reason; private final long leafGraphId; - public DeoptimizeNode() { - this(DeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID); - } - public DeoptimizeNode(DeoptAction action, long leafGraphId) { + public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason, long leafGraphId) { super(StampFactory.illegal()); this.action = action; + this.reason = reason; this.leafGraphId = leafGraphId; } @@ -59,17 +51,21 @@ return message; } - public DeoptAction action() { + public RiDeoptAction action() { return action; } + public RiDeoptReason reason() { + return reason; + } + public long leafGraphId() { return leafGraphId; } @Override public void generate(LIRGeneratorTool gen) { - gen.emitDeoptimize(action, message, leafGraphId); + gen.emitDeoptimize(action, reason, message, leafGraphId); } @NodeIntrinsic diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -24,25 +24,27 @@ import com.oracle.graal.cri.*; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType { @Input private final NodeInputList conditions; + @Data private final RiDeoptReason deoptReason; private final long leafGraphId; - public FixedGuardNode(BooleanNode condition, long leafGraphId) { + public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason, long leafGraphId) { super(StampFactory.illegal()); this.leafGraphId = leafGraphId; this.conditions = new NodeInputList<>(this, new BooleanNode[] {condition}); + this.deoptReason = deoptReason; } @Override public void generate(LIRGeneratorTool gen) { for (BooleanNode condition : conditions()) { - gen.emitGuardCheck(condition, leafGraphId); + gen.emitGuardCheck(condition, deoptReason, leafGraphId); } } @@ -66,7 +68,7 @@ if (next != null) { tool.deleteBranch(next); } - setNext(graph().add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, leafGraphId))); + setNext(graph().add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, deoptReason, leafGraphId))); return; } } @@ -80,7 +82,7 @@ public void lower(CiLoweringTool tool) { AnchorNode newAnchor = graph().add(new AnchorNode()); for (BooleanNode b : conditions) { - newAnchor.addGuard((GuardNode) tool.createGuard(b, leafGraphId)); + newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason, leafGraphId)); } ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Mar 21 11:28:22 2012 +0100 @@ -209,7 +209,7 @@ } else { popSlots = 1; } - assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind(); + assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind() || (stackAt(stackSize() - popSlots) instanceof BoxedVirtualObjectNode && popKind.isObject()); } int pushSlots = pushedValues.length; diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -27,11 +27,13 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.types.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, TypeFeedbackProvider, Node.IterableNodeType { @Input private BooleanNode condition; @Input(notDataflow = true) private FixedNode anchor; + @Data private RiDeoptReason reason; private final long leafGraphId; public FixedNode anchor() { @@ -55,16 +57,21 @@ condition = x; } - public GuardNode(BooleanNode condition, FixedNode anchor, long leafGraphId) { + public RiDeoptReason reason() { + return reason; + } + + public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason, long leafGraphId) { super(StampFactory.illegal()); this.condition = condition; this.anchor = anchor; + this.reason = reason; this.leafGraphId = leafGraphId; } @Override public void generate(LIRGeneratorTool gen) { - gen.emitGuardCheck(condition(), leafGraphId); + gen.emitGuardCheck(condition(), reason(), leafGraphId); } @Override diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -185,6 +185,11 @@ if (node == null) { assert kind() == CiKind.Void && usages().isEmpty(); ((StructuredGraph) graph()).removeSplit(this, NORMAL_EDGE); + } else if (node instanceof DeoptimizeNode) { + this.replaceAtPredecessors(node); + this.replaceAtUsages(null); + GraphUtil.killCFG(this); + return; } else { ((StructuredGraph) graph()).replaceSplit(this, node, NORMAL_EDGE); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; public class SafeReadNode extends SafeAccessNode implements Lowerable { @@ -39,7 +40,7 @@ @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), StructuredGraph.INVALID_GRAPH_ID); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID); ReadNode read = graph.add(new ReadNode(object(), location(), stamp())); read.setGuard(guard); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,12 +22,13 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.max.cri.ci.*; import com.oracle.graal.cri.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.max.cri.ci.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ri.*; public class SafeWriteNode extends SafeAccessNode implements Lowerable{ @@ -46,7 +47,7 @@ @Override public void lower(CiLoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), StructuredGraph.INVALID_GRAPH_ID); + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID); WriteNode write = graph.add(new WriteNode(object(), value(), location())); write.setGuard(guard); graph.replaceFixedWithFixed(this, write); diff -r 51111665eda6 -r ab038e0d6b43 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 Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,12 +22,12 @@ */ package com.oracle.graal.nodes.spi; -import com.oracle.max.cri.ci.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; public abstract class LIRGeneratorTool { public abstract CiTarget target(); @@ -79,13 +79,13 @@ public abstract CiValue emitConvert(ConvertNode.Op opcode, CiValue inputVal); public abstract void emitMembar(int barriers); - public abstract void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo); - public abstract void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId); + 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 void emitIf(IfNode i); public abstract void emitConditional(ConditionalNode i); - public abstract void emitGuardCheck(BooleanNode comp, long leafGraphId); + public abstract void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId); public abstract void emitLookupSwitch(LookupSwitchNode i); public abstract void emitTableSwitch(TableSwitchNode i); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Mar 21 11:28:22 2012 +0100 @@ -60,9 +60,8 @@ loopend.predecessor().replaceFirstSuccessor(loopend, null); loopend.safeDelete(); } - FixedNode next = begin.next(); + killCFG(begin.next()); begin.safeDelete(); - killCFG(next); } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore ((StructuredGraph) end.graph()).reduceDegenerateLoopBegin((LoopBeginNode) merge); } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Wed Mar 21 11:28:22 2012 +0100 @@ -297,6 +297,20 @@ assert false; } break; + case '\u0000': case '\u0001': case '\u0002': case '\u0003': + case '\u0004': case '\u0005': case '\u0006': case '\u0007': + case '\u0008': case '\u000b': case '\u000c': case '\u000e': + case '\u000f': case '\u0010': case '\u0011': case '\u0012': + case '\u0013': case '\u0014': case '\u0015': case '\u0016': + case '\u0017': case '\u0018': case '\u0019': case '\u001a': + case '\u001b': case '\u001c': case '\u001d': case '\u001e': + case '\u001f': + if (str == null) { + str = new StringBuilder(); + str.append(s, 0, i); + } + str.append("'0x").append(Integer.toHexString(c)); + break; default: if (str != null) { str.append(c); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,21 +22,20 @@ */ package com.oracle.graal.snippets; +import com.oracle.graal.compiler.*; +import com.oracle.graal.cri.*; import com.oracle.max.cri.ci.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.cri.*; /** * Definition of the snippets that are VM-independent and can be intrinsified by Graal in any VM. */ public class GraalIntrinsics { - public static void installIntrinsics(GraalRuntime runtime, CiTarget target, PhasePlan plan) { + public static void installIntrinsics(GraalRuntime runtime, CiTarget target) { if (GraalOptions.Intrinsify) { - Snippets.install(runtime, target, new MathSnippetsX86(), plan); - Snippets.install(runtime, target, new DoubleSnippets(), plan); - Snippets.install(runtime, target, new FloatSnippets(), plan); - Snippets.install(runtime, target, new NodeClassSnippets(), plan); + Snippets.install(runtime, target, new MathSnippetsX86()); + Snippets.install(runtime, target, new DoubleSnippets()); + Snippets.install(runtime, target, new FloatSnippets()); + Snippets.install(runtime, target, new NodeClassSnippets()); } } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java Wed Mar 21 11:28:22 2012 +0100 @@ -43,17 +43,17 @@ */ public class Snippets { - public static void install(GraalRuntime runtime, CiTarget target, SnippetsInterface obj, PhasePlan plan) { + public static void install(GraalRuntime runtime, CiTarget target, SnippetsInterface obj) { Class clazz = obj.getClass(); BoxingMethodPool pool = new BoxingMethodPool(runtime); if (clazz.isAnnotationPresent(ClassSubstitution.class)) { - installSubstitution(runtime, target, plan, clazz, pool, clazz.getAnnotation(ClassSubstitution.class).value()); + installSubstitution(runtime, target, clazz, pool, clazz.getAnnotation(ClassSubstitution.class).value()); } else { - installSnippets(runtime, target, plan, clazz, pool); + installSnippets(runtime, target, clazz, pool); } } - private static void installSnippets(GraalRuntime runtime, CiTarget target, PhasePlan plan, Class< ? extends SnippetsInterface> clazz, + private static void installSnippets(GraalRuntime runtime, CiTarget target, Class< ? extends SnippetsInterface> clazz, BoxingMethodPool pool) { for (Method snippet : clazz.getDeclaredMethods()) { int modifiers = snippet.getModifiers(); @@ -62,12 +62,12 @@ } RiResolvedMethod snippetRiMethod = runtime.getRiMethod(snippet); if (snippetRiMethod.compilerStorage().get(Graph.class) == null) { - buildSnippetGraph(snippetRiMethod, runtime, target, pool, plan); + buildSnippetGraph(snippetRiMethod, runtime, target, pool); } } } - private static void installSubstitution(GraalRuntime runtime, CiTarget target, PhasePlan plan, Class< ? extends SnippetsInterface> clazz, + private static void installSubstitution(GraalRuntime runtime, CiTarget target, Class< ? extends SnippetsInterface> clazz, BoxingMethodPool pool, Class original) throws GraalInternalError { for (Method snippet : clazz.getDeclaredMethods()) { try { @@ -80,7 +80,7 @@ throw new RuntimeException("Snippet must not be abstract or native"); } RiResolvedMethod snippetRiMethod = runtime.getRiMethod(snippet); - StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool, plan); + StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool); runtime.getRiMethod(method).compilerStorage().put(Graph.class, graph); } catch (NoSuchMethodException e) { throw new RuntimeException("Could not resolve method to substitute with: " + snippet.getName(), e); @@ -88,13 +88,13 @@ } } - private static StructuredGraph buildSnippetGraph(final RiResolvedMethod snippetRiMethod, final GraalRuntime runtime, final CiTarget target, final BoxingMethodPool pool, final PhasePlan plan) { + private static StructuredGraph buildSnippetGraph(final RiResolvedMethod snippetRiMethod, final GraalRuntime runtime, final CiTarget target, final BoxingMethodPool pool) { return Debug.scope("BuildSnippetGraph", snippetRiMethod, new Callable() { @Override public StructuredGraph call() throws Exception { GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); - GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config); + GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); StructuredGraph graph = new StructuredGraph(snippetRiMethod); graphBuilder.apply(graph); @@ -109,7 +109,7 @@ if (holder.isSubtypeOf(runtime.getType(SnippetsInterface.class))) { StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class); if (targetGraph == null) { - targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool, plan); + targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool); } InliningUtil.inline(invoke, targetGraph, true); if (GraalOptions.OptCanonicalizer) { diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -28,6 +28,7 @@ import org.junit.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.graal.debug.*; @@ -123,7 +124,8 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, phasePlan).apply(graph); + + new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); Debug.dump(graph, "Graph"); new BoxingEliminationPhase().apply(graph); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,13 +26,14 @@ import org.junit.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiCompiledMethod.MethodInvalidatedException; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiCompiledMethod.MethodInvalidatedException; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. Then @@ -78,7 +79,7 @@ Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); RiResolvedMethod riMethod = runtime.getRiMethod(method); StructuredGraph graph = new StructuredGraph(riMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault()).apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); new CanonicalizerPhase(null, runtime, null).apply(graph); new DeadCodeEliminationPhase().apply(graph); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -22,15 +22,16 @@ */ package com.oracle.graal.compiler.tests; -import junit.framework.*; +import junit.framework.Assert; import org.junit.Test; -import com.oracle.max.cri.ci.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.max.cri.ci.*; /** * In these test cases the probability of all invokes is set to a high value, such that an InliningPhase should inline them all. @@ -121,10 +122,10 @@ n.node().setProbability(100000); } - new InliningPhase(null, runtime(), null, null, getDefaultPhasePlan()).apply(graph); + new InliningPhase(null, runtime(), null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); Debug.dump(graph, "Graph"); - new EscapeAnalysisPhase(null, runtime(), null, getDefaultPhasePlan()).apply(graph); + new EscapeAnalysisPhase(null, runtime(), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); int retCount = 0; for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -50,7 +50,7 @@ } block = block.getDominator(); } - Assert.assertTrue(block == aBlock); + Assert.assertSame(block, aBlock); } } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -24,15 +24,16 @@ import java.lang.reflect.*; -import junit.framework.Assert; +import junit.framework.*; -import com.oracle.max.cri.ri.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.compiler.phases.PhasePlan.*; +import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.graal.cri.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.max.cri.ri.*; /** * Base class for Graal compiler unit tests. These are white box tests @@ -110,7 +111,7 @@ protected StructuredGraph parse(Method m) { RiResolvedMethod riMethod = runtime.getRiMethod(m); StructuredGraph graph = new StructuredGraph(riMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault()).apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL).apply(graph); return graph; } @@ -120,13 +121,13 @@ protected StructuredGraph parseProfiled(Method m) { RiResolvedMethod riMethod = runtime.getRiMethod(m); StructuredGraph graph = new StructuredGraph(riMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault()).apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph); return graph; } protected PhasePlan getDefaultPhasePlan() { PhasePlan plan = new PhasePlan(); - plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault())); + plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL)); return plan; } } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.graal.debug.*; @@ -84,7 +85,7 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, phasePlan).apply(graph); + new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new PhiStampPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.nodes.*; @@ -62,7 +63,7 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph); + new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new DeadCodeEliminationPhase().apply(graph); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -28,6 +28,7 @@ import org.junit.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -81,7 +82,7 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph); + new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java Wed Mar 21 11:28:22 2012 +0100 @@ -31,6 +31,7 @@ import org.junit.Assert; import org.junit.Test; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -93,7 +94,7 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph); + new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptAction.java Wed Mar 21 11:28:22 2012 +0100 @@ -0,0 +1,32 @@ +/* + * 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.max.cri.ri; + + +public enum RiDeoptAction { + None, // just interpret, do not invalidate nmethod + RecompileIfTooManyDeopts, // recompile the nmethod; need not invalidate + InvalidateReprofile, // invalidate the nmethod, reset IC, maybe recompile + InvalidateRecompile, // invalidate the nmethod, recompile (probably) + InvalidateStopCompiling; // invalidate the nmethod and do not compile +} diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptReason.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptReason.java Wed Mar 21 11:28:22 2012 +0100 @@ -0,0 +1,40 @@ +/* + * 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.max.cri.ri; + + +public enum RiDeoptReason { + None, + NullCheckException, + BoundsCheckException, + ClassCastException, + ArrayStoreException, + UnreachedCode, + TypeCheckedInliningViolated, + OptimizedTypeCheckViolated, + NotCompiledExceptionHandler, + Unresolved, + JavaSubroutineMismatch, + ArithmeticException, + RuntimeConstraint; +} diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java Wed Mar 21 11:28:22 2012 +0100 @@ -64,4 +64,12 @@ * @return the estimated execution count or -1 if not available. */ int getExecutionCount(int bci); + + /** + * Returns how frequently a method was deoptimized for the given deoptimization reason. This only indicates how + * often the method did fall back to the interpreter for the execution and does not indicate how often it was recompiled. + * @param reason the reason for which the number of deoptimizations should be queried + * @return the number of times the compiled method deoptimized for the given reason. + */ + int getDeoptimizationCount(RiDeoptReason reason); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java Wed Mar 21 10:47:02 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java Wed Mar 21 11:28:22 2012 +0100 @@ -195,4 +195,22 @@ * @return a reference to the compiled and ready-to-run code */ RiCompiledMethod addMethod(RiResolvedMethod method, CiTargetMethod code); + + /** + * Encodes a deoptimization action and a deoptimization reason in an integer value. + * @return the encoded value as an integer + */ + int encodeDeoptActionAndReason(RiDeoptAction action, RiDeoptReason reason); + + /** + * Converts a RiDeoptReason into an integer value. + * @return An integer value representing the given RiDeoptReason. + */ + int convertDeoptReason(RiDeoptReason reason); + + /** + * Converts a RiDeoptAction into an integer value. + * @return An integer value representing the given RiDeoptAction. + */ + int convertDeoptAction(RiDeoptAction action); } diff -r 51111665eda6 -r ab038e0d6b43 graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseProfilingInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseProfilingInfo.java Wed Mar 21 11:28:22 2012 +0100 @@ -0,0 +1,78 @@ +/* + * 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.max.criutils; + +import com.oracle.max.cri.ri.*; + + +/** + * Dummy profiling information in case that a method was not executed frequently enough so that + * no profiling information does exist yet, or in case that the profiling information should not be used. + */ +public final class BaseProfilingInfo implements RiProfilingInfo { + private static final RiProfilingInfo[] NO_PROFILING_INFO = new RiProfilingInfo[] { + new BaseProfilingInfo(RiExceptionSeen.TRUE), + new BaseProfilingInfo(RiExceptionSeen.FALSE), + new BaseProfilingInfo(RiExceptionSeen.NOT_SUPPORTED) + }; + + private final RiExceptionSeen exceptionSeen; + + BaseProfilingInfo(RiExceptionSeen exceptionSeen) { + this.exceptionSeen = exceptionSeen; + } + + @Override + public RiTypeProfile getTypeProfile(int bci) { + return null; + } + + @Override + public double getBranchTakenProbability(int bci) { + return -1; + } + + @Override + public double[] getSwitchProbabilities(int bci) { + return null; + } + + @Override + public RiExceptionSeen getExceptionSeen(int bci) { + return exceptionSeen; + } + + @Override + public int getExecutionCount(int bci) { + return -1; + } + + public static RiProfilingInfo get(RiExceptionSeen exceptionSeen) { + return NO_PROFILING_INFO[exceptionSeen.ordinal()]; + } + + @Override + public int getDeoptimizationCount(RiDeoptReason reason) { + return 0; + } +} diff -r 51111665eda6 -r ab038e0d6b43 hotspot/.cproject --- a/hotspot/.cproject Wed Mar 21 10:47:02 2012 +0100 +++ b/hotspot/.cproject Wed Mar 21 11:28:22 2012 +0100 @@ -20,7 +20,7 @@ - + @@ -80,6 +80,7 @@ + diff -r 51111665eda6 -r ab038e0d6b43 hotspot/.project --- a/hotspot/.project Wed Mar 21 10:47:02 2012 +0100 +++ b/hotspot/.project Wed Mar 21 11:28:22 2012 +0100 @@ -23,7 +23,7 @@ org.eclipse.cdt.make.core.autoBuildTarget - debug + ide-build-target org.eclipse.cdt.make.core.buildArguments diff -r 51111665eda6 -r ab038e0d6b43 mx/commands.py --- a/mx/commands.py Wed Mar 21 10:47:02 2012 +0100 +++ b/mx/commands.py Wed Mar 21 11:28:22 2012 +0100 @@ -384,6 +384,12 @@ log.close() return ret +def jdkhome(args, vm=None): + """prints the JDK directory selected for the 'vm' command""" + + build = _vmbuild if _vmSourcesAvailable else 'product' + print join(_graal_home, 'jdk' + mx.java().version, build) + def build(args, vm=None): """build the VM binary @@ -414,6 +420,12 @@ buildSuffix = 'graal' for build in builds: + if build == 'ide-build-target': + build = os.environ.get('IDE_BUILD_TARGET', 'product') + if len(build) == 0: + mx.log('[skipping build from IDE as IDE_BUILD_TARGET environment variable is ""]') + continue + jdk = _jdk(build, create=True) vmDir = join(_vmLibDirInJdk(jdk), vm) @@ -751,9 +763,19 @@ def gv(args): """run the Graal Visualizer""" with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp: - mx.log('[Graal Visualizer output is in ' + fp.name + ']') + mx.log('[Graal Visualizer log is in ' + fp.name + ']') + if not exists(join(_graal_home, 'visualizer', 'build.xml')): + mx.log('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run']) +def igv(args): + """run the Ideal Graph Visualizer""" + with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp: + mx.log('[Ideal Graph Visualizer log is in ' + fp.name + ']') + if not exists(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')): + mx.log('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') + mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run']) + def bench(args): """run benchmarks and parse their output for results @@ -876,11 +898,13 @@ 'buildvms': [buildvms, '[-options]'], 'clean': [clean, ''], 'hsdis': [hsdis, '[att]'], + 'igv' : [igv, ''], 'intro': [intro, ''], + 'jdkhome': [jdkhome, ''], 'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'], 'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'], 'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'], - 'example': [example, '[-v] example names...'], + #'example': [example, '[-v] example names...'], 'gate' : [gate, '[-options]'], 'gv' : [gv, ''], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], diff -r 51111665eda6 -r ab038e0d6b43 mxtool/mx.py --- a/mxtool/mx.py Wed Mar 21 10:47:02 2012 +0100 +++ b/mxtool/mx.py Wed Mar 21 11:28:22 2012 +0100 @@ -510,6 +510,7 @@ ArgumentParser.__init__(self, prog='mx') self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output') + self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output') self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on for a debugger', metavar='') self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"') self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='') @@ -536,6 +537,9 @@ opts.__dict__.setdefault('timeout', 0) opts.__dict__.setdefault('ptimeout', 0) + if opts.very_verbose: + opts.verbose = True + if opts.java_home is None: opts.java_home = os.environ.get('JAVA_HOME') @@ -640,6 +644,10 @@ assert isinstance(arg, types.StringTypes), 'argument is not a string: ' + str(arg) if _opts.verbose: + if _opts.very_verbose: + log('Environment variables:') + for key in sorted(os.environ.keys()): + log(' ' + key + '=' + os.environ[key]) log(' '.join(args)) if timeout is None and _opts.ptimeout != 0: @@ -697,7 +705,10 @@ if retcode and nonZeroIsFatal: if _opts.verbose: - raise subprocess.CalledProcessError(retcode, ' '.join(args)) + if _opts.very_verbose: + raise subprocess.CalledProcessError(retcode, ' '.join(args)) + else: + log('[exit code: ' + str(retcode)+ ']') abort(retcode) return retcode diff -r 51111665eda6 -r ab038e0d6b43 src/cpu/x86/vm/c1_Runtime1_x86.cpp --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -97,12 +97,23 @@ if (oop_result2->is_valid()) { movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); } +#ifdef GRAAL // (thomaswue) Deoptimize in case of an exception. restore_live_registers(this, false); movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); leave(); - movl(rscratch1, 2); // InvalidateRecompile + movl(rscratch1, Deoptimization::make_trap_request(Deoptimization::Reason_constraint, Deoptimization::Action_reinterpret)); jump(RuntimeAddress(SharedRuntime::deopt_blob()->uncommon_trap())); +#else + if (frame_size() == no_frame_size) { + leave(); + jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + } else if (_stub_id == Runtime1::forward_exception_id) { + should_not_reach_here(); + } else { + jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); + } +#endif bind(L); } // get oop results if there are any and reset the values in the thread diff -r 51111665eda6 -r ab038e0d6b43 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -3015,9 +3015,9 @@ #ifdef GRAAL __ jmp(cont); - int jmp_uncommon_trap_offset = __ pc() - start; + int implicit_exception_uncommon_trap_offset = __ pc() - start; __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset()))); - __ movptr(rscratch1, 2); // InvalidateRecompile + __ movptr(rscratch1, Address(r15_thread, in_bytes(JavaThread::ScratchB_offset()))); int uncommon_trap_offset = __ pc() - start; @@ -3028,8 +3028,7 @@ assert(r10 == rscratch1, "scratch register should be r10"); __ movl(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes())); - __ orq(c_rarg1, ~(int32_t)Deoptimization::make_trap_request(Deoptimization::Reason_unreached, Deoptimization::Action_none)); - __ notq(c_rarg1); + __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute); __ mov(c_rarg0, r15_thread); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); @@ -3039,7 +3038,7 @@ Label after_fetch_unroll_info_call; __ jmp(after_fetch_unroll_info_call); -#endif +#endif // GRAAL __ bind(cont); @@ -3245,7 +3244,7 @@ _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); #ifdef GRAAL _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset); - _deopt_blob->set_jmp_uncommon_trap_offset(jmp_uncommon_trap_offset); + _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset); #endif } diff -r 51111665eda6 -r ab038e0d6b43 src/share/tools/IdealGraphVisualizer/nbproject/platform.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Wed Mar 21 11:28:22 2012 +0100 @@ -1,3 +1,11 @@ +nbplatform.active=default +bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar +autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.1.1/uc/final/distribution/catalog.xml.gz +suite.dir=${basedir} +nbplatform.active.dir=${suite.dir}/nbplatform +nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform +nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness +harness.dir=${nbplatform.active.dir}/harness cluster.path=\ ${nbplatform.active.dir}/ide:\ ${nbplatform.active.dir}/platform @@ -201,4 +209,4 @@ # org.netbeans.core.netigso,\ # org.netbeans.libs.felix,\ # org.netbeans.libs.osgi,\ -nbplatform.active=default + diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/c1/c1_Runtime1.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -169,7 +169,7 @@ RegisterMap reg_map(thread, false); frame runtime_frame = thread->last_frame(); frame caller_frame = runtime_frame.sender(®_map); - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); assert(caller_is_deopted(), "Must be deoptimized"); } } @@ -434,7 +434,7 @@ if (osr_nm != NULL) { RegisterMap map(thread, false); frame fr = thread->last_frame().sender(&map); - Deoptimization::deoptimize_frame(thread, fr.id()); + Deoptimization::deoptimize_frame(thread, fr.id(), Deoptimization::Reason_constraint); } JRT_BLOCK_END return NULL; @@ -505,7 +505,7 @@ // We don't really want to deoptimize the nmethod itself since we // can actually continue in the exception handler ourselves but I // don't see an easy way to have the desired effect. - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); assert(caller_is_deopted(), "Must be deoptimized"); return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); @@ -763,7 +763,7 @@ assert(CodeCache::find_nmethod(caller_frame.pc()) != NULL, "sanity"); // Deoptimize the caller frame. - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); // Return to the now deoptimized frame. JRT_END @@ -975,7 +975,7 @@ nm->make_not_entrant(); } - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); // Return to the now deoptimized frame. } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/code/codeBlob.hpp --- a/src/share/vm/code/codeBlob.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/code/codeBlob.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -407,7 +407,7 @@ // (thomaswue) Offset when graal calls uncommon_trap. int _uncommon_trap_offset; - int _jmp_uncommon_trap_offset; + int _implicit_exception_uncommon_trap_offset; // Creation support @@ -469,11 +469,11 @@ assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob"); } address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; } - void set_jmp_uncommon_trap_offset(int offset) { - _jmp_uncommon_trap_offset = offset; - assert(contains(code_begin() + _jmp_uncommon_trap_offset), "must be PC inside codeblob"); + void set_implicit_exception_uncommon_trap_offset(int offset) { + _implicit_exception_uncommon_trap_offset = offset; + assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob"); } - address jmp_uncommon_trap() const { return code_begin() + _jmp_uncommon_trap_offset; } + address implicit_exception_uncommon_trap() const { return code_begin() + _implicit_exception_uncommon_trap_offset; } }; diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/code/nmethod.hpp --- a/src/share/vm/code/nmethod.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/code/nmethod.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -596,7 +596,7 @@ // (thomaswue) When using graal, the address might be off by 5 (because this is the size of the call instruction. // (thomaswue) TODO: Replace this by a more general mechanism. - bool is_deopt_entry (address pc) { return pc == deopt_handler_begin() IS_GRAAL( || pc == deopt_handler_begin() + 5); } + bool is_deopt_entry (address pc) { return pc == deopt_handler_begin() GRAAL_ONLY( || pc == deopt_handler_begin() + 5); } bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); } // Accessor/mutator for the original pc of a frame before a frame was deopted. address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -179,6 +179,7 @@ oop type = CiVirtualObject::type(value); int id = CiVirtualObject::id(value); klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)); + bool isLongArray = klass == Universe::longArrayKlassObj(); for (jint i = 0; i < objects->length(); i++) { ObjectValue* obj = (ObjectValue*) objects->at(i); @@ -198,6 +199,17 @@ ScopeValue* cur_second = NULL; ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second); + if (isLongArray && cur_second == NULL) { + // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. + // add an int 0 constant +#ifdef BIG_ENDIAN + cur_second = value; + value = new ConstantIntValue(0); +#else + cur_second = new ConstantIntValue(0); +#endif + } + if (cur_second != NULL) { sv->field_values()->append(cur_second); } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -319,7 +319,7 @@ HotSpotMethodResolved::set_accessFlags(obj, method->access_flags().as_int()); HotSpotMethodResolved::set_maxLocals(obj, method->max_locals()); HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack()); - HotSpotMethodResolved::set_canBeInlined(obj, !CompilerOracle::should_not_inline(method)); + HotSpotMethodResolved::set_canBeInlined(obj, !method->is_not_compilable() && !CompilerOracle::should_not_inline(method)); method->set_graal_mirror(obj()); return obj; diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -775,6 +775,7 @@ set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset())); set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset())); + set_int(env, config, "methodDataOopTrapHistoryOffset", in_bytes(methodDataOopDesc::trap_history_offset())); set_int(env, config, "dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); set_int(env, config, "dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); set_int(env, config, "dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/oops/methodDataOop.hpp --- a/src/share/vm/oops/methodDataOop.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/oops/methodDataOop.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -1206,7 +1206,11 @@ // Whole-method sticky bits and flags public: enum { +#ifdef GRAAL + _trap_hist_limit = 13, // decoupled from Deoptimization::Reason_LIMIT +#else _trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT +#endif _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values @@ -1481,17 +1485,13 @@ uint inc_trap_count(int reason) { // Count another trap, anywhere in this method. assert(reason >= 0, "must be single trap"); - if ((uint)reason < _trap_hist_limit) { - uint cnt1 = 1 + _trap_hist._array[reason]; - if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow... - _trap_hist._array[reason] = cnt1; - return cnt1; - } else { - return _trap_hist_mask + (++_nof_overflow_traps); - } + assert((uint)reason < _trap_hist_limit, "oob"); + uint cnt1 = 1 + _trap_hist._array[reason]; + if ((cnt1 & _trap_hist_mask) != 0) { // if no counter overflow... + _trap_hist._array[reason] = cnt1; + return cnt1; } else { - // Could not represent the count in the histogram. - return (++_nof_overflow_traps); + return _trap_hist_mask + (++_nof_overflow_traps); } } @@ -1514,6 +1514,10 @@ return byte_offset_of(methodDataOopDesc, _data[0]); } + static ByteSize trap_history_offset() { + return byte_offset_of(methodDataOopDesc, _trap_hist._array); + } + static ByteSize invocation_counter_offset() { return byte_offset_of(methodDataOopDesc, _invocation_counter); } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/oops/methodOop.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -51,6 +51,9 @@ #include "runtime/signature.hpp" #include "utilities/quickSort.hpp" #include "utilities/xmlstream.hpp" +#ifdef GRAAL +#include "graal/graalJavaAccess.hpp" +#endif // Implementation of methodOopDesc @@ -658,6 +661,13 @@ } } CompilationPolicy::policy()->disable_compilation(this); + +#ifdef GRAAL + oop graal_mirror = this->graal_mirror(); + if (graal_mirror != NULL) { + HotSpotMethodResolved::set_canBeInlined(graal_mirror, false); + } +#endif } // Revert to using the interpreter and clear out the nmethod diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/opto/runtime.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -1149,7 +1149,7 @@ frame caller_frame = stub_frame.sender(®_map); // Deoptimize the caller frame. - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); } } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/prims/jvmtiEnv.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -1457,7 +1457,7 @@ // If any of the top 2 frames is a compiled one, need to deoptimize it for (int i = 0; i < 2; i++) { if (!is_interpreted[i]) { - Deoptimization::deoptimize_frame(java_thread, frame_sp[i]); + Deoptimization::deoptimize_frame(java_thread, frame_sp[i], Deoptimization::Reason_constraint); } } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -1340,7 +1340,7 @@ if (!vf->fr().can_be_deoptimized()) { return JVMTI_ERROR_OPAQUE_FRAME; } - Deoptimization::deoptimize_frame(java_thread, jvf->fr().id()); + Deoptimization::deoptimize_frame(java_thread, jvf->fr().id(), Deoptimization::Reason_constraint); } // Get information about method return type diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/prims/jvmtiImpl.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -767,7 +767,7 @@ // Schedule deoptimization so that eventually the local // update will be written to an interpreter frame. - Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id()); + Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id(), Deoptimization::Reason_constraint); // Now store a new value for the local which will be applied // once deoptimization occurs. Note however that while this diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/arguments.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -2127,7 +2127,7 @@ } if (PrintVMOptions) tty->print_cr("GRAAL=%s", graal_dir); - SysClassPath scp_compiler(Arguments::get_sysclasspath()); + SysClassPath scp_compiler(""); struct dirent* dentry; char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(graal_dir)); errno = 0; diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/compilationPolicy.hpp --- a/src/share/vm/runtime/compilationPolicy.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/compilationPolicy.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -118,7 +118,7 @@ // StackWalkCompPolicy - existing C2 policy -//#ifdef COMPILER2 +#if defined(COMPILER2) || defined(GRAAL) class StackWalkCompPolicy : public NonTieredCompPolicy { public: virtual void method_invocation_event(methodHandle m, JavaThread* thread); @@ -138,6 +138,6 @@ // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg }; -//#endif +#endif #endif // SHARE_VM_RUNTIME_COMPILATIONPOLICY_HPP diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -1151,17 +1151,17 @@ } -void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr) { +void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deoptimization::DeoptReason reason) { assert(fr.can_be_deoptimized(), "checking frame type"); - gather_statistics(Reason_constraint, Action_none, Bytecodes::_illegal); + gather_statistics(reason, Action_none, Bytecodes::_illegal); // Patch the nmethod so that when execution returns to it we will // deopt the execution state and return to the interpreter. fr.deoptimize(thread); } -void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map) { +void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) { // Deoptimize only if the frame comes from compile code. // Do not deoptimize the frame which is already patched // during the execution of the loops below. @@ -1173,12 +1173,12 @@ if (UseBiasedLocking) { revoke_biases_of_monitors(thread, fr, map); } - deoptimize_single_frame(thread, fr); + deoptimize_single_frame(thread, fr, reason); } -void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id) { +void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason) { assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(), "can only deoptimize other thread at a safepoint"); // Compute frame and register map based on thread and sp. @@ -1187,15 +1187,15 @@ while (fr.id() != id) { fr = fr.sender(®_map); } - deoptimize(thread, fr, ®_map); + deoptimize(thread, fr, ®_map, reason); } -void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) { +void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason) { if (thread == Thread::current()) { - Deoptimization::deoptimize_frame_internal(thread, id); + Deoptimization::deoptimize_frame_internal(thread, id, reason); } else { - VM_DeoptimizeFrame deopt(thread, id); + VM_DeoptimizeFrame deopt(thread, id, reason); VMThread::execute(&deopt); } } @@ -1520,7 +1520,7 @@ uint this_trap_count = 0; bool maybe_prior_trap = false; bool maybe_prior_recompile = false; - pdata = query_update_method_data(trap_mdo, trap_bci, reason, + pdata = query_update_method_data(trap_mdo, trap_bci, reason, true, //outputs: this_trap_count, maybe_prior_trap, @@ -1654,25 +1654,31 @@ Deoptimization::query_update_method_data(methodDataHandle trap_mdo, int trap_bci, Deoptimization::DeoptReason reason, + bool update_total_trap_count, //outputs: uint& ret_this_trap_count, bool& ret_maybe_prior_trap, bool& ret_maybe_prior_recompile) { - uint prior_trap_count = trap_mdo->trap_count(reason); - uint this_trap_count = trap_mdo->inc_trap_count(reason); + bool maybe_prior_trap = false; + bool maybe_prior_recompile = false; + uint this_trap_count = 0; + if (update_total_trap_count) { + uint prior_trap_count = trap_mdo->trap_count(reason); + this_trap_count = trap_mdo->inc_trap_count(reason); - // If the runtime cannot find a place to store trap history, - // it is estimated based on the general condition of the method. - // If the method has ever been recompiled, or has ever incurred - // a trap with the present reason , then this BCI is assumed - // (pessimistically) to be the culprit. - bool maybe_prior_trap = (prior_trap_count != 0); - bool maybe_prior_recompile = (trap_mdo->decompile_count() != 0); - ProfileData* pdata = NULL; - + // If the runtime cannot find a place to store trap history, + // it is estimated based on the general condition of the method. + // If the method has ever been recompiled, or has ever incurred + // a trap with the present reason , then this BCI is assumed + // (pessimistically) to be the culprit. + maybe_prior_trap = (prior_trap_count != 0); + maybe_prior_recompile = (trap_mdo->decompile_count() != 0); + } // For reasons which are recorded per bytecode, we check per-BCI data. + ProfileData* pdata = NULL; DeoptReason per_bc_reason = reason_recorded_per_bytecode_if_any(reason); + assert(per_bc_reason != Reason_none || update_total_trap_count, "must be"); if (per_bc_reason != Reason_none) { // Find the profile data for this BCI. If there isn't one, // try to allocate one from the MDO's set of spares. @@ -1717,8 +1723,11 @@ uint ignore_this_trap_count; bool ignore_maybe_prior_trap; bool ignore_maybe_prior_recompile; + // Graal uses the total counts to determine if deoptimizations are happening too frequently -> do not adjust total counts + bool update_total_counts = GRAAL_ONLY(false) NOT_GRAAL(true); query_update_method_data(trap_mdo, trap_bci, (DeoptReason)reason, + update_total_counts, ignore_this_trap_count, ignore_maybe_prior_trap, ignore_maybe_prior_recompile); @@ -1831,6 +1840,21 @@ Deoptimization::DeoptAction Deoptimization::_unloaded_action = Deoptimization::Action_reinterpret; const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = { +#ifdef GRAAL + "none", + "null_check", + "range_check", + "class_check", + "array_check", + "unreached", + "type_checked_inlining", + "optimized_type_check", + "not_compiled_exception_handler", + "unresolved", + "jsr_mismatch", + "div0_check", + "constraint" +#else // Note: Keep this in sync. with enum DeoptReason. "none", "null_check", @@ -1849,6 +1873,7 @@ "age", "predicate", "loop_limit_check" +#endif }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/deoptimization.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -37,8 +37,35 @@ friend class VMStructs; public: - // What condition caused the deoptimization? + // What condition caused the deoptimization enum DeoptReason { +#ifdef GRAAL + Reason_many = -1, // indicates presence of several reasons + Reason_none = 0, // indicates absence of a relevant deopt. + // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits. + // This is more complicated for Graal as Graal may deoptimize to *some* bytecode before the + // bytecode that actually caused the deopt (with inlining, Graal may even deoptimize to a + // bytecode in another method): + // - bytecode y in method b() causes deopt + // - Graal deoptimizes to bytecode x in method a() + // -> the deopt reason will be recorded for method a() at bytecode x + Reason_null_check, + Reason_range_check, + Reason_class_check, + Reason_array_check, + Reason_unreached, + Reason_type_checked_inlining, + Reason_optimized_type_check, + + // recorded per method + Reason_not_compiled_exception_handler, + Reason_unresolved, + Reason_jsr_mismatch, + Reason_div0_check, + Reason_constraint, + Reason_LIMIT, + Reason_RECORDED_LIMIT = Reason_optimized_type_check +#else Reason_many = -1, // indicates presence of several reasons Reason_none = 0, // indicates absence of a relevant deopt. // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits @@ -50,7 +77,7 @@ Reason_intrinsic, // saw unexpected operand to intrinsic (@bci) Reason_bimorphic, // saw unexpected object class in bimorphic inlining (@bci) - Reason_unloaded, // unloaded class or constant pool entry + Reason_unloaded, // unloaded or class constant pool entry Reason_uninitialized, // bad class state (uninitialized) Reason_unreached, // code is not reached, compiler Reason_unhandled, // arbitrary compiler limitation @@ -60,12 +87,13 @@ Reason_predicate, // compiler generated predicate failed Reason_loop_limit_check, // compiler generated loop limits check failed Reason_LIMIT, + Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc +#endif // Note: Keep this enum in sync. with _trap_reason_name. - Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc // Note: Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of // DataLayout::trap_bits. This dependency is enforced indirectly // via asserts, to avoid excessive direct header-to-header dependencies. - // See Deoptimization::trap_state_reason and class DataLayout. + // See Deoptimization::trap_state_reason and class DataLayout }; // What action must be taken by the runtime? @@ -99,11 +127,11 @@ static int deoptimize_dependents(); // Deoptimizes a frame lazily. nmethod gets patched deopt happens on return to the frame - static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map); + static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map, DeoptReason reason); private: // Does the actual work for deoptimizing a single frame - static void deoptimize_single_frame(JavaThread* thread, frame fr); + static void deoptimize_single_frame(JavaThread* thread, frame fr, DeoptReason reason); // Helper function to revoke biases of all monitors in frame if UseBiasedLocking // is enabled @@ -233,11 +261,11 @@ // Only called from VMDeoptimizeFrame // @argument thread. Thread where stub_frame resides. // @argument id. id of frame that should be deoptimized. - static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id); + static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason); - // If thread is not the current thread then execute + // if thread is not the current thread then execute // VM_DeoptimizeFrame otherwise deoptimize directly. - static void deoptimize_frame(JavaThread* thread, intptr_t* id); + static void deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason); // Statistics static void gather_statistics(DeoptReason reason, DeoptAction action, @@ -251,37 +279,60 @@ // trap_request codes static DeoptReason trap_request_reason(int trap_request) { - if (trap_request < 0) + if (trap_request < 0) { return (DeoptReason) ((~(trap_request) >> _reason_shift) & right_n_bits(_reason_bits)); - else + } else { +#ifdef GRAAL + ShouldNotReachHere(); + return Reason_none; +#else // standard reason for unloaded CP entry return Reason_unloaded; +#endif // GRAAL + } } static DeoptAction trap_request_action(int trap_request) { - if (trap_request < 0) + if (trap_request < 0) { return (DeoptAction) ((~(trap_request) >> _action_shift) & right_n_bits(_action_bits)); - else + } else { +#ifdef GRAAL + ShouldNotReachHere(); + return Action_make_not_compilable; +#else // standard action for unloaded CP entry return _unloaded_action; +#endif // GRAAL + } } static int trap_request_index(int trap_request) { - if (trap_request < 0) + if (trap_request < 0) { return -1; - else + } else { +#ifdef GRAAL + ShouldNotReachHere(); + return -1; +#else return trap_request; +#endif // GRAAL + } } static int make_trap_request(DeoptReason reason, DeoptAction action, int index = -1) { +#ifdef GRAAL + assert(index == -1, "Graal does not use index"); +#endif + assert((1 << _reason_bits) >= Reason_LIMIT, "enough bits"); assert((1 << _action_bits) >= Action_LIMIT, "enough bits"); int trap_request; - if (index != -1) + if (index != -1) { trap_request = index; - else + } else { trap_request = (~(((reason) << _reason_shift) + ((action) << _action_shift))); + } assert(reason == trap_request_reason(trap_request), "valid reason"); assert(action == trap_request_action(trap_request), "valid action"); assert(index == trap_request_index(trap_request), "valid index"); @@ -337,6 +388,7 @@ static ProfileData* query_update_method_data(methodDataHandle trap_mdo, int trap_bci, DeoptReason reason, + bool update_total_trap_count, //outputs: uint& ret_this_trap_count, bool& ret_maybe_prior_trap, diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/safepoint.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -1060,7 +1060,7 @@ // as otherwise we may never deliver it. if (thread()->has_async_condition()) { ThreadInVMfromJavaNoAsyncException __tiv(thread()); - Deoptimization::deoptimize_frame(thread(), caller_fr.id()); + Deoptimization::deoptimize_frame(thread(), caller_fr.id(), Deoptimization::Reason_constraint); } // If an exception has been installed we must check for a pending deoptimization diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -665,7 +665,7 @@ RegisterMap reg_map(thread); frame runtime_frame = thread->last_frame(); frame caller_frame = runtime_frame.sender(®_map); - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_not_compiled_exception_handler); return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); } @@ -789,14 +789,17 @@ throw_and_post_jvmti_exception(thread, exception); JRT_END -address SharedRuntime::deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm) -{ +#ifdef GRAAL +address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) { + assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason"); if (TraceSignals) { tty->print_cr(err_msg("Deoptimizing on implicit exception at relative pc=%d in method %s", pc - nm->entry_point(), nm->method()->name()->as_C_string())); } thread->_ScratchA = (intptr_t)pc; - return (SharedRuntime::deopt_blob()->jmp_uncommon_trap()); + thread->_ScratchB = Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret); + return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap()); } +#endif JRT_ENTRY(void, SharedRuntime::throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual)) assert(thread == JavaThread::current() && required->is_oop() && actual->is_oop(), "bad args"); @@ -891,7 +894,7 @@ _implicit_null_throws++; #endif #ifdef GRAAL - target_pc = deoptimization_continuation(thread, pc, nm); + target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check); #else target_pc = nm->continuation_for_implicit_exception(pc); #endif @@ -914,7 +917,7 @@ if (TraceSignals) { tty->print_cr("graal implicit div0"); } - target_pc = deoptimization_continuation(thread, pc, nm); + target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); #else target_pc = nm->continuation_for_implicit_exception(pc); #endif diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/sharedRuntime.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -187,11 +187,13 @@ static void throw_NullPointerException(JavaThread* thread); static void throw_NullPointerException_at_call(JavaThread* thread); static void throw_StackOverflowError(JavaThread* thread); - static address deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm); static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual); static address continuation_for_implicit_exception(JavaThread* thread, address faulting_pc, ImplicitExceptionKind exception_kind); +#ifdef GRAAL + static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason); +#endif // Shared stub locations static address get_poll_stub(address pc); diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/thread.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -2058,7 +2058,7 @@ RegisterMap reg_map(this, UseBiasedLocking); frame compiled_frame = f.sender(®_map); if (compiled_frame.can_be_deoptimized()) { - Deoptimization::deoptimize(this, compiled_frame, ®_map); + Deoptimization::deoptimize(this, compiled_frame, ®_map, Deoptimization::Reason_constraint); } } } @@ -2490,7 +2490,7 @@ trace_frames(); trace_stack(); } - Deoptimization::deoptimize(this, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(this, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint); } } @@ -2520,7 +2520,7 @@ StackFrameStream fst(this, UseBiasedLocking); for(; !fst.is_done(); fst.next()) { if (fst.current()->should_be_deoptimized()) { - Deoptimization::deoptimize(this, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(this, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint); } } } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -2452,26 +2452,32 @@ declare_constant(Location::on_stack) \ declare_constant(Location::in_register) \ \ - declare_constant(Deoptimization::Reason_many) \ - declare_constant(Deoptimization::Reason_none) \ - declare_constant(Deoptimization::Reason_null_check) \ - declare_constant(Deoptimization::Reason_null_assert) \ - declare_constant(Deoptimization::Reason_range_check) \ - declare_constant(Deoptimization::Reason_class_check) \ - declare_constant(Deoptimization::Reason_array_check) \ - declare_constant(Deoptimization::Reason_intrinsic) \ - declare_constant(Deoptimization::Reason_bimorphic) \ - declare_constant(Deoptimization::Reason_unloaded) \ - declare_constant(Deoptimization::Reason_uninitialized) \ - declare_constant(Deoptimization::Reason_unreached) \ - declare_constant(Deoptimization::Reason_unhandled) \ - declare_constant(Deoptimization::Reason_constraint) \ - declare_constant(Deoptimization::Reason_div0_check) \ - declare_constant(Deoptimization::Reason_age) \ - declare_constant(Deoptimization::Reason_predicate) \ - declare_constant(Deoptimization::Reason_loop_limit_check) \ - declare_constant(Deoptimization::Reason_LIMIT) \ - declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ + /* TODO (chaeubl) those constants should be graal/c1/c2 specific */ \ + /*declare_constant(Deoptimization::Reason_many)*/ \ + /*declare_constant(Deoptimization::Reason_none)*/ \ + /*declare_constant(Deoptimization::Reason_null_check)*/ \ + /*declare_constant(Deoptimization::Reason_range_check)*/ \ + /*declare_constant(Deoptimization::Reason_class_check)*/ \ + /*declare_constant(Deoptimization::Reason_array_check)*/ \ + /*declare_constant(Deoptimization::Reason_unreached)*/ \ + /*declare_constant(Deoptimization::Reason_constraint)*/ \ + /*declare_constant(Deoptimization::Reason_div0_check)*/ \ + /*declare_constant(Deoptimization::Reason_type_checked_inlining)*/ \ + /*declare_constant(Deoptimization::Reason_optimized_type_check)*/ \ + /*declare_constant(Deoptimization::Reason_not_compiled_exception_handler)*/ \ + /*declare_constant(Deoptimization::Reason_unresolved)*/ \ + /*declare_constant(Deoptimization::Reason_jsr_mismatch)*/ \ + /*declare_constant(Deoptimization::Reason_LIMIT)*/ \ + /*declare_constant(Deoptimization::Reason_RECORDED_LIMIT)*/ \ + /*declare_constant(Deoptimization::Reason_null_assert)*/ \ + /*declare_constant(Deoptimization::Reason_intrinsic)*/ \ + /*declare_constant(Deoptimization::Reason_bimorphic)*/ \ + /*declare_constant(Deoptimization::Reason_unloaded)*/ \ + /*declare_constant(Deoptimization::Reason_uninitialized) */ \ + /*declare_constant(Deoptimization::Reason_unhandled)*/ \ + /*declare_constant(Deoptimization::Reason_age)*/ \ + /*declare_constant(Deoptimization::Reason_predicate)*/ \ + /*declare_constant(Deoptimization::Reason_loop_limit_check)*/ \ \ /*********************/ \ /* Matcher (C2 only) */ \ diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/vm_operations.cpp --- a/src/share/vm/runtime/vm_operations.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/vm_operations.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -117,14 +117,16 @@ } -VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id) { +VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason) { _thread = thread; _id = id; + _reason = reason; } void VM_DeoptimizeFrame::doit() { - Deoptimization::deoptimize_frame_internal(_thread, _id); + assert(_reason > Deoptimization::Reason_none && _reason < Deoptimization::Reason_LIMIT, "invalid deopt reason"); + Deoptimization::deoptimize_frame_internal(_thread, _id, (Deoptimization::DeoptReason)_reason); } @@ -156,7 +158,7 @@ if (fst.current()->can_be_deoptimized()) { if (fcount++ == fnum) { fcount = 0; - Deoptimization::deoptimize(thread, *fst.current(), fst.register_map()); + Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint); } } } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/runtime/vm_operations.hpp --- a/src/share/vm/runtime/vm_operations.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/runtime/vm_operations.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -251,7 +251,8 @@ private: JavaThread* _thread; intptr_t* _id; - VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id); + int _reason; + VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason); public: VMOp_Type type() const { return VMOp_DeoptimizeFrame; } diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/utilities/macros.hpp --- a/src/share/vm/utilities/macros.hpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/utilities/macros.hpp Wed Mar 21 11:28:22 2012 +0100 @@ -75,9 +75,11 @@ #endif // COMPILER2 #ifdef GRAAL -#define IS_GRAAL(code) code +#define GRAAL_ONLY(code...) code +#define NOT_GRAAL(code) #else -#define IS_GRAAL(code) +#define GRAAL_ONLY(code...) +#define NOT_GRAAL(code) code #endif #ifdef TIERED @@ -258,14 +260,6 @@ #define NOT_EMBEDDED(code) code #endif -#ifdef GRAAL -#define GRAAL_ONLY(code...) code -#define NOT_GRAAL(code...) -#else -#define GRAAL_ONLY(code...) -#define NOT_GRAAL(code...) code -#endif - #define define_pd_global(type, name, value) const type pd_##name = value; #endif // SHARE_VM_UTILITIES_MACROS_HPP diff -r 51111665eda6 -r ab038e0d6b43 src/share/vm/utilities/ostream.cpp --- a/src/share/vm/utilities/ostream.cpp Wed Mar 21 10:47:02 2012 +0100 +++ b/src/share/vm/utilities/ostream.cpp Wed Mar 21 11:28:22 2012 +0100 @@ -616,9 +616,9 @@ // Print it as a java-style property list. // System properties don't generally contain newlines, so don't bother with unparsing. for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { - xs->text()->print(p->key()); + xs->text()->print(p->key() ? p->key() : ""); xs->text()->print("="); - xs->text()->print_cr(p->value()); + xs->text()->print_cr(p->value() ? p->value() : ""); } xs->tail("properties"); }