1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.phases.common.inlining; 24 25 import java.util.Map; 26 27 import org.graalvm.compiler.nodes.Invoke; 28 import org.graalvm.compiler.nodes.StructuredGraph; 29 import org.graalvm.compiler.options.Option; 30 import org.graalvm.compiler.options.OptionType; 31 import org.graalvm.compiler.options.OptionValue; 32 import org.graalvm.compiler.phases.common.AbstractInliningPhase; 33 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 34 import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; 35 import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy; 36 import org.graalvm.compiler.phases.common.inlining.walker.InliningData; 37 import org.graalvm.compiler.phases.tiers.HighTierContext; 38 39 public class InliningPhase extends AbstractInliningPhase { 40 41 public static class Options { 42 43 @Option(help = "Unconditionally inline intrinsics", type = OptionType.Debug)// 44 public static final OptionValue<Boolean> AlwaysInlineIntrinsics = new OptionValue<>(false); 45 46 /** 47 * This is a defensive measure against known pathologies of the inliner where the breadth of 48 * the inlining call tree exploration can be wide enough to prevent inlining from completing 49 * in reasonable time. 50 */ 51 @Option(help = "Per-compilation method inlining exploration limit before giving up (use 0 to disable)", type = OptionType.Debug)// 52 public static final OptionValue<Integer> MethodInlineBailoutLimit = new OptionValue<>(5000); 53 } 54 55 private final InliningPolicy inliningPolicy; 56 private final CanonicalizerPhase canonicalizer; 57 58 private int maxMethodPerInlining = Integer.MAX_VALUE; 59 60 public InliningPhase(CanonicalizerPhase canonicalizer) { 61 this(new GreedyInliningPolicy(null), canonicalizer); 62 } 63 64 public InliningPhase(Map<Invoke, Double> hints, CanonicalizerPhase canonicalizer) { 65 this(new GreedyInliningPolicy(hints), canonicalizer); 66 } 67 68 public InliningPhase(InliningPolicy policy, CanonicalizerPhase canonicalizer) { 69 this.inliningPolicy = policy; 70 this.canonicalizer = canonicalizer; 71 } 72 73 public CanonicalizerPhase getCanonicalizer() { 74 return canonicalizer; 75 } 76 77 @Override 78 public float codeSizeIncrease() { 79 return 10_000f; 80 } 81 82 public void setMaxMethodsPerInlining(int max) { 83 maxMethodPerInlining = max; 84 } 85 86 /** 87 * 88 * This method sets in motion the inlining machinery. 89 * 90 * @see InliningData 91 * @see InliningData#moveForward() 92 * 93 */ 94 @Override 95 protected void run(final StructuredGraph graph, final HighTierContext context) { 96 final InliningData data = new InliningData(graph, context, maxMethodPerInlining, canonicalizer, inliningPolicy); 97 98 int count = 0; 99 assert data.repOK(); 100 int limit = Options.MethodInlineBailoutLimit.getValue(); 101 while (data.hasUnprocessedGraphs()) { 102 boolean wasInlined = data.moveForward(); 103 assert data.repOK(); 104 count++; 105 if (!wasInlined) { 106 if (limit > 0 && count == limit) { 107 // Limit the amount of exploration which is done 108 break; 109 } 110 } 111 } 112 113 assert data.inliningDepth() == 0 || count == limit; 114 assert data.graphCount() == 0 || count == limit; 115 } 116 117 }