001/* 002 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.phases.common.inlining.policy; 024 025import static com.oracle.graal.compiler.common.GraalOptions.*; 026 027import java.util.*; 028 029import com.oracle.graal.debug.*; 030 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.nodes.spi.*; 033import com.oracle.graal.phases.common.inlining.*; 034import com.oracle.graal.phases.common.inlining.info.*; 035import com.oracle.graal.phases.common.inlining.walker.*; 036 037public class GreedyInliningPolicy extends AbstractInliningPolicy { 038 039 private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); 040 041 public GreedyInliningPolicy(Map<Invoke, Double> hints) { 042 super(hints); 043 } 044 045 public boolean continueInlining(StructuredGraph currentGraph) { 046 if (currentGraph.getNodeCount() >= MaximumDesiredSize.getValue()) { 047 InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); 048 metricInliningStoppedByMaxDesiredSize.increment(); 049 return false; 050 } 051 return true; 052 } 053 054 @Override 055 public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { 056 057 final InlineInfo info = invocation.callee(); 058 final double probability = invocation.probability(); 059 final double relevance = invocation.relevance(); 060 061 if (InlineEverything.getValue()) { 062 InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); 063 return true; 064 } 065 066 if (isIntrinsic(replacements, info)) { 067 InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic"); 068 return true; 069 } 070 071 if (info.shouldInline()) { 072 InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining"); 073 return true; 074 } 075 076 double inliningBonus = getInliningBonus(info); 077 int nodes = info.determineNodeCount(); 078 int lowLevelGraphSize = previousLowLevelGraphSize(info); 079 080 if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) { 081 InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", lowLevelGraphSize, 082 relevance, probability, inliningBonus, nodes); 083 return false; 084 } 085 086 if (nodes < TrivialInliningSize.getValue() * inliningBonus) { 087 InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); 088 return true; 089 } 090 091 /* 092 * TODO (chaeubl): invoked methods that are on important paths but not yet compiled -> will 093 * be compiled anyways and it is likely that we are the only caller... might be useful to 094 * inline those methods but increases bootstrap time (maybe those methods are also getting 095 * queued in the compilation queue concurrently) 096 */ 097 double invokes = determineInvokeProbability(info); 098 if (LimitInlinedInvokes.getValue() > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue() * inliningBonus) { 099 InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance, 100 probability, inliningBonus, nodes); 101 return false; 102 } 103 104 double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue() * inliningBonus)); 105 if (nodes <= maximumNodes) { 106 InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, 107 nodes, maximumNodes); 108 return true; 109 } 110 111 InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes); 112 return false; 113 } 114}