comparison graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java @ 4199:aaac4894175c

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