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 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 158 public final boolean mustReplaceWithNullRegister(JavaConstant nullConstant) { 159 return !nullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant); 160 } 161 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 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 192 public void setTotalFrameSize(int frameSize) { 193 compilationResult.setTotalFrameSize(frameSize); 194 } 195 196 public void setMaxInterpreterFrameSize(int maxInterpreterFrameSize) { 197 compilationResult.setMaxInterpreterFrameSize(maxInterpreterFrameSize); 198 } 199 200 public Mark recordMark(Object id) { 201 return compilationResult.recordMark(asm.position(), id); 202 } 203 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 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 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 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 564 public void setOpCallback(Consumer<LIRInstruction> beforeOp, Consumer<LIRInstruction> afterOp) { 565 this.beforeOp = beforeOp; 566 this.afterOp = afterOp; 567 } 568 569 public OptionValues getOptions() { 570 return options; 571 } 572 573 } | 1 /* 2 * Copyright (c) 2013, 2019, 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.asm.Label; 42 import org.graalvm.compiler.code.CompilationResult; 43 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; 44 import org.graalvm.compiler.code.DataSection.Data; 45 import org.graalvm.compiler.code.DataSection.RawData; 46 import org.graalvm.compiler.core.common.NumUtil; 47 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 48 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; 49 import org.graalvm.compiler.core.common.type.DataPointerConstant; 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.StandardOp.LabelHoldingOp; 58 import org.graalvm.compiler.lir.framemap.FrameMap; 59 import org.graalvm.compiler.options.Option; 60 import org.graalvm.compiler.options.OptionKey; 61 import org.graalvm.compiler.options.OptionType; 62 import org.graalvm.compiler.options.OptionValues; 63 64 import jdk.vm.ci.code.BailoutException; 65 import jdk.vm.ci.code.CodeCacheProvider; 66 import jdk.vm.ci.code.DebugInfo; 67 import jdk.vm.ci.code.Register; 68 import jdk.vm.ci.code.StackSlot; 69 import jdk.vm.ci.code.TargetDescription; 70 import jdk.vm.ci.code.site.ConstantReference; 71 import jdk.vm.ci.code.site.DataSectionReference; 72 import jdk.vm.ci.code.site.InfopointReason; 73 import jdk.vm.ci.code.site.Mark; 74 import jdk.vm.ci.meta.Constant; 75 import jdk.vm.ci.meta.InvokeTarget; 76 import jdk.vm.ci.meta.JavaConstant; 77 import jdk.vm.ci.meta.JavaKind; 78 import jdk.vm.ci.meta.VMConstant; 79 import jdk.vm.ci.meta.Value; 80 81 /** 82 * Fills in a {@link CompilationResult} as its code is being assembled. 83 * 84 * @see CompilationResultBuilderFactory 140 141 /** 142 * The index of the block currently being emitted. 143 */ 144 protected int currentBlockIndex; 145 146 /** 147 * The object that emits code for managing a method's frame. 148 */ 149 public final FrameContext frameContext; 150 151 private List<ExceptionInfo> exceptionInfoList; 152 153 private final OptionValues options; 154 private final DebugContext debug; 155 private final EconomicMap<Constant, Data> dataCache; 156 157 private Consumer<LIRInstruction> beforeOp; 158 private Consumer<LIRInstruction> afterOp; 159 160 /** 161 * These position maps are used for estimating offsets of forward branches. Used for 162 * architectures where certain branch instructions have limited displacement such as ARM tbz or 163 * SPARC cbcond. 164 */ 165 private EconomicMap<Label, Integer> labelBindLirPositions; 166 private EconomicMap<LIRInstruction, Integer> lirPositions; 167 /** 168 * This flag is for setting the 169 * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, Label, int)} into a 170 * conservative mode and always answering false. 171 */ 172 private boolean conservativeLabelOffsets = false; 173 174 public final boolean mustReplaceWithNullRegister(JavaConstant nullConstant) { 175 return !nullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant); 176 } 177 178 public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, 179 OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) { 180 this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister, EconomicMap.create(Equivalence.DEFAULT)); 181 } 182 183 public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, 184 OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister, EconomicMap<Constant, Data> dataCache) { 185 this.target = codeCache.getTarget(); 186 this.codeCache = codeCache; 187 this.foreignCalls = foreignCalls; 188 this.frameMap = frameMap; 189 this.asm = asm; 190 this.dataBuilder = dataBuilder; 191 this.compilationResult = compilationResult; 192 this.nullRegister = nullRegister; 193 this.frameContext = frameContext; 194 this.options = options; 195 this.debug = debug; 196 assert frameContext != null; 197 this.dataCache = dataCache; 198 } 199 200 public void setTotalFrameSize(int frameSize) { 201 compilationResult.setTotalFrameSize(frameSize); 202 } 203 204 public void setMaxInterpreterFrameSize(int maxInterpreterFrameSize) { 205 compilationResult.setMaxInterpreterFrameSize(maxInterpreterFrameSize); 206 } 207 208 public Mark recordMark(Object id) { 209 return compilationResult.recordMark(asm.position(), id); 210 } 211 212 public void blockComment(String s) { 213 compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.position(), s)); 214 } 215 216 /** 217 * Sets the {@linkplain CompilationResult#setTargetCode(byte[], int) code} and 534 if (beforeOp != null) { 535 beforeOp.accept(op); 536 } 537 emitOp(this, op); 538 if (afterOp != null) { 539 afterOp.accept(op); 540 } 541 } catch (GraalError e) { 542 throw e.addContext("lir instruction", block + "@" + op.id() + " " + op.getClass().getName() + " " + op + "\n" + Arrays.toString(lir.codeEmittingOrder())); 543 } 544 } 545 } 546 547 private static void emitOp(CompilationResultBuilder crb, LIRInstruction op) { 548 try { 549 int start = crb.asm.position(); 550 op.emitCode(crb); 551 if (op.getPosition() != null) { 552 crb.recordSourceMapping(start, crb.asm.position(), op.getPosition()); 553 } 554 } catch (BailoutException e) { 555 throw e; 556 } catch (AssertionError t) { 557 throw new GraalError(t); 558 } catch (RuntimeException t) { 559 throw new GraalError(t); 560 } 561 } 562 563 public void resetForEmittingCode() { 564 asm.reset(); 565 compilationResult.resetForEmittingCode(); 566 if (exceptionInfoList != null) { 567 exceptionInfoList.clear(); 568 } 569 if (dataCache != null) { 570 dataCache.clear(); 571 } 572 lir = null; 573 currentBlockIndex = 0; 574 } 575 576 public void setOpCallback(Consumer<LIRInstruction> beforeOp, Consumer<LIRInstruction> afterOp) { 577 this.beforeOp = beforeOp; 578 this.afterOp = afterOp; 579 } 580 581 public OptionValues getOptions() { 582 return options; 583 } 584 585 /** 586 * Builds up a map for label and LIR instruction positions where labels are or labels pointing 587 * to. 588 */ 589 public void buildLabelOffsets(LIR generatedLIR) { 590 labelBindLirPositions = EconomicMap.create(Equivalence.IDENTITY); 591 lirPositions = EconomicMap.create(Equivalence.IDENTITY); 592 int instructionPosition = 0; 593 for (AbstractBlockBase<?> block : generatedLIR.codeEmittingOrder()) { 594 if (block != null) { 595 for (LIRInstruction op : generatedLIR.getLIRforBlock(block)) { 596 if (op instanceof LabelHoldingOp) { 597 Label label = ((LabelHoldingOp) op).getLabel(); 598 if (label != null) { 599 labelBindLirPositions.put(label, instructionPosition); 600 } 601 lirPositions.put(op, instructionPosition); 602 } 603 instructionPosition++; 604 } 605 } 606 } 607 } 608 609 /** 610 * Answers the code generator whether the jump from instruction to label is within disp LIR 611 * instructions. 612 * 613 * @param disp Maximum number of LIR instructions between label and instruction 614 */ 615 public boolean labelWithinRange(LIRInstruction instruction, Label label, int disp) { 616 if (conservativeLabelOffsets) { 617 return false; 618 } 619 Integer labelPosition = labelBindLirPositions.get(label); 620 Integer instructionPosition = lirPositions.get(instruction); 621 boolean result; 622 if (labelPosition != null && instructionPosition != null) { 623 result = Math.abs(labelPosition - instructionPosition) < disp; 624 } else { 625 result = false; 626 } 627 return result; 628 } 629 630 /** 631 * Sets this CompilationResultBuilder into conservative mode. If set, 632 * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, Label, int)} always returns 633 * false. 634 */ 635 public void setConservativeLabelRanges() { 636 this.conservativeLabelOffsets = true; 637 } 638 } |