Mercurial > hg > graal-compiler
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 } |