comparison graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/Inlining.java @ 2874:d90bf514d647

Renamed packages.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:59:54 +0200
parents graal/com.oracle.max.graal.compiler/src/com/sun/c1x/graph/Inlining.java@0341b6424579
children 3570f1f7903e
comparison
equal deleted inserted replaced
2873:810e2d253e00 2874:d90bf514d647
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 com.oracle.max.graal.compiler.graph;
24
25 import java.lang.reflect.*;
26 import java.util.*;
27
28 import com.oracle.max.graal.compiler.*;
29 import com.oracle.max.graal.compiler.ir.*;
30 import com.oracle.max.graal.compiler.value.*;
31 import com.oracle.max.graal.graph.*;
32 import com.sun.cri.ci.*;
33 import com.sun.cri.ri.*;
34
35
36 public class Inlining extends Phase {
37
38 private final C1XCompilation compilation;
39 private final IR ir;
40
41 private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
42 private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
43 private int inliningSize;
44
45 public Inlining(C1XCompilation compilation, IR ir) {
46 this.compilation = compilation;
47 this.ir = ir;
48 }
49
50 private void addToQueue(Invoke invoke, RiMethod method) {
51 invokes.add(invoke);
52 methods.add(method);
53 inliningSize += method.code().length;
54 }
55
56 @Override
57 protected void run(Graph graph) {
58 if (!C1XOptions.Inline) {
59 return;
60 }
61
62 inliningSize = compilation.method.code().length;
63 int iterations = C1XOptions.MaximumRecursiveInlineLevel;
64 do {
65 for (Node node : graph.getNodes()) {
66 if (node instanceof Invoke) {
67 Invoke invoke = (Invoke) node;
68 RiMethod target = invoke.target;
69 if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
70 continue;
71 }
72 if (target.canBeStaticallyBound()) {
73 if (checkInliningConditions(invoke.target)) {
74 addToQueue(invoke, invoke.target);
75 }
76 } else {
77 RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
78 if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
79 if (checkInliningConditions(concrete)) {
80 if (C1XOptions.TraceInlining) {
81 System.out.println("registering concrete method assumption...");
82 }
83 compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
84 addToQueue(invoke, concrete);
85 }
86 }
87 }
88 if (inliningSize > C1XOptions.MaximumInstructionCount) {
89 break;
90 }
91 }
92 }
93
94 assert invokes.size() == methods.size();
95 if (invokes.isEmpty()) {
96 break;
97 }
98
99 Invoke invoke;
100 while ((invoke = invokes.poll()) != null) {
101 RiMethod method = methods.remove();
102 inlineMethod(invoke, method);
103 }
104 DeadCodeElimination dce = new DeadCodeElimination();
105 dce.apply(graph);
106 if (dce.deletedNodeCount > 0) {
107 ir.verifyAndPrint("After dead code elimination");
108 }
109 ir.verifyAndPrint("After inlining iteration");
110
111 if (inliningSize > C1XOptions.MaximumInstructionCount) {
112 if (C1XOptions.TraceInlining) {
113 System.out.println("inlining stopped: MaximumInstructionCount reached");
114 }
115 break;
116 }
117 } while(--iterations > 0);
118 }
119
120 private boolean checkInliningConditions(Invoke invoke) {
121 String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
122 if (invoke.predecessors().size() == 0) {
123 if (C1XOptions.TraceInlining) {
124 System.out.println("not inlining " + name + " because the invoke is dead code");
125 }
126 return false;
127 }
128 return true;
129 }
130
131 private boolean checkInliningConditions(RiMethod method) {
132 String name = null;
133 if (C1XOptions.TraceInlining) {
134 name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
135 }
136 if (method.code().length > C1XOptions.MaximumInlineSize) {
137 if (C1XOptions.TraceInlining) {
138 System.out.println("not inlining " + name + " because of code size");
139 }
140 return false;
141 }
142 if (!method.holder().isInitialized()) {
143 if (C1XOptions.TraceInlining) {
144 System.out.println("not inlining " + name + " because of non-initialized class");
145 }
146 return false;
147 }
148 return true;
149 }
150
151 private void inlineMethod(Invoke invoke, RiMethod method) {
152 String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
153 FrameState stateAfter = invoke.stateAfter();
154 Instruction exceptionEdge = invoke.exceptionEdge();
155
156 if (C1XOptions.TraceInlining) {
157 System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
158 }
159
160 CompilerGraph graph = new CompilerGraph();
161 new GraphBuilder(compilation, method, graph).build(true);
162
163 boolean withReceiver = !Modifier.isStatic(method.accessFlags());
164
165 int argumentCount = method.signature().argumentCount(false);
166 Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
167 int slot = withReceiver ? 1 : 0;
168 int param = withReceiver ? 1 : 0;
169 for (int i = 0; i < argumentCount; i++) {
170 parameters[param++] = invoke.argument(slot);
171 slot += method.signature().argumentKindAt(i).sizeInSlots();
172 }
173 if (withReceiver) {
174 parameters[0] = invoke.argument(0);
175 }
176
177 HashMap<Node, Node> replacements = new HashMap<Node, Node>();
178 ArrayList<Node> nodes = new ArrayList<Node>();
179 ArrayList<Node> frameStates = new ArrayList<Node>();
180 Return returnNode = null;
181 Unwind unwindNode = null;
182 StartNode startNode = graph.start();
183 for (Node node : graph.getNodes()) {
184 if (node != null) {
185 if (node instanceof StartNode) {
186 assert startNode == node;
187 } else if (node instanceof Local) {
188 replacements.put(node, parameters[((Local) node).index()]);
189 } else {
190 nodes.add(node);
191 if (node instanceof Return) {
192 returnNode = (Return) node;
193 } else if (node instanceof Unwind) {
194 unwindNode = (Unwind) node;
195 } else if (node instanceof FrameState) {
196 frameStates.add(node);
197 }
198 }
199 }
200 }
201
202 if (C1XOptions.TraceInlining) {
203 ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
204 System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
205 }
206
207 assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
208 Instruction pred;
209 if (withReceiver) {
210 pred = new NullCheck(parameters[0], compilation.graph);
211 } else {
212 pred = new Merge(compilation.graph);
213 }
214 invoke.predecessors().get(0).successors().replace(invoke, pred);
215 replacements.put(startNode, pred);
216
217 Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
218
219 if (returnNode != null) {
220 List<Node> usages = new ArrayList<Node>(invoke.usages());
221 for (Node usage : usages) {
222 if (returnNode.result() instanceof Local) {
223 usage.inputs().replace(invoke, replacements.get(returnNode.result()));
224 } else {
225 usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
226 }
227 }
228 Node returnDuplicate = duplicates.get(returnNode);
229 returnDuplicate.inputs().clearAll();
230
231 assert returnDuplicate.predecessors().size() == 1;
232 Node returnPred = returnDuplicate.predecessors().get(0);
233 int index = returnDuplicate.predecessorsIndex().get(0);
234 returnPred.successors().setAndClear(index, invoke, 0);
235 returnDuplicate.delete();
236 }
237
238 // if (invoke.next() instanceof Merge) {
239 // ((Merge) invoke.next()).removePhiPredecessor(invoke);
240 // }
241 // invoke.successors().clearAll();
242 invoke.inputs().clearAll();
243 invoke.setExceptionEdge(null);
244 // invoke.delete();
245
246
247 if (exceptionEdge != null) {
248 if (unwindNode != null) {
249 assert unwindNode.predecessors().size() == 1;
250 assert exceptionEdge.successors().size() == 1;
251 ExceptionObject obj = (ExceptionObject) exceptionEdge;
252
253 List<Node> usages = new ArrayList<Node>(obj.usages());
254 for (Node usage : usages) {
255 if (replacements.containsKey(unwindNode.exception())) {
256 usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
257 } else {
258 usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
259 }
260 }
261 Node unwindDuplicate = duplicates.get(unwindNode);
262 unwindDuplicate.inputs().clearAll();
263
264 assert unwindDuplicate.predecessors().size() == 1;
265 Node unwindPred = unwindDuplicate.predecessors().get(0);
266 int index = unwindDuplicate.predecessorsIndex().get(0);
267 unwindPred.successors().setAndClear(index, obj, 0);
268
269 obj.inputs().clearAll();
270 obj.delete();
271 unwindDuplicate.delete();
272
273 }
274 }
275
276 // adjust all frame states that were copied
277 if (frameStates.size() > 0) {
278 FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
279 for (Node frameState : frameStates) {
280 ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
281 }
282 }
283
284 if (C1XOptions.TraceInlining) {
285 ir.verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
286 }
287 }
288 }