1 /* 2 * Copyright (c) 2013, 2018, 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 25 package org.graalvm.compiler.lir.asm; 26 27 import static jdk.vm.ci.code.ValueUtil.asStackSlot; 28 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 29 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; 30 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.function.Consumer; 36 37 import jdk.internal.vm.compiler.collections.EconomicMap; 38 import jdk.internal.vm.compiler.collections.Equivalence; 39 import org.graalvm.compiler.asm.AbstractAddress; 40 import org.graalvm.compiler.asm.Assembler; 41 import org.graalvm.compiler.code.CompilationResult; 42 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; 43 import org.graalvm.compiler.code.DataSection.Data; 44 import org.graalvm.compiler.code.DataSection.RawData; 45 import org.graalvm.compiler.core.common.NumUtil; 46 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 47 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; 48 import org.graalvm.compiler.core.common.type.DataPointerConstant; 49 import org.graalvm.compiler.debug.Assertions; 50 import org.graalvm.compiler.debug.DebugContext; 51 import org.graalvm.compiler.debug.GraalError; 52 import org.graalvm.compiler.graph.NodeSourcePosition; 53 import org.graalvm.compiler.lir.LIR; 54 import org.graalvm.compiler.lir.LIRFrameState; 55 import org.graalvm.compiler.lir.LIRInstruction; 56 import org.graalvm.compiler.lir.LabelRef; 57 import org.graalvm.compiler.lir.framemap.FrameMap; 58 import org.graalvm.compiler.options.Option; 59 import org.graalvm.compiler.options.OptionKey; 60 import org.graalvm.compiler.options.OptionType; 61 import org.graalvm.compiler.options.OptionValues; 62 63 import jdk.vm.ci.code.CodeCacheProvider; 64 import jdk.vm.ci.code.DebugInfo; 65 import jdk.vm.ci.code.Register; 66 import jdk.vm.ci.code.StackSlot; 67 import jdk.vm.ci.code.TargetDescription; 68 import jdk.vm.ci.code.site.ConstantReference; 69 import jdk.vm.ci.code.site.DataSectionReference; 70 import jdk.vm.ci.code.site.InfopointReason; 71 import jdk.vm.ci.code.site.Mark; 72 import jdk.vm.ci.meta.Constant; 73 import jdk.vm.ci.meta.InvokeTarget; 74 import jdk.vm.ci.meta.JavaConstant; 75 import jdk.vm.ci.meta.JavaKind; 76 import jdk.vm.ci.meta.VMConstant; 77 import jdk.vm.ci.meta.Value; 78 79 /** 80 * Fills in a {@link CompilationResult} as its code is being assembled. 81 * 82 * @see CompilationResultBuilderFactory 83 */ 84 public class CompilationResultBuilder { 85 86 public static class Options { 87 @Option(help = "Include the LIR as comments with the final assembly.", type = OptionType.Debug) // 88 public static final OptionKey<Boolean> PrintLIRWithAssembly = new OptionKey<>(false); 89 } 90 91 private static class ExceptionInfo { 92 93 public final int codeOffset; 94 public final LabelRef exceptionEdge; 95 ExceptionInfo(int pcOffset, LabelRef exceptionEdge)96 ExceptionInfo(int pcOffset, LabelRef exceptionEdge) { 97 this.codeOffset = pcOffset; 98 this.exceptionEdge = exceptionEdge; 99 } 100 } 101 102 /** 103 * Wrapper for a code annotation that was produced by the {@link Assembler}. 104 */ 105 public static final class AssemblerAnnotation extends CodeAnnotation { 106 107 public final Assembler.CodeAnnotation assemblerCodeAnnotation; 108 AssemblerAnnotation(Assembler.CodeAnnotation assemblerCodeAnnotation)109 public AssemblerAnnotation(Assembler.CodeAnnotation assemblerCodeAnnotation) { 110 super(assemblerCodeAnnotation.instructionPosition); 111 this.assemblerCodeAnnotation = assemblerCodeAnnotation; 112 } 113 114 @Override equals(Object obj)115 public boolean equals(Object obj) { 116 return this == obj; 117 } 118 119 @Override toString()120 public String toString() { 121 return assemblerCodeAnnotation.toString(); 122 } 123 } 124 125 public final Assembler asm; 126 public final DataBuilder dataBuilder; 127 public final CompilationResult compilationResult; 128 public final Register nullRegister; 129 public final TargetDescription target; 130 public final CodeCacheProvider codeCache; 131 public final ForeignCallsProvider foreignCalls; 132 public final FrameMap frameMap; 133 134 /** 135 * The LIR for which code is being generated. 136 */ 137 protected LIR lir; 138 139 /** 140 * The index of the block currently being emitted. 141 */ 142 protected int currentBlockIndex; 143 144 /** 145 * The object that emits code for managing a method's frame. 146 */ 147 public final FrameContext frameContext; 148 149 private List<ExceptionInfo> exceptionInfoList; 150 151 private final OptionValues options; 152 private final DebugContext debug; 153 private final EconomicMap<Constant, Data> dataCache; 154 155 private Consumer<LIRInstruction> beforeOp; 156 private Consumer<LIRInstruction> afterOp; 157 mustReplaceWithNullRegister(JavaConstant nullConstant)158 public final boolean mustReplaceWithNullRegister(JavaConstant nullConstant) { 159 return !nullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant); 160 } 161 CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister)162 public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, 163 OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) { 164 this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister, EconomicMap.create(Equivalence.DEFAULT)); 165 } 166 CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister, EconomicMap<Constant, Data> dataCache)167 public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, 168 OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister, EconomicMap<Constant, Data> dataCache) { 169 this.target = codeCache.getTarget(); 170 this.codeCache = codeCache; 171 this.foreignCalls = foreignCalls; 172 this.frameMap = frameMap; 173 this.asm = asm; 174 this.dataBuilder = dataBuilder; 175 this.compilationResult = compilationResult; 176 this.nullRegister = nullRegister; 177 this.frameContext = frameContext; 178 this.options = options; 179 this.debug = debug; 180 assert frameContext != null; 181 this.dataCache = dataCache; 182 183 if (dataBuilder.needDetailedPatchingInformation() || Assertions.assertionsEnabled()) { 184 /* 185 * Always enabled in debug mode, even when the VM does not request detailed information, 186 * to increase test coverage. 187 */ 188 asm.setCodePatchingAnnotationConsumer(assemblerCodeAnnotation -> compilationResult.addAnnotation(new AssemblerAnnotation(assemblerCodeAnnotation))); 189 } 190 } 191 setTotalFrameSize(int frameSize)192 public void setTotalFrameSize(int frameSize) { 193 compilationResult.setTotalFrameSize(frameSize); 194 } 195 setMaxInterpreterFrameSize(int maxInterpreterFrameSize)196 public void setMaxInterpreterFrameSize(int maxInterpreterFrameSize) { 197 compilationResult.setMaxInterpreterFrameSize(maxInterpreterFrameSize); 198 } 199 recordMark(Object id)200 public Mark recordMark(Object id) { 201 return compilationResult.recordMark(asm.position(), id); 202 } 203 blockComment(String s)204 public void blockComment(String s) { 205 compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.position(), s)); 206 } 207 208 /** 209 * Sets the {@linkplain CompilationResult#setTargetCode(byte[], int) code} and 210 * {@linkplain CompilationResult#recordExceptionHandler(int, int) exception handler} fields of 211 * the compilation result and then {@linkplain #closeCompilationResult() closes} it. 212 */ finish()213 public void finish() { 214 int position = asm.position(); 215 compilationResult.setTargetCode(asm.close(false), position); 216 217 // Record exception handlers if they exist 218 if (exceptionInfoList != null) { 219 for (ExceptionInfo ei : exceptionInfoList) { 220 int codeOffset = ei.codeOffset; 221 compilationResult.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position()); 222 } 223 } 224 closeCompilationResult(); 225 } 226 227 /** 228 * Calls {@link CompilationResult#close()} on {@link #compilationResult}. 229 */ closeCompilationResult()230 protected void closeCompilationResult() { 231 compilationResult.close(); 232 } 233 recordExceptionHandlers(int pcOffset, LIRFrameState info)234 public void recordExceptionHandlers(int pcOffset, LIRFrameState info) { 235 if (info != null) { 236 if (info.exceptionEdge != null) { 237 if (exceptionInfoList == null) { 238 exceptionInfoList = new ArrayList<>(4); 239 } 240 exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge)); 241 } 242 } 243 } 244 recordImplicitException(int pcOffset, LIRFrameState info)245 public void recordImplicitException(int pcOffset, LIRFrameState info) { 246 compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION); 247 assert info.exceptionEdge == null; 248 } 249 recordDirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info)250 public void recordDirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) { 251 DebugInfo debugInfo = info != null ? info.debugInfo() : null; 252 compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true); 253 } 254 recordIndirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info)255 public void recordIndirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) { 256 DebugInfo debugInfo = info != null ? info.debugInfo() : null; 257 compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); 258 } 259 recordInfopoint(int pos, LIRFrameState info, InfopointReason reason)260 public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) { 261 // infopoints always need debug info 262 DebugInfo debugInfo = info.debugInfo(); 263 recordInfopoint(pos, debugInfo, reason); 264 } 265 recordInfopoint(int pos, DebugInfo debugInfo, InfopointReason reason)266 public void recordInfopoint(int pos, DebugInfo debugInfo, InfopointReason reason) { 267 compilationResult.recordInfopoint(pos, debugInfo, reason); 268 } 269 recordSourceMapping(int pcOffset, int endPcOffset, NodeSourcePosition sourcePosition)270 public void recordSourceMapping(int pcOffset, int endPcOffset, NodeSourcePosition sourcePosition) { 271 compilationResult.recordSourceMapping(pcOffset, endPcOffset, sourcePosition); 272 } 273 recordInlineDataInCode(Constant data)274 public void recordInlineDataInCode(Constant data) { 275 assert data != null; 276 int pos = asm.position(); 277 debug.log("Inline data in code: pos = %d, data = %s", pos, data); 278 if (data instanceof VMConstant) { 279 compilationResult.recordDataPatch(pos, new ConstantReference((VMConstant) data)); 280 } 281 } 282 recordInlineDataInCodeWithNote(Constant data, Object note)283 public void recordInlineDataInCodeWithNote(Constant data, Object note) { 284 assert data != null; 285 int pos = asm.position(); 286 debug.log("Inline data in code: pos = %d, data = %s, note = %s", pos, data, note); 287 if (data instanceof VMConstant) { 288 compilationResult.recordDataPatchWithNote(pos, new ConstantReference((VMConstant) data), note); 289 } 290 } 291 recordDataSectionReference(Data data)292 public AbstractAddress recordDataSectionReference(Data data) { 293 assert data != null; 294 DataSectionReference reference = compilationResult.getDataSection().insertData(data); 295 int instructionStart = asm.position(); 296 compilationResult.recordDataPatch(instructionStart, reference); 297 return asm.getPlaceholder(instructionStart); 298 } 299 recordDataReferenceInCode(DataPointerConstant constant)300 public AbstractAddress recordDataReferenceInCode(DataPointerConstant constant) { 301 return recordDataReferenceInCode(constant, constant.getAlignment()); 302 } 303 recordDataReferenceInCode(Constant constant, int alignment)304 public AbstractAddress recordDataReferenceInCode(Constant constant, int alignment) { 305 assert constant != null; 306 debug.log("Constant reference in code: pos = %d, data = %s", asm.position(), constant); 307 Data data = createDataItem(constant); 308 data.updateAlignment(alignment); 309 return recordDataSectionReference(data); 310 } 311 recordDataReferenceInCode(Data data, int alignment)312 public AbstractAddress recordDataReferenceInCode(Data data, int alignment) { 313 assert data != null; 314 data.updateAlignment(alignment); 315 return recordDataSectionReference(data); 316 } 317 createDataItem(Constant constant)318 public Data createDataItem(Constant constant) { 319 Data data = dataCache.get(constant); 320 if (data == null) { 321 data = dataBuilder.createDataItem(constant); 322 dataCache.put(constant, data); 323 } 324 return data; 325 } 326 recordDataReferenceInCode(byte[] data, int alignment)327 public AbstractAddress recordDataReferenceInCode(byte[] data, int alignment) { 328 assert data != null; 329 if (debug.isLogEnabled()) { 330 debug.log("Data reference in code: pos = %d, data = %s", asm.position(), Arrays.toString(data)); 331 } 332 return recordDataSectionReference(new RawData(data, alignment)); 333 } 334 335 /** 336 * Notifies this object of a branch instruction at offset {@code pcOffset} in the code. 337 * 338 * @param isNegated negation status of the branch's condition. 339 */ 340 @SuppressWarnings("unused") recordBranch(int pcOffset, boolean isNegated)341 public void recordBranch(int pcOffset, boolean isNegated) { 342 } 343 344 /** 345 * Notifies this object of a call instruction belonging to an INVOKEVIRTUAL or INVOKEINTERFACE 346 * at offset {@code pcOffset} in the code. 347 * 348 * @param nodeSourcePosition source position of the corresponding invoke. 349 */ 350 @SuppressWarnings("unused") recordInvokeVirtualOrInterfaceCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition)351 public void recordInvokeVirtualOrInterfaceCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) { 352 } 353 354 /** 355 * Notifies this object of a call instruction belonging to an INLINE_INVOKE at offset 356 * {@code pcOffset} in the code. 357 * 358 * @param nodeSourcePosition source position of the corresponding invoke. 359 */ 360 @SuppressWarnings("unused") recordInlineInvokeCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition)361 public void recordInlineInvokeCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) { 362 } 363 364 /** 365 * Returns the integer value of any constant that can be represented by a 32-bit integer value, 366 * including long constants that fit into the 32-bit range. 367 */ asIntConst(Value value)368 public int asIntConst(Value value) { 369 assert isJavaConstant(value) && asJavaConstant(value).getJavaKind().isNumericInteger(); 370 JavaConstant constant = asJavaConstant(value); 371 long c = constant.asLong(); 372 if (!NumUtil.isInt(c)) { 373 throw GraalError.shouldNotReachHere(); 374 } 375 return (int) c; 376 } 377 378 /** 379 * Returns the float value of any constant that can be represented by a 32-bit float value. 380 */ asFloatConst(Value value)381 public float asFloatConst(Value value) { 382 assert isJavaConstant(value) && asJavaConstant(value).getJavaKind() == JavaKind.Float; 383 JavaConstant constant = asJavaConstant(value); 384 return constant.asFloat(); 385 } 386 387 /** 388 * Returns the long value of any constant that can be represented by a 64-bit long value. 389 */ asLongConst(Value value)390 public long asLongConst(Value value) { 391 assert isJavaConstant(value) && asJavaConstant(value).getJavaKind() == JavaKind.Long; 392 JavaConstant constant = asJavaConstant(value); 393 return constant.asLong(); 394 } 395 396 /** 397 * Returns the double value of any constant that can be represented by a 64-bit float value. 398 */ asDoubleConst(Value value)399 public double asDoubleConst(Value value) { 400 assert isJavaConstant(value) && asJavaConstant(value).getJavaKind() == JavaKind.Double; 401 JavaConstant constant = asJavaConstant(value); 402 return constant.asDouble(); 403 } 404 405 /** 406 * Returns the address of a float constant that is embedded as a data reference into the code. 407 */ asFloatConstRef(JavaConstant value)408 public AbstractAddress asFloatConstRef(JavaConstant value) { 409 return asFloatConstRef(value, 4); 410 } 411 asFloatConstRef(JavaConstant value, int alignment)412 public AbstractAddress asFloatConstRef(JavaConstant value, int alignment) { 413 assert value.getJavaKind() == JavaKind.Float; 414 return recordDataReferenceInCode(value, alignment); 415 } 416 417 /** 418 * Returns the address of a double constant that is embedded as a data reference into the code. 419 */ asDoubleConstRef(JavaConstant value)420 public AbstractAddress asDoubleConstRef(JavaConstant value) { 421 return asDoubleConstRef(value, 8); 422 } 423 asDoubleConstRef(JavaConstant value, int alignment)424 public AbstractAddress asDoubleConstRef(JavaConstant value, int alignment) { 425 assert value.getJavaKind() == JavaKind.Double; 426 return recordDataReferenceInCode(value, alignment); 427 } 428 429 /** 430 * Returns the address of a long constant that is embedded as a data reference into the code. 431 */ asLongConstRef(JavaConstant value)432 public AbstractAddress asLongConstRef(JavaConstant value) { 433 assert value.getJavaKind() == JavaKind.Long; 434 return recordDataReferenceInCode(value, 8); 435 } 436 437 /** 438 * Returns the address of an object constant that is embedded as a data reference into the code. 439 */ asObjectConstRef(JavaConstant value)440 public AbstractAddress asObjectConstRef(JavaConstant value) { 441 assert value.getJavaKind() == JavaKind.Object; 442 return recordDataReferenceInCode(value, 8); 443 } 444 asByteAddr(Value value)445 public AbstractAddress asByteAddr(Value value) { 446 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Byte.getByteCount(); 447 return asAddress(value); 448 } 449 asShortAddr(Value value)450 public AbstractAddress asShortAddr(Value value) { 451 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Short.getByteCount(); 452 return asAddress(value); 453 } 454 asIntAddr(Value value)455 public AbstractAddress asIntAddr(Value value) { 456 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Int.getByteCount(); 457 return asAddress(value); 458 } 459 asLongAddr(Value value)460 public AbstractAddress asLongAddr(Value value) { 461 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Long.getByteCount(); 462 return asAddress(value); 463 } 464 asFloatAddr(Value value)465 public AbstractAddress asFloatAddr(Value value) { 466 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Float.getByteCount(); 467 return asAddress(value); 468 } 469 asDoubleAddr(Value value)470 public AbstractAddress asDoubleAddr(Value value) { 471 assert value.getPlatformKind().getSizeInBytes() >= JavaKind.Double.getByteCount(); 472 return asAddress(value); 473 } 474 asAddress(Value value)475 public AbstractAddress asAddress(Value value) { 476 assert isStackSlot(value); 477 StackSlot slot = asStackSlot(value); 478 return asm.makeAddress(frameMap.getRegisterConfig().getFrameRegister(), frameMap.offsetForStackSlot(slot)); 479 } 480 481 /** 482 * Determines if a given edge from the block currently being emitted goes to its lexical 483 * successor. 484 */ isSuccessorEdge(LabelRef edge)485 public boolean isSuccessorEdge(LabelRef edge) { 486 assert lir != null; 487 AbstractBlockBase<?>[] order = lir.codeEmittingOrder(); 488 assert order[currentBlockIndex] == edge.getSourceBlock(); 489 AbstractBlockBase<?> nextBlock = LIR.getNextBlock(order, currentBlockIndex); 490 return nextBlock == edge.getTargetBlock(); 491 } 492 493 /** 494 * Emits code for {@code lir} in its {@linkplain LIR#codeEmittingOrder() code emitting order}. 495 */ emit(@uppressWarningsR) LIR lir)496 public void emit(@SuppressWarnings("hiding") LIR lir) { 497 assert this.lir == null; 498 assert currentBlockIndex == 0; 499 this.lir = lir; 500 this.currentBlockIndex = 0; 501 frameContext.enter(this); 502 for (AbstractBlockBase<?> b : lir.codeEmittingOrder()) { 503 assert (b == null && lir.codeEmittingOrder()[currentBlockIndex] == null) || lir.codeEmittingOrder()[currentBlockIndex].equals(b); 504 emitBlock(b); 505 currentBlockIndex++; 506 } 507 this.lir = null; 508 this.currentBlockIndex = 0; 509 } 510 emitBlock(AbstractBlockBase<?> block)511 private void emitBlock(AbstractBlockBase<?> block) { 512 if (block == null) { 513 return; 514 } 515 boolean emitComment = debug.isDumpEnabled(DebugContext.BASIC_LEVEL) || Options.PrintLIRWithAssembly.getValue(getOptions()); 516 if (emitComment) { 517 blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); 518 } 519 520 for (LIRInstruction op : lir.getLIRforBlock(block)) { 521 if (emitComment) { 522 blockComment(String.format("%d %s", op.id(), op)); 523 } 524 525 try { 526 if (beforeOp != null) { 527 beforeOp.accept(op); 528 } 529 emitOp(this, op); 530 if (afterOp != null) { 531 afterOp.accept(op); 532 } 533 } catch (GraalError e) { 534 throw e.addContext("lir instruction", block + "@" + op.id() + " " + op.getClass().getName() + " " + op + "\n" + Arrays.toString(lir.codeEmittingOrder())); 535 } 536 } 537 } 538 emitOp(CompilationResultBuilder crb, LIRInstruction op)539 private static void emitOp(CompilationResultBuilder crb, LIRInstruction op) { 540 try { 541 int start = crb.asm.position(); 542 op.emitCode(crb); 543 if (op.getPosition() != null) { 544 crb.recordSourceMapping(start, crb.asm.position(), op.getPosition()); 545 } 546 } catch (AssertionError t) { 547 throw new GraalError(t); 548 } catch (RuntimeException t) { 549 throw new GraalError(t); 550 } 551 } 552 resetForEmittingCode()553 public void resetForEmittingCode() { 554 asm.reset(); 555 compilationResult.resetForEmittingCode(); 556 if (exceptionInfoList != null) { 557 exceptionInfoList.clear(); 558 } 559 if (dataCache != null) { 560 dataCache.clear(); 561 } 562 } 563 setOpCallback(Consumer<LIRInstruction> beforeOp, Consumer<LIRInstruction> afterOp)564 public void setOpCallback(Consumer<LIRInstruction> beforeOp, Consumer<LIRInstruction> afterOp) { 565 this.beforeOp = beforeOp; 566 this.afterOp = afterOp; 567 } 568 getOptions()569 public OptionValues getOptions() { 570 return options; 571 } 572 573 } 574