comparison graal/Compiler/src/com/sun/c1x/C1XCompilation.java @ 2507:9ec15d6914ca

Pull over of compiler from maxine repository.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:43:22 +0200
parents
children
comparison
equal deleted inserted replaced
2506:4a3bf8a5bf41 2507:9ec15d6914ca
1 /*
2 * Copyright (c) 2009, 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
24 package com.sun.c1x;
25
26 import java.util.*;
27
28 import com.sun.c1x.alloc.*;
29 import com.sun.c1x.asm.*;
30 import com.sun.c1x.gen.*;
31 import com.sun.c1x.gen.LIRGenerator.DeoptimizationStub;
32 import com.sun.c1x.graph.*;
33 import com.sun.c1x.ir.*;
34 import com.sun.c1x.lir.*;
35 import com.sun.c1x.observer.*;
36 import com.sun.c1x.value.*;
37 import com.sun.cri.bytecode.*;
38 import com.sun.cri.ci.*;
39 import com.sun.cri.ri.*;
40
41 /**
42 * This class encapsulates global information about the compilation of a particular method,
43 * including a reference to the runtime, statistics about the compiled code, etc.
44 *
45 * @author Ben L. Titzer
46 */
47 public final class C1XCompilation {
48
49 private static ThreadLocal<C1XCompilation> currentCompilation = new ThreadLocal<C1XCompilation>();
50
51 public final C1XCompiler compiler;
52 public final CiTarget target;
53 public final RiRuntime runtime;
54 public final RiMethod method;
55 public final RiRegisterConfig registerConfig;
56 public final CiStatistics stats;
57 public final int osrBCI;
58 public final CiAssumptions assumptions = new CiAssumptions();
59 public final FrameState placeholderState;
60
61 private boolean hasExceptionHandlers;
62 private final C1XCompilation parent;
63
64 /**
65 * @see #setNotTypesafe()
66 * @see #isTypesafe()
67 */
68 private boolean typesafe = true;
69
70 private int nextID = 1;
71
72 private FrameMap frameMap;
73 private AbstractAssembler assembler;
74
75 private IR hir;
76
77 private LIRGenerator lirGenerator;
78
79 /**
80 * Creates a new compilation for the specified method and runtime.
81 *
82 * @param compiler the compiler
83 * @param method the method to be compiled or {@code null} if generating code for a stub
84 * @param osrBCI the bytecode index for on-stack replacement, if requested
85 * @param stats externally supplied statistics object to be used if not {@code null}
86 */
87 public C1XCompilation(C1XCompiler compiler, RiMethod method, int osrBCI, CiStatistics stats) {
88 this.parent = currentCompilation.get();
89 currentCompilation.set(this);
90 this.compiler = compiler;
91 this.target = compiler.target;
92 this.runtime = compiler.runtime;
93 this.method = method;
94 this.osrBCI = osrBCI;
95 this.stats = stats == null ? new CiStatistics() : stats;
96 this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method);
97 this.placeholderState = method != null && method.minimalDebugInfo() ? new MutableFrameState(new IRScope(null, null, method, -1), 0, 0, 0) : null;
98
99 if (compiler.isObserved()) {
100 compiler.fireCompilationStarted(new CompilationEvent(this));
101 }
102 }
103
104 public void close() {
105 currentCompilation.set(parent);
106 }
107
108 public IR hir() {
109 return hir;
110 }
111
112 /**
113 * Records that this compilation has exception handlers.
114 */
115 public void setHasExceptionHandlers() {
116 hasExceptionHandlers = true;
117 }
118
119 /**
120 * Records that this compilation encountered an instruction (e.g. {@link Bytecodes#UNSAFE_CAST})
121 * that breaks the type safety invariant of the input bytecode.
122 */
123 public void setNotTypesafe() {
124 typesafe = false;
125 }
126
127 /**
128 * Checks whether this compilation is for an on-stack replacement.
129 *
130 * @return {@code true} if this compilation is for an on-stack replacement
131 */
132 public boolean isOsrCompilation() {
133 return osrBCI >= 0;
134 }
135
136 /**
137 * Translates a given kind to a canonical architecture kind.
138 * This is an identity function for all but {@link CiKind#Word}
139 * which is translated to {@link CiKind#Int} or {@link CiKind#Long}
140 * depending on whether or not this is a {@linkplain #is64Bit() 64-bit}
141 * compilation.
142 */
143 public CiKind archKind(CiKind kind) {
144 if (kind.isWord()) {
145 return target.arch.is64bit() ? CiKind.Long : CiKind.Int;
146 }
147 return kind;
148 }
149
150 /**
151 * Determines if two given kinds are equal at the {@linkplain #archKind(CiKind) architecture} level.
152 */
153 public boolean archKindsEqual(CiKind kind1, CiKind kind2) {
154 return archKind(kind1) == archKind(kind2);
155 }
156
157 /**
158 * Gets the frame which describes the layout of the OSR interpreter frame for this method.
159 *
160 * @return the OSR frame
161 */
162 public RiOsrFrame getOsrFrame() {
163 return runtime.getOsrFrame(method, osrBCI);
164 }
165
166 /**
167 * Records an assumption that the specified type has no finalizable subclasses.
168 *
169 * @param receiverType the type that is assumed to have no finalizable subclasses
170 * @return {@code true} if the assumption was recorded and can be assumed; {@code false} otherwise
171 */
172 public boolean recordNoFinalizableSubclassAssumption(RiType receiverType) {
173 return false;
174 }
175
176 /**
177 * Converts this compilation to a string.
178 *
179 * @return a string representation of this compilation
180 */
181 @Override
182 public String toString() {
183 if (isOsrCompilation()) {
184 return "osr-compile @ " + osrBCI + ": " + method;
185 }
186 return "compile: " + method;
187 }
188
189 /**
190 * Builds the block map for the specified method.
191 *
192 * @param method the method for which to build the block map
193 * @param osrBCI the OSR bytecode index; {@code -1} if this is not an OSR
194 * @return the block map for the specified method
195 */
196 public BlockMap getBlockMap(RiMethod method, int osrBCI) {
197 // PERF: cache the block map for methods that are compiled or inlined often
198 BlockMap map = new BlockMap(method, hir.numberOfBlocks());
199 boolean isOsrCompilation = false;
200 if (osrBCI >= 0) {
201 map.addEntrypoint(osrBCI, BlockBegin.BlockFlag.OsrEntry);
202 isOsrCompilation = true;
203 }
204 if (!map.build(!isOsrCompilation && C1XOptions.PhiLoopStores)) {
205 throw new CiBailout("build of BlockMap failed for " + method);
206 } else {
207 if (compiler.isObserved()) {
208 String label = CiUtil.format("BlockListBuilder %f %r %H.%n(%p)", method, true);
209 compiler.fireCompilationEvent(new CompilationEvent(this, label, map, method.code().length));
210 }
211 }
212 map.cleanup();
213 stats.bytecodeCount += map.numberOfBytes();
214 stats.blockCount += map.numberOfBlocks();
215 return map;
216 }
217
218 /**
219 * Returns the frame map of this compilation.
220 * @return the frame map
221 */
222 public FrameMap frameMap() {
223 return frameMap;
224 }
225
226 public AbstractAssembler masm() {
227 if (assembler == null) {
228 assembler = compiler.backend.newAssembler(registerConfig);
229 assembler.setFrameSize(frameMap.frameSize());
230 assembler.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
231 }
232 return assembler;
233 }
234
235 public boolean hasExceptionHandlers() {
236 return hasExceptionHandlers;
237 }
238
239 /**
240 * Determines if this compilation has encountered any instructions (e.g. {@link Bytecodes#UNSAFE_CAST})
241 * that break the type safety invariant of the input bytecode.
242 */
243 public boolean isTypesafe() {
244 return typesafe;
245 }
246
247 public CiResult compile() {
248 CiTargetMethod targetMethod;
249 try {
250 emitHIR();
251 emitLIR();
252 targetMethod = emitCode();
253
254 if (C1XOptions.PrintMetrics) {
255 C1XMetrics.BytecodesCompiled += method.code().length;
256 }
257 } catch (CiBailout b) {
258 return new CiResult(null, b, stats);
259 } catch (Throwable t) {
260 return new CiResult(null, new CiBailout("Exception while compiling: " + method, t), stats);
261 } finally {
262 if (compiler.isObserved()) {
263 compiler.fireCompilationFinished(new CompilationEvent(this));
264 }
265 }
266
267 return new CiResult(targetMethod, null, stats);
268 }
269
270 public IR emitHIR() {
271 hir = new IR(this);
272 hir.build();
273 return hir;
274 }
275
276 public void initFrameMap(int numberOfLocks) {
277 frameMap = this.compiler.backend.newFrameMap(method, numberOfLocks);
278 }
279
280 private void emitLIR() {
281 if (C1XOptions.GenLIR) {
282 if (C1XOptions.PrintTimers) {
283 C1XTimers.LIR_CREATE.start();
284 }
285
286 initFrameMap(hir.topScope.maxLocks());
287
288 lirGenerator = compiler.backend.newLIRGenerator(this);
289 for (BlockBegin begin : hir.linearScanOrder()) {
290 lirGenerator.doBlock(begin);
291 }
292
293 if (C1XOptions.PrintTimers) {
294 C1XTimers.LIR_CREATE.stop();
295 }
296
297 new LinearScan(this, hir, lirGenerator, frameMap()).allocate();
298 }
299 }
300
301 private CiTargetMethod emitCode() {
302 if (C1XOptions.GenLIR && C1XOptions.GenCode) {
303 final LIRAssembler lirAssembler = compiler.backend.newLIRAssembler(this);
304 lirAssembler.emitCode(hir.linearScanOrder());
305
306 // generate code for slow cases
307 lirAssembler.emitLocalStubs();
308
309 // generate exception adapters
310 lirAssembler.emitExceptionEntries();
311
312 // generate deoptimization stubs
313 ArrayList<DeoptimizationStub> deoptimizationStubs = lirGenerator.deoptimizationStubs();
314 if (deoptimizationStubs != null) {
315 for (DeoptimizationStub stub : deoptimizationStubs) {
316 lirAssembler.emitDeoptizationStub(stub);
317 }
318 }
319
320 // generate traps at the end of the method
321 lirAssembler.emitTraps();
322
323 CiTargetMethod targetMethod = masm().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false);
324 if (assumptions.count() > 0) {
325 targetMethod.setAssumptions(assumptions);
326 }
327
328 if (compiler.isObserved()) {
329 compiler.fireCompilationEvent(new CompilationEvent(this, "After code generation", hir.startBlock, false, true, targetMethod));
330 }
331
332 if (C1XOptions.PrintTimers) {
333 C1XTimers.CODE_CREATE.stop();
334 }
335 return targetMethod;
336 }
337
338 return null;
339 }
340
341 public int nextID() {
342 return nextID++;
343 }
344
345 public static C1XCompilation compilation() {
346 C1XCompilation compilation = currentCompilation.get();
347 assert compilation != null;
348 return compilation;
349 }
350
351 public static C1XCompilation compilationOrNull() {
352 return currentCompilation.get();
353 }
354 }