comparison graal/com.oracle.max.cri/src/com/sun/cri/ci/CiTargetMethod.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children bc8527f3071c
comparison
equal deleted inserted replaced
3732:3e2e8b8abdaf 3733:e233f5660da4
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 package com.sun.cri.ci;
24
25 import java.io.*;
26 import java.util.*;
27
28 import com.sun.cri.ri.*;
29
30 /**
31 * Represents the output from compiling a method, including the compiled machine code, associated data and references,
32 * relocation information, deoptimization information, etc. It is the essential component of a {@link CiResult}, which also includes
33 * {@linkplain CiStatistics compilation statistics} and {@linkplain CiBailout failure information}.
34 */
35 public class CiTargetMethod implements Serializable {
36
37 /**
38 * Represents a code position with associated additional information.
39 */
40 public abstract static class Site implements Serializable {
41 /**
42 * The position (or offset) of this site with respect to the start of the target method.
43 */
44 public final int pcOffset;
45
46 public Site(int pos) {
47 this.pcOffset = pos;
48 }
49 }
50
51 /**
52 * Represents a safepoint with associated debug info.
53 */
54 public static class Safepoint extends Site implements Comparable<Safepoint> {
55 public final CiDebugInfo debugInfo;
56
57 Safepoint(int pcOffset, CiDebugInfo debugInfo) {
58 super(pcOffset);
59 this.debugInfo = debugInfo;
60 }
61
62 @Override
63 public String toString() {
64 StringBuilder sb = new StringBuilder();
65 sb.append(pcOffset);
66 sb.append("[<safepoint>]");
67 appendDebugInfo(sb, debugInfo);
68 return sb.toString();
69 }
70
71 @Override
72 public int compareTo(Safepoint o) {
73 if (pcOffset < o.pcOffset) {
74 return -1;
75 } else if (pcOffset > o.pcOffset) {
76 return 1;
77 }
78 return 0;
79 }
80 }
81
82 /**
83 * Represents a call in the code.
84 */
85 public static final class Call extends Safepoint {
86 /**
87 * The target of the call.
88 */
89 public final Object target;
90
91 /**
92 * The size of the call instruction.
93 */
94 public final int size;
95
96 /**
97 * Specifies if this call is direct or indirect. A direct call has an immediate operand encoding
98 * the absolute or relative (to the call itself) address of the target. An indirect call has a
99 * register or memory operand specifying the target address of the call.
100 */
101 public final boolean direct;
102
103 Call(Object target, int pcOffset, int size, boolean direct, CiDebugInfo debugInfo) {
104 super(pcOffset, debugInfo);
105 this.size = size;
106 this.target = target;
107 this.direct = direct;
108 }
109
110 @Override
111 public String toString() {
112 StringBuilder sb = new StringBuilder();
113 sb.append(pcOffset);
114 sb.append('[');
115 sb.append(target);
116 sb.append(']');
117
118 if (debugInfo != null) {
119 appendDebugInfo(sb, debugInfo);
120 }
121
122 return sb.toString();
123 }
124 }
125
126 /**
127 * Represents a reference to data from the code. The associated data can be any constant.
128 */
129 public static final class DataPatch extends Site {
130 public final CiConstant constant;
131 public final int alignment;
132
133 DataPatch(int pcOffset, CiConstant data, int alignment) {
134 super(pcOffset);
135 this.constant = data;
136 this.alignment = alignment;
137 }
138
139 @Override
140 public String toString() {
141 return String.format("%d[<data patch referring to data %s>]", pcOffset, constant);
142 }
143 }
144
145 /**
146 * Provides extra information about instructions or data at specific positions in {@link CiTargetMethod#targetCode()}.
147 * This is optional information that can be used to enhance a disassembly of the code.
148 */
149 public abstract static class CodeAnnotation implements Serializable {
150 public final int position;
151
152 public CodeAnnotation(int position) {
153 this.position = position;
154 }
155 }
156
157 /**
158 * A string comment about one or more instructions at a specific position in the code.
159 */
160 public static final class CodeComment extends CodeAnnotation {
161 public final String value;
162 public CodeComment(int position, String comment) {
163 super(position);
164 this.value = comment;
165 }
166
167 @Override
168 public String toString() {
169 return getClass().getSimpleName() + "@" + position + ": " + value;
170 }
171 }
172
173 /**
174 * Labels some inline data in the code.
175 */
176 public static final class InlineData extends CodeAnnotation {
177 public final int size;
178 public InlineData(int position, int size) {
179 super(position);
180 this.size = size;
181 }
182
183 @Override
184 public String toString() {
185 return getClass().getSimpleName() + "@" + position + ": size=" + size;
186 }
187 }
188
189 /**
190 * Describes a table of signed offsets embedded in the code. The offsets are relative to the starting
191 * address of the table. This type of table maybe generated when translating a multi-way branch
192 * based on a key value from a dense value set (e.g. the {@code tableswitch} JVM instruction).
193 *
194 * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high} inclusive.
195 */
196 public static final class JumpTable extends CodeAnnotation {
197 /**
198 * The low value in the key range (inclusive).
199 */
200 public final int low;
201
202 /**
203 * The high value in the key range (inclusive).
204 */
205 public final int high;
206
207 /**
208 * The size (in bytes) of each table entry.
209 */
210 public final int entrySize;
211
212 public JumpTable(int position, int low, int high, int entrySize) {
213 super(position);
214 this.low = low;
215 this.high = high;
216 this.entrySize = entrySize;
217 }
218
219 @Override
220 public String toString() {
221 return getClass().getSimpleName() + "@" + position + ": [" + low + " .. " + high + "]";
222 }
223 }
224
225 /**
226 * Describes a table of key and offset pairs. The offset in each table entry is relative to the address of
227 * the table. This type of table maybe generated when translating a multi-way branch
228 * based on a key value from a sparse value set (e.g. the {@code lookupswitch} JVM instruction).
229 */
230 public static final class LookupTable extends CodeAnnotation {
231 /**
232 * The number of entries in the table.
233 */
234 public final int npairs;
235
236 /**
237 * The size (in bytes) of entry's key.
238 */
239 public final int keySize;
240
241 /**
242 * The size (in bytes) of entry's offset value.
243 */
244 public final int offsetSize;
245
246 public LookupTable(int position, int npairs, int keySize, int offsetSize) {
247 super(position);
248 this.npairs = npairs;
249 this.keySize = keySize;
250 this.offsetSize = offsetSize;
251 }
252
253 @Override
254 public String toString() {
255 return getClass().getSimpleName() + "@" + position + ": [npairs=" + npairs + ", keySize=" + keySize + ", offsetSize=" + offsetSize + "]";
256 }
257 }
258
259 /**
260 * Represents exception handler information for a specific code position. It includes the catch code position as
261 * well as the caught exception type.
262 */
263 public static final class ExceptionHandler extends Site {
264 public final int bci;
265 public final int scopeLevel;
266 public final int handlerPos;
267 public final int handlerBci;
268 public final RiType exceptionType;
269
270 ExceptionHandler(int pcOffset, int bci, int scopeLevel, int handlerPos, int handlerBci, RiType exceptionType) {
271 super(pcOffset);
272 this.bci = bci;
273 this.scopeLevel = scopeLevel;
274 this.handlerPos = handlerPos;
275 this.handlerBci = handlerBci;
276 this.exceptionType = exceptionType;
277 }
278
279 @Override
280 public String toString() {
281 return String.format("%d[<exception edge to %d with type %s>]", pcOffset, handlerPos, (exceptionType == null) ? "null" : exceptionType);
282 }
283 }
284
285 public static final class Mark extends Site {
286 public final Object id;
287 public final Mark[] references;
288
289 Mark(int pcOffset, Object id, Mark[] references) {
290 super(pcOffset);
291 this.id = id;
292 this.references = references;
293 }
294
295 @Override
296 public String toString() {
297 if (id == null) {
298 return String.format("%d[<mark with %d references>]", pcOffset, references.length);
299 } else if (id instanceof Integer) {
300 return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, Integer.toHexString((Integer) id));
301 } else {
302 return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, id.toString());
303 }
304 }
305 }
306
307 /**
308 * List of safepoints, sorted by {@link Site#pcOffset}.
309 */
310 public final List<Safepoint> safepoints = new ArrayList<Safepoint>();
311
312 /**
313 * List of data references.
314 */
315 public final List<DataPatch> dataReferences = new ArrayList<DataPatch>();
316
317 /**
318 * List of exception handlers.
319 */
320 public final List<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>();
321
322 /**
323 * List of marks.
324 */
325 public final List<Mark> marks = new ArrayList<Mark>();
326
327 private int frameSize = -1;
328 private int customStackAreaOffset = -1;
329 private int registerRestoreEpilogueOffset = -1;
330 private int deoptReturnAddressOffset;
331
332 /**
333 * The buffer containing the emitted machine code.
334 */
335 private byte[] targetCode;
336
337 /**
338 * The leading number of bytes in {@link #targetCode} containing the emitted machine code.
339 */
340 private int targetCodeSize;
341
342 private ArrayList<CodeAnnotation> annotations;
343
344 private CiAssumptions assumptions;
345
346 /**
347 * Constructs a new target method.
348 */
349 public CiTargetMethod() {
350 }
351
352 public void setAssumptions(CiAssumptions assumptions) {
353 this.assumptions = assumptions;
354 }
355
356 public CiAssumptions assumptions() {
357 return assumptions;
358 }
359
360 /**
361 * Sets the frame size in bytes. Does not include the return address pushed onto the
362 * stack, if any.
363 *
364 * @param size the size of the frame in bytes
365 */
366 public void setFrameSize(int size) {
367 frameSize = size;
368 }
369
370 /**
371 * Sets the machine that has been generated by the compiler.
372 *
373 * @param code the machine code generated
374 * @param size the size of the machine code
375 */
376 public void setTargetCode(byte[] code, int size) {
377 targetCode = code;
378 targetCodeSize = size;
379 }
380
381 /**
382 * Records a reference to the data section in the code section (e.g. to load an integer or floating point constant).
383 *
384 * @param codePos the position in the code where the data reference occurs
385 * @param data the data that is referenced
386 * @param alignment the alignment requirement of the data or 0 if there is no alignment requirement
387 */
388 public void recordDataReference(int codePos, CiConstant data, int alignment) {
389 assert codePos >= 0 && data != null;
390 dataReferences.add(new DataPatch(codePos, data, alignment));
391 }
392
393 /**
394 * Records a call in the code array.
395 *
396 * @param codePos the position of the call in the code array
397 * @param size the size of the call instruction
398 * @param target the {@link RiRuntime#asCallTarget(Object) target} being called
399 * @param debugInfo the debug info for the call
400 * @param direct specifies if this is a {@linkplain Call#direct direct} call
401 */
402 public void recordCall(int codePos, int size, Object target, CiDebugInfo debugInfo, boolean direct) {
403 final Call call = new Call(target, codePos, size, direct, debugInfo);
404 addSafepoint(call);
405 }
406
407 /**
408 * Records an exception handler for this method.
409 *
410 * @param codePos the position in the code that is covered by the handler
411 * @param handlerPos the position of the handler
412 * @param throwableType the type of exceptions handled by the handler
413 */
414 public void recordExceptionHandler(int codePos, int bci, int scopeLevel, int handlerPos, int handlerBci, RiType throwableType) {
415 exceptionHandlers.add(new ExceptionHandler(codePos, bci, scopeLevel, handlerPos, handlerBci, throwableType));
416 }
417
418 /**
419 * Records a safepoint in the code array.
420 *
421 * @param codePos the position of the safepoint in the code array
422 * @param debugInfo the debug info for the safepoint
423 */
424 public void recordSafepoint(int codePos, CiDebugInfo debugInfo) {
425 addSafepoint(new Safepoint(codePos, debugInfo));
426 }
427
428 private void addSafepoint(Safepoint safepoint) {
429 // The safepoints list must always be sorted
430 if (!safepoints.isEmpty() && safepoints.get(safepoints.size() - 1).pcOffset >= safepoint.pcOffset) {
431 // This re-sorting should be very rare
432 Collections.sort(safepoints);
433 }
434 safepoints.add(safepoint);
435 }
436
437 /**
438 * Records an instruction mark within this method.
439 *
440 * @param codePos the position in the code that is covered by the handler
441 * @param id the identifier for this mark
442 * @param references an array of other marks that this mark references
443 */
444 public Mark recordMark(int codePos, Object id, Mark[] references) {
445 Mark mark = new Mark(codePos, id, references);
446 marks.add(mark);
447 return mark;
448 }
449
450 /**
451 * Allows a method to specify the offset of the epilogue that restores the callee saved registers. Must be called
452 * iff the method is a callee saved method and stores callee registers on the stack.
453 *
454 * @param registerRestoreEpilogueOffset the offset in the machine code where the epilogue begins
455 */
456 public void setRegisterRestoreEpilogueOffset(int registerRestoreEpilogueOffset) {
457 assert this.registerRestoreEpilogueOffset == -1;
458 this.registerRestoreEpilogueOffset = registerRestoreEpilogueOffset;
459 }
460
461 /**
462 * The frame size of the method in bytes.
463 *
464 * @return the frame size
465 */
466 public int frameSize() {
467 assert frameSize != -1 : "frame size not yet initialized!";
468 return frameSize;
469 }
470
471 /**
472 * @return the code offset of the start of the epilogue that restores all callee saved registers, or -1 if this is
473 * not a callee saved method
474 */
475 public int registerRestoreEpilogueOffset() {
476 return registerRestoreEpilogueOffset;
477 }
478
479 /**
480 * Offset in bytes for the custom stack area (relative to sp).
481 * @return the offset in bytes
482 */
483 public int customStackAreaOffset() {
484 return customStackAreaOffset;
485 }
486
487 /**
488 * @see #customStackAreaOffset()
489 * @param offset
490 */
491 public void setCustomStackAreaOffset(int offset) {
492 customStackAreaOffset = offset;
493 }
494
495 /**
496 * @return the machine code generated for this method
497 */
498 public byte[] targetCode() {
499 return targetCode;
500 }
501
502 /**
503 * @return the size of the machine code generated for this method
504 */
505 public int targetCodeSize() {
506 return targetCodeSize;
507 }
508
509 /**
510 * @return the code annotations or {@code null} if there are none
511 */
512 public List<CodeAnnotation> annotations() {
513 return annotations;
514 }
515
516 public void addAnnotation(CodeAnnotation annotation) {
517 assert annotation != null;
518 if (annotations == null) {
519 annotations = new ArrayList<CiTargetMethod.CodeAnnotation>();
520 }
521 annotations.add(annotation);
522 }
523
524 private static void appendDebugInfo(StringBuilder sb, CiDebugInfo info) {
525 if (info != null) {
526 appendRefMap(sb, "stackMap", info.frameRefMap);
527 appendRefMap(sb, "registerMap", info.registerRefMap);
528 CiCodePos codePos = info.codePos;
529 if (codePos != null) {
530 CiUtil.appendLocation(sb.append(" "), codePos.method, codePos.bci);
531 if (info.hasFrame()) {
532 sb.append(" #locals=").append(info.frame().numLocals).append(" #expr=").append(info.frame().numStack);
533 if (info.frame().numLocks > 0) {
534 sb.append(" #locks=").append(info.frame().numLocks);
535 }
536 }
537 }
538 }
539 }
540
541 private static void appendRefMap(StringBuilder sb, String name, CiBitMap map) {
542 if (map != null) {
543 sb.append(' ').append(name).append('[').append(map.toBinaryString(-1)).append(']');
544 }
545 }
546 }