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.walker; 024 025import java.util.*; 026import java.util.function.*; 027 028import jdk.internal.jvmci.meta.*; 029 030import com.oracle.graal.graph.*; 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.phases.common.inlining.policy.*; 033import com.oracle.graal.phases.graph.*; 034 035/** 036 * <p> 037 * A {@link CallsiteHolder} whose graph has been copied already and thus can be modified without 038 * affecting the original (usually cached) version. 039 * </p> 040 * 041 * <p> 042 * An instance of this class is derived from an 043 * {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph InlineableGraph} and 044 * contains a subset of the information there: just the {@link Invoke} nodes from it. Such nodes are 045 * candidates for depth-first search of further inlining opportunities (thus the adjective 046 * "explorable" given to this class) 047 * </p> 048 * 049 * @see InliningData#moveForward() 050 */ 051public final class CallsiteHolderExplorable extends CallsiteHolder { 052 053 /** 054 * Graph in which inlining may be performed at one or more of the callsites containined in 055 * {@link #remainingInvokes}. 056 */ 057 private final StructuredGraph graph; 058 059 private final LinkedList<Invoke> remainingInvokes; 060 private final double probability; 061 private final double relevance; 062 063 /** 064 * @see #getFixedParams() 065 */ 066 private final Set<ParameterNode> fixedParams; 067 068 private final ToDoubleFunction<FixedNode> probabilities; 069 private final ComputeInliningRelevance computeInliningRelevance; 070 071 public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance, BitSet freshlyInstantiatedArguments) { 072 assert graph != null; 073 this.graph = graph; 074 this.probability = probability; 075 this.relevance = relevance; 076 this.fixedParams = fixedParamsAt(freshlyInstantiatedArguments); 077 remainingInvokes = new InliningIterator(graph).apply(); 078 if (remainingInvokes.isEmpty()) { 079 probabilities = null; 080 computeInliningRelevance = null; 081 } else { 082 probabilities = new FixedNodeProbabilityCache(); 083 computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); 084 computeProbabilities(); 085 } 086 assert repOK(); 087 } 088 089 /** 090 * @see #getFixedParams() 091 */ 092 @SuppressWarnings("unchecked") 093 private Set<ParameterNode> fixedParamsAt(BitSet freshlyInstantiatedArguments) { 094 if (freshlyInstantiatedArguments == null || freshlyInstantiatedArguments.isEmpty()) { 095 return Collections.EMPTY_SET; 096 } 097 Set<ParameterNode> result = Node.newSet(); 098 for (ParameterNode p : graph.getNodes(ParameterNode.TYPE)) { 099 if (freshlyInstantiatedArguments.get(p.index())) { 100 result.add(p); 101 } 102 } 103 return result; 104 } 105 106 /** 107 * <p> 108 * Parameters for which the callsite targeting {@link #graph()} provides "fixed" arguments. That 109 * callsite isn't referenced by this instance. Instead, it belongs to the graph of the caller of 110 * this {@link CallsiteHolderExplorable} 111 * </p> 112 * 113 * <p> 114 * Constant arguments don't contribute to fixed-params: those params have been removed already, 115 * see {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph}. 116 * </p> 117 * 118 * <p> 119 * Instead, fixed-params are those receiving freshly instantiated arguments (possibly 120 * instantiated several levels up in the call-hierarchy) 121 * </p> 122 * */ 123 public Set<ParameterNode> getFixedParams() { 124 return fixedParams; 125 } 126 127 public boolean repOK() { 128 for (Invoke invoke : remainingInvokes) { 129 if (!invoke.asNode().isAlive() || !containsInvoke(invoke)) { 130 assert false; 131 return false; 132 } 133 if (!allArgsNonNull(invoke)) { 134 assert false; 135 return false; 136 } 137 } 138 for (ParameterNode fixedParam : fixedParams) { 139 if (!containsParam(fixedParam)) { 140 assert false; 141 return false; 142 } 143 } 144 return true; 145 } 146 147 @Override 148 public ResolvedJavaMethod method() { 149 return graph == null ? null : graph.method(); 150 } 151 152 @Override 153 public boolean hasRemainingInvokes() { 154 return !remainingInvokes.isEmpty(); 155 } 156 157 @Override 158 public StructuredGraph graph() { 159 return graph; 160 } 161 162 public Invoke popInvoke() { 163 return remainingInvokes.removeFirst(); 164 } 165 166 public void pushInvoke(Invoke invoke) { 167 remainingInvokes.push(invoke); 168 } 169 170 public static boolean allArgsNonNull(Invoke invoke) { 171 for (ValueNode arg : invoke.callTarget().arguments()) { 172 if (arg == null) { 173 assert false; 174 return false; 175 } 176 } 177 return true; 178 } 179 180 public boolean containsInvoke(Invoke invoke) { 181 for (Invoke i : graph().getInvokes()) { 182 if (i == invoke) { 183 return true; 184 } 185 } 186 return false; 187 } 188 189 public boolean containsParam(ParameterNode param) { 190 for (ParameterNode p : graph.getNodes(ParameterNode.TYPE)) { 191 if (p == param) { 192 return true; 193 } 194 } 195 return false; 196 } 197 198 public void computeProbabilities() { 199 computeInliningRelevance.compute(); 200 } 201 202 public double invokeProbability(Invoke invoke) { 203 return probability * probabilities.applyAsDouble(invoke.asNode()); 204 } 205 206 public double invokeRelevance(Invoke invoke) { 207 return Math.min(AbstractInliningPolicy.CapInheritedRelevance, relevance) * computeInliningRelevance.getRelevance(invoke); 208 } 209 210 @Override 211 public String toString() { 212 return (graph != null ? method().format("%H.%n(%p)") : "<null method>") + remainingInvokes; 213 } 214}