diff graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java @ 7684:bbf97d6688d3

cleanup for the inlining policies added devirtualization of invokes
author Christian Haeubl <haeubl@ssw.jku.at>
date Fri, 01 Feb 2013 16:57:40 +0100
parents 42b6e0905881
children 7d66682cc901
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Jan 16 10:19:09 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Feb 01 16:57:40 2013 +0100
@@ -32,9 +32,11 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
-import com.oracle.graal.phases.common.InliningUtil.*;
+import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
+import com.oracle.graal.phases.common.InliningUtil.InliningCallback;
+import com.oracle.graal.phases.common.InliningUtil.InliningPolicy;
 
 public class InliningPhase extends Phase implements InliningCallback {
     /*
@@ -50,6 +52,7 @@
     private final Assumptions assumptions;
     private final GraphCache cache;
     private final InliningPolicy inliningPolicy;
+    private final OptimisticOptimizations optimisticOpts;
     private CustomCanonicalizer customCanonicalizer;
 
     // Metrics
@@ -59,20 +62,21 @@
     private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
 
     public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
-        this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints));
+        this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts);
     }
 
     public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
         this.customCanonicalizer = customCanonicalizer;
     }
 
-    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) {
+    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) {
         this.target = target;
         this.runtime = runtime;
         this.assumptions = assumptions;
         this.cache = cache;
         this.plan = plan;
         this.inliningPolicy = inliningPolicy;
+        this.optimisticOpts = optimisticOpts;
     }
 
     @Override
@@ -93,12 +97,11 @@
                         candidate.inline(graph, runtime, this, assumptions);
                         Debug.dump(graph, "after %s", candidate);
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
+                        inliningPolicy.scanInvokes(newNodes);
                         if (GraalOptions.OptCanonicalizer) {
                             new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         metricInliningPerformed.increment();
-
-                        inliningPolicy.scanInvokes(newNodes);
                     } catch (BailoutException bailout) {
                         // TODO determine if we should really bail out of the whole compilation.
                         throw bailout;
@@ -109,6 +112,8 @@
                     } catch (GraalInternalError e) {
                         throw e.addContext(candidate.toString());
                     }
+                } else if (optimisticOpts.devirtualizeInvokes()) {
+                    candidate.tryToDevirtualizeInvoke(graph, runtime, assumptions);
                 }
             }
         }
@@ -149,161 +154,187 @@
         boolean isWorthInlining(InlineInfo info);
     }
 
-    private abstract static class AbstractInliningDecision implements InliningDecision {
-        protected static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
-            assert !Double.isNaN(info.weight()) && !Double.isNaN(maxSize);
-            boolean success = info.weight() <= maxSize;
-            if (GraalOptions.Debug) {
-                String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)";
-                InliningUtil.logInliningDecision(info, success, formatterString, info.weight(), maxSize);
-            }
-            return success;
-        }
+    private static class GreedySizeBasedInliningDecision implements InliningDecision {
+        private final GraalCodeCacheProvider runtime;
+        private final Collection<Invoke> hints;
 
-        protected static boolean checkCompiledCodeSize(InlineInfo info) {
-            if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
-                InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
-                return false;
-            }
-            return true;
+        public GreedySizeBasedInliningDecision(GraalCodeCacheProvider runtime, Collection<Invoke> hints) {
+            this.runtime = runtime;
+            this.hints = hints;
         }
 
-        protected static double getRelevance(Invoke invoke) {
-            if (GraalOptions.UseRelevanceBasedInlining) {
-                return invoke.inliningRelevance();
-            } else {
-                return invoke.probability();
-            }
-        }
-    }
-
-    private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision {
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize);
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class MinimumCodeSizeBasedInliningDecision extends AbstractInliningDecision {
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double inlineWeight = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight;
-            maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize);
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class DynamicSizeBasedInliningDecision extends AbstractInliningDecision {
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double relevance = getRelevance(info.invoke());
-            double inlineBoost = Math.min(GraalOptions.RatioCapForInlining, relevance) + Math.log10(Math.max(1, relevance - GraalOptions.RatioCapForInlining + 1));
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize;
-            maxSize = maxSize + maxSize * inlineBoost;
-            maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize));
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class GreedySizeBasedInliningDecision extends AbstractInliningDecision {
         @Override
         public boolean isWorthInlining(InlineInfo info) {
+//            assert GraalOptions.ProbabilityAnalysis;
+//            if (compiledCodeSize(info) > GraalOptions.SmallCompiledCodeSize) {
+//                return false;
+//            }
+//
+//            double maxSize = GraalOptions.NormalComplexity;
+//            Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature();
+//            int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers()));
+//            if (signature.getReturnKind() != Kind.Void) {
+//                transferredValues++;
+//            }
+//            maxSize += transferredValues * 10;
+//
+//            maxSize = Math.min(GraalOptions.RelevanceCapForInlining, info.invoke().inliningRelevance()) * maxSize;
+//            maxSize = Math.max(maxSize, GraalOptions.TrivialComplexity);
+//
+//            return compilationComplexity(info) < maxSize;
+
             assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
+            // TODO (chaeubl): invoked methods that are on important paths but not yet compiled -> will be compiled anyways and it is likely that we are the only caller...
+            //       might be useful to inline those methods but increases bootstrap time (maybe those methods are also getting queued in the compilation queue concurrently)
+
+            if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) {
+                return InliningUtil.logInlinedMethod(info, "intrinsic");
             }
 
-            double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            if (GraalOptions.InliningBonusPerTransferredValue != 0) {
-                Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature();
-                int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers()));
-                if (signature.getReturnKind() != Kind.Void) {
-                    transferredValues++;
+            int bytecodeSize = bytecodeCodeSize(info);
+            int complexity = compilationComplexity(info);
+            int compiledCodeSize = compiledCodeSize(info);
+            double relevance = info.invoke().inliningRelevance();
+
+            // as long as the compiled code size is small enough (or the method was not yet compiled), we can do a pretty general inlining that suits most situations
+            if (compiledCodeSize < GraalOptions.SmallCompiledCodeSize) {
+                if (isTrivialInlining(bytecodeSize, complexity, compiledCodeSize)) {
+                    return InliningUtil.logInlinedMethod(info, "trivial (bytecodes=%d, complexity=%d, codeSize=%d)", bytecodeSize, complexity, compiledCodeSize);
                 }
-                maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue;
+
+                if (canInlineRelevanceBased(relevance, bytecodeSize, complexity, compiledCodeSize)) {
+                    return InliningUtil.logInlinedMethod(info, "relevance-based (relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d)", relevance, bytecodeSize, complexity, compiledCodeSize);
+                }
             }
 
-            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
-            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
+            // the normal inlining did not fit this invoke, so check if we have any reason why we should still do the inlining
+            double probability = info.invoke().probability();
+            int transferredValues = numberOfTransferredValues(info);
+            int invokeUsages = countInvokeUsages(info);
+            int moreSpecificArguments = countMoreSpecificArgumentInfo(info);
+            int level = info.level();
+            boolean preferredInvoke = hints != null && hints.contains(info.invoke());
 
-            return decideSizeBasedInlining(info, maxSize);
+            // TODO (chaeubl): compute metric that is used to check if this method should be inlined anyways. also use the relevance somehow...
+//            double metric = (moreSpecificArguments * 5 + transferredValues + invokeUsages) * (preferredInvoke ? 1 : GraalOptions.BoostInliningForEscapeAnalysis);
+//            if (metric > 50) {
+//                // TEMP:
+//                TTY.println("Inlined special method (relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d, probability=%f, transferredValues=%d, invokeUsages=%d, moreSpecificArguments=%d, level=%d, preferred=%b)",
+//                                relevance, bytecodeSize, complexity, compiledCodeSize, probability, transferredValues, invokeUsages, moreSpecificArguments, level, preferredInvoke);
+//                return InliningUtil.logInlinedMethod(info, "(relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d, probability=%f, transferredValues=%d, invokeUsages=%d, moreSpecificArguments=%d, level=%d, preferred=%b)",
+//                                relevance, bytecodeSize, complexity, compiledCodeSize, probability, transferredValues, invokeUsages, moreSpecificArguments, level, preferredInvoke);
+//            }
+
+
+            return InliningUtil.logNotInlinedMethod(info, "(relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d, probability=%f, transferredValues=%d, invokeUsages=%d, moreSpecificArguments=%d, level=%d, preferred=%b)",
+                            relevance, bytecodeSize, complexity, compiledCodeSize, probability, transferredValues, invokeUsages, moreSpecificArguments, level, preferredInvoke);
         }
-    }
+
+        private static boolean isTrivialInlining(int bytecodeSize, int complexity, int compiledCodeSize) {
+            return bytecodeSize < GraalOptions.TrivialBytecodeSize ||
+                   complexity < GraalOptions.TrivialComplexity ||
+                   compiledCodeSize > 0 && compiledCodeSize < GraalOptions.TrivialCompiledCodeSize;
+        }
 
-    private static class GreedyMachineCodeInliningDecision extends AbstractInliningDecision {
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
+        private static boolean canInlineRelevanceBased(double relevance, int bytecodeSize, int complexity, int compiledCodeSize) {
+            return bytecodeSize < computeMaximumSize(relevance, GraalOptions.NormalBytecodeSize) ||
+                   complexity < computeMaximumSize(relevance, GraalOptions.NormalComplexity) ||
+                   compiledCodeSize > 0 && compiledCodeSize < computeMaximumSize(relevance, GraalOptions.NormalCompiledCodeSize);
+        }
+
+        private static double computeMaximumSize(double relevance, int configuredMaximum) {
+            double inlineRatio = Math.min(GraalOptions.RelevanceCapForInlining, relevance);
+            return configuredMaximum * inlineRatio;
+        }
 
-            double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
-            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
+        private static int numberOfTransferredValues(InlineInfo info) {
+            Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature();
+            int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers()));
+            if (signature.getReturnKind() != Kind.Void) {
+                transferredValues++;
+            }
+            return transferredValues;
+        }
 
-            return decideSizeBasedInlining(info, maxSize);
+        private static int countInvokeUsages(InlineInfo info) {
+            // inlining calls with lots of usages simplifies the caller
+            int usages = 0;
+            for (Node n: info.invoke().node().usages()) {
+                if (!(n instanceof FrameState)) {
+                    usages++;
+                }
+            }
+            return usages;
         }
-    }
+
+        private int countMoreSpecificArgumentInfo(InlineInfo info) {
+            // inlining invokes where the caller has very specific information about the passed argument simplifies the callee
+            int moreSpecificArgumentInfo = 0;
+            boolean isStatic = info.invoke().methodCallTarget().isStatic();
+            int signatureOffset = isStatic ? 0 : 1;
+            NodeInputList arguments = info.invoke().methodCallTarget().arguments();
+            ResolvedJavaMethod targetMethod = info.invoke().methodCallTarget().targetMethod();
+            ResolvedJavaType methodHolderClass = targetMethod.getDeclaringClass();
+            Signature signature = targetMethod.getSignature();
 
-    private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+            for (int i = 0; i < arguments.size(); i++) {
+                Node n = arguments.get(i);
+                if (n instanceof ConstantNode) {
+                    moreSpecificArgumentInfo++;
+                } else if (n instanceof ValueNode && !((ValueNode) n).kind().isPrimitive()) {
+                    ResolvedJavaType actualType = ((ValueNode) n).stamp().javaType(runtime);
+                    JavaType declaredType;
+                    if (i == 0 && !isStatic) {
+                        declaredType = methodHolderClass;
+                    } else {
+                        declaredType = signature.getParameterType(i - signatureOffset, methodHolderClass);
+                    }
+
+                    if (declaredType instanceof ResolvedJavaType && !actualType.equals(declaredType) && ((ResolvedJavaType) declaredType).isAssignableFrom(actualType)) {
+                        moreSpecificArgumentInfo++;
+                    }
+                }
             }
 
-            double codeSize = method.getCodeSize();
-            if (preferredInvoke) {
-                codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis;
-            }
-            return codeSize;
+            return moreSpecificArgumentInfo;
         }
-    }
 
-    private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+        private static int bytecodeCodeSize(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCodeSize();
             }
+            return result;
+        }
 
-            double complexity = method.getCompilationComplexity();
-            if (preferredInvoke) {
-                complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis;
+        private static int compilationComplexity(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCompilationComplexity();
             }
-            return complexity;
+            return result;
         }
-    }
 
-    private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+        private static int compiledCodeSize(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCompiledCodeSize();
             }
+            return result;
+        }
 
-            int compiledCodeSize = method.getCompiledCodeSize();
-            return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10;
+        private static boolean onlyIntrinsics(InlineInfo info) {
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                if (!InliningUtil.canIntrinsify(info.methodAt(i))) {
+                    return false;
+                }
+            }
+            return true;
         }
     }
 
     private static class CFInliningPolicy implements InliningPolicy {
         private final InliningDecision inliningDecision;
-        private final WeightComputationPolicy weightComputationPolicy;
         private final Collection<Invoke> hints;
         private final Assumptions assumptions;
         private final OptimisticOptimizations optimisticOpts;
@@ -311,10 +342,9 @@
         private NodeBitMap visitedFixedNodes;
         private FixedNode invokePredecessor;
 
-        public CFInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection<Invoke> hints,
+        public CFInliningPolicy(InliningDecision inliningPolicy, Collection<Invoke> hints,
                         Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
             this.inliningDecision = inliningPolicy;
-            this.weightComputationPolicy = weightComputationPolicy;
             this.hints = hints;
             this.assumptions = assumptions;
             this.optimisticOpts = optimisticOpts;
@@ -333,7 +363,7 @@
 
         public InlineInfo next() {
             Invoke invoke = sortedInvokes.pop();
-            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts);
+            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, optimisticOpts);
             if (info != null) {
                 invokePredecessor = (FixedNode) info.invoke().predecessor();
                 assert invokePredecessor.isAlive();
@@ -354,169 +384,103 @@
         }
 
         public void scanInvokes(Iterable<? extends Node> newNodes) {
-            scanGraphForInvokes(invokePredecessor);
+            assert invokePredecessor.isAlive();
+            int invokes = scanGraphForInvokes(invokePredecessor);
+            assert invokes == countInvokes(newNodes);
         }
 
-        private void scanGraphForInvokes(FixedNode start) {
+        private int scanGraphForInvokes(FixedNode start) {
             ArrayList<Invoke> invokes = new InliningIterator(start, visitedFixedNodes).apply();
 
             // insert the newly found invokes in their correct control-flow order
             for (int i = invokes.size() - 1; i >= 0; i--) {
-                sortedInvokes.addFirst(invokes.get(i));
-            }
-        }
-
-        public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
-            boolean preferredInvoke = hints != null && hints.contains(invoke);
-            return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke);
-        }
-    }
-
-    private static class PriorityInliningPolicy implements InliningPolicy {
-        private final InliningDecision inliningDecision;
-        private final WeightComputationPolicy weightComputationPolicy;
-        private final Collection<Invoke> hints;
-        private final Assumptions assumptions;
-        private final OptimisticOptimizations optimisticOpts;
-        private final PriorityQueue<InlineInfo> sortedCandidates;
-
-        public PriorityInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection<Invoke> hints,
-                        Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
-            this.inliningDecision = inliningPolicy;
-            this.weightComputationPolicy = weightComputationPolicy;
-            this.hints = hints;
-            this.assumptions = assumptions;
-            this.optimisticOpts = optimisticOpts;
-            sortedCandidates = new PriorityQueue<>();
-        }
-
-        public boolean continueInlining(StructuredGraph graph) {
-            if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
-                InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize");
-                metricInliningStoppedByMaxDesiredSize.increment();
-                return false;
+                Invoke invoke = invokes.get(i);
+                assert !sortedInvokes.contains(invoke);
+                sortedInvokes.addFirst(invoke);
             }
 
-            return !sortedCandidates.isEmpty();
+            return invokes.size();
         }
 
-        public InlineInfo next() {
-            // refresh cached info before using it (it might have been in the queue for a long time)
-            InlineInfo info = sortedCandidates.remove();
-            return InliningUtil.getInlineInfo(info.invoke(), assumptions, this, optimisticOpts);
-        }
-
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            return inliningDecision.isWorthInlining(info);
-        }
-
-        @SuppressWarnings("unchecked")
-        public void initialize(StructuredGraph graph) {
-            if (hints == null) {
-                scanInvokes(graph.getNodes(InvokeNode.class));
-                scanInvokes(graph.getNodes(InvokeWithExceptionNode.class));
-            } else {
-                scanInvokes((Iterable<? extends Node>) (Iterable<?>) hints);
-            }
-        }
-
-        public void scanInvokes(Iterable<? extends Node> nodes) {
-            for (Node node: nodes) {
-                if (node != null) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        scanInvoke(invoke);
-                    }
-                    for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
-                        scanInvoke((Invoke) usage);
-                    }
+        private static int countInvokes(Iterable<? extends Node> nodes) {
+            int count = 0;
+            for (Node n: nodes) {
+                if (n instanceof Invoke) {
+                    count++;
                 }
             }
-        }
-
-        private void scanInvoke(Invoke invoke) {
-            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts);
-            if (info != null) {
-                sortedCandidates.add(info);
-            }
-        }
-
-        @Override
-        public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
-            boolean preferredInvoke = hints != null && hints.contains(invoke);
-            return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke);
+            return count;
         }
     }
 
     private static class InliningIterator {
         private final FixedNode start;
-        private final NodeBitMap processedNodes;
-
         private final Deque<FixedNode> nodeQueue;
         private final NodeBitMap queuedNodes;
 
         public InliningIterator(FixedNode start, NodeBitMap visitedFixedNodes) {
             this.start = start;
-            this.processedNodes = visitedFixedNodes;
-
             this.nodeQueue = new ArrayDeque<>();
-            this.queuedNodes = visitedFixedNodes.copy();
-
+            this.queuedNodes = visitedFixedNodes;
             assert start.isAlive();
         }
 
         public ArrayList<Invoke> apply() {
             ArrayList<Invoke> invokes = new ArrayList<>();
-            FixedNode current = start;
-            do {
+            FixedNode current;
+            forcedQueue(start);
+
+            while ((current = nextQueuedNode()) != null) {
                 assert current.isAlive();
-                processedNodes.mark(current);
 
-                if (current instanceof InvokeWithExceptionNode || current instanceof InvokeNode) {
-                    invokes.add((Invoke) current);
+                if (current instanceof Invoke) {
+                    if (current != start) {
+                        invokes.add((Invoke) current);
+                    }
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else if (current instanceof LoopBeginNode) {
-                    current = ((LoopBeginNode) current).next();
-                    assert current != null;
+                    queueSuccessors(current);
                 } else if (current instanceof LoopEndNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof MergeNode) {
-                    current = ((MergeNode) current).next();
-                    assert current != null;
+                    queueSuccessors(current);
                 } else if (current instanceof FixedWithNextNode) {
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else if (current instanceof EndNode) {
                     queueMerge((EndNode) current);
-                    current = nextQueuedNode();
                 } else if (current instanceof DeoptimizeNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof ReturnNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof UnwindNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof ControlSplitNode) {
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else {
                     assert false : current;
                 }
-            } while(current != null);
+            }
 
             return invokes;
         }
 
         private void queueSuccessors(FixedNode x) {
             for (Node node : x.successors()) {
-                if (node != null && !queuedNodes.isMarked(node)) {
-                    queuedNodes.mark(node);
-                    nodeQueue.addFirst((FixedNode) node);
-                }
+                queue(node);
             }
         }
 
+        private void queue(Node node) {
+            if (node != null && !queuedNodes.isMarked(node)) {
+                forcedQueue(node);
+            }
+        }
+
+        private void forcedQueue(Node node) {
+            queuedNodes.mark(node);
+            nodeQueue.addFirst((FixedNode) node);
+        }
+
         private FixedNode nextQueuedNode() {
             if (nodeQueue.isEmpty()) {
                 return null;
@@ -537,7 +501,7 @@
 
         private boolean visitedAllEnds(MergeNode merge) {
             for (int i = 0; i < merge.forwardEndCount(); i++) {
-                if (!processedNodes.isMarked(merge.forwardEndAt(i))) {
+                if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                     return false;
                 }
             }
@@ -545,38 +509,8 @@
         }
     }
 
-    private static InliningPolicy createInliningPolicy(Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection<Invoke> hints) {
-        switch(GraalOptions.InliningPolicy) {
-            case 0: return new CFInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts);
-            case 1: return new PriorityInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts);
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private static InliningDecision createInliningDecision() {
-        switch(GraalOptions.InliningDecision) {
-            case 1: return new C1StaticSizeBasedInliningDecision();
-            case 2: return new MinimumCodeSizeBasedInliningDecision();
-            case 3: return new DynamicSizeBasedInliningDecision();
-            case 4: return new GreedySizeBasedInliningDecision();
-            case 5: return new GreedyMachineCodeInliningDecision();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private static WeightComputationPolicy createWeightComputationPolicy() {
-        switch(GraalOptions.WeightComputationPolicy) {
-            case 0: throw new GraalInternalError("removed because of invokation counter changes");
-            case 1: return new BytecodeSizeBasedWeightComputationPolicy();
-            case 2: return new ComplexityBasedWeightComputationPolicy();
-            case 3: return new CompiledCodeSizeWeightComputationPolicy();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
+    private static InliningPolicy createInliningPolicy(GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection<Invoke> hints) {
+        InliningDecision inliningDecision = new GreedySizeBasedInliningDecision(runtime, hints);
+        return new CFInliningPolicy(inliningDecision, hints, assumptions, optimisticOpts);
     }
 }