src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54601 c40b2a190173
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    59 import org.graalvm.compiler.lir.LIRFrameState;
    59 import org.graalvm.compiler.lir.LIRFrameState;
    60 import org.graalvm.compiler.lir.LIRInstruction;
    60 import org.graalvm.compiler.lir.LIRInstruction;
    61 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
    61 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
    62 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
    62 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
    63 import org.graalvm.compiler.lir.StandardOp.LabelOp;
    63 import org.graalvm.compiler.lir.StandardOp.LabelOp;
       
    64 import org.graalvm.compiler.lir.StandardOp.RestoreRegistersOp;
    64 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
    65 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
    65 import org.graalvm.compiler.lir.ValueConsumer;
    66 import org.graalvm.compiler.lir.ValueConsumer;
    66 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
    67 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
    67 import org.graalvm.compiler.lir.framemap.FrameMap;
    68 import org.graalvm.compiler.lir.framemap.FrameMap;
    68 import org.graalvm.compiler.nodes.UnwindNode;
    69 import org.graalvm.compiler.nodes.UnwindNode;
    74 import org.graalvm.compiler.phases.tiers.SuitesProvider;
    75 import org.graalvm.compiler.phases.tiers.SuitesProvider;
    75 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
    76 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
    76 import org.graalvm.compiler.word.Word;
    77 import org.graalvm.compiler.word.Word;
    77 import jdk.internal.vm.compiler.word.Pointer;
    78 import jdk.internal.vm.compiler.word.Pointer;
    78 
    79 
       
    80 import jdk.vm.ci.code.CallingConvention;
    79 import jdk.vm.ci.code.CompilationRequest;
    81 import jdk.vm.ci.code.CompilationRequest;
    80 import jdk.vm.ci.code.CompiledCode;
    82 import jdk.vm.ci.code.CompiledCode;
    81 import jdk.vm.ci.code.Register;
    83 import jdk.vm.ci.code.Register;
    82 import jdk.vm.ci.code.RegisterSaveLayout;
       
    83 import jdk.vm.ci.code.StackSlot;
    84 import jdk.vm.ci.code.StackSlot;
    84 import jdk.vm.ci.code.ValueUtil;
    85 import jdk.vm.ci.code.ValueUtil;
    85 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
    86 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
    86 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
    87 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
    87 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
    88 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
       
    89 import jdk.vm.ci.meta.AllocatableValue;
    88 import jdk.vm.ci.meta.ResolvedJavaMethod;
    90 import jdk.vm.ci.meta.ResolvedJavaMethod;
    89 import jdk.vm.ci.meta.Value;
    91 import jdk.vm.ci.meta.Value;
    90 import jdk.vm.ci.runtime.JVMCICompiler;
    92 import jdk.vm.ci.runtime.JVMCICompiler;
    91 
    93 
    92 /**
    94 /**
    95 public abstract class HotSpotBackend extends Backend implements FrameMap.ReferenceMapBuilderFactory {
    97 public abstract class HotSpotBackend extends Backend implements FrameMap.ReferenceMapBuilderFactory {
    96 
    98 
    97     public static class Options {
    99     public static class Options {
    98         // @formatter:off
   100         // @formatter:off
    99         @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
   101         @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
   100         public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9);
   102         public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPEC >= 9);
   101         @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
   103         @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
   102                         " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
   104                         " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
   103         public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
   105         public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
   104         // @formatter:on
   106         // @formatter:on
   105     }
   107     }
   423     }
   425     }
   424 
   426 
   425     /**
   427     /**
   426      * Finds all the registers that are defined by some given LIR.
   428      * Finds all the registers that are defined by some given LIR.
   427      *
   429      *
   428      * @param lir the LIR to examine
   430      * @param gen the result to examine
   429      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
   431      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
   430      */
   432      */
   431     protected final EconomicSet<Register> gatherDestroyedCallerRegisters(LIR lir) {
   433     private EconomicSet<Register> gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult gen) {
       
   434         LIR lir = gen.getLIR();
       
   435         final EconomicSet<Register> preservedRegisters = EconomicSet.create(Equivalence.IDENTITY);
   432         final EconomicSet<Register> destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY);
   436         final EconomicSet<Register> destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY);
   433         ValueConsumer defConsumer = new ValueConsumer() {
   437         ValueConsumer defConsumer = new ValueConsumer() {
   434 
   438 
   435             @Override
   439             @Override
   436             public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
   440             public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
   437                 if (ValueUtil.isRegister(value)) {
   441                 if (ValueUtil.isRegister(value)) {
   438                     final Register reg = ValueUtil.asRegister(value);
   442                     final Register reg = ValueUtil.asRegister(value);
   439                     destroyedRegisters.add(reg);
   443                     if (!preservedRegisters.contains(reg)) {
       
   444                         destroyedRegisters.add(reg);
       
   445                     }
   440                 }
   446                 }
   441             }
   447             }
   442         };
   448         };
       
   449         boolean sawSaveRegisters = false;
   443         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
   450         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
   444             if (block == null) {
   451             if (block == null) {
   445                 continue;
   452                 continue;
   446             }
   453             }
       
   454             // Ignore the effects of instructions bracketed by save/restore
       
   455             SaveRegistersOp save = null;
   447             for (LIRInstruction op : lir.getLIRforBlock(block)) {
   456             for (LIRInstruction op : lir.getLIRforBlock(block)) {
   448                 if (op instanceof LabelOp) {
   457                 if (op instanceof LabelOp) {
   449                     // Don't consider this as a definition
   458                     // Don't consider this as a definition
       
   459                 } else if (op instanceof SaveRegistersOp) {
       
   460                     save = (SaveRegistersOp) op;
       
   461                     sawSaveRegisters = true;
       
   462                     preservedRegisters.addAll(save.getSaveableRegisters());
       
   463                 } else if (op instanceof RestoreRegistersOp) {
       
   464                     save = null;
       
   465                     preservedRegisters.clear();
   450                 } else {
   466                 } else {
   451                     op.visitEachTemp(defConsumer);
   467                     op.visitEachTemp(defConsumer);
   452                     op.visitEachOutput(defConsumer);
   468                     op.visitEachOutput(defConsumer);
   453                 }
   469                 }
   454             }
   470             }
       
   471             assert save == null : "missing RestoreRegistersOp";
       
   472         }
       
   473 
       
   474         if (sawSaveRegisters) {
       
   475             // The return value must be killed so it can be propagated out
       
   476             CallingConvention cc = gen.getCallingConvention();
       
   477             AllocatableValue returnValue = cc.getReturn();
       
   478             if (returnValue != null) {
       
   479                 if (ValueUtil.isRegister(returnValue)) {
       
   480                     destroyedRegisters.add(ValueUtil.asRegister(returnValue));
       
   481                 }
       
   482             }
   455         }
   483         }
   456         return translateToCallerRegisters(destroyedRegisters);
   484         return translateToCallerRegisters(destroyedRegisters);
   457     }
   485     }
   458 
   486 
   459     /**
   487     /**
   462      * register windows on SPARC). Registers which are not visible by the caller are removed.
   490      * register windows on SPARC). Registers which are not visible by the caller are removed.
   463      */
   491      */
   464     protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
   492     protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
   465 
   493 
   466     /**
   494     /**
   467      * Updates a given stub with respect to the registers it destroys.
   495      * Updates a given stub with respect to the registers it destroys by
   468      * <p>
   496      * {@link #gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult) computing the destroyed
   469      * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove()
   497      * registers} and removing those registers from the {@linkplain SaveRegistersOp SaveRegistersOp}
   470      * supports} pruning will have {@code destroyedRegisters}
   498      * as these registers are declared as temporaries in the stub's {@linkplain ForeignCallLinkage
   471      * {@linkplain SaveRegistersOp#remove(EconomicSet) removed} as these registers are declared as
   499      * linkage} (and thus will be saved by the stub's caller).
   472      * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by
       
   473      * the stub's caller).
       
   474      *
   500      *
   475      * @param stub the stub to update
   501      * @param stub the stub to update
   476      * @param destroyedRegisters the registers destroyed by the stub
   502      * @param gen the HotSpotLIRGenerationResult being emitted
   477      * @param calleeSaveInfo a map from debug infos to the operations that provide their
       
   478      *            {@linkplain RegisterSaveLayout callee-save information}
       
   479      * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual
   503      * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual
   480      *            slot to a frame slot index
   504      */
   481      */
   505     protected void updateStub(Stub stub, HotSpotLIRGenerationResult gen, FrameMap frameMap) {
   482     protected void updateStub(Stub stub, EconomicSet<Register> destroyedRegisters, EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo, FrameMap frameMap) {
   506         EconomicSet<Register> destroyedRegisters = gatherDestroyedCallerRegisters(gen);
       
   507         EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
       
   508 
       
   509         if (stub.getLinkage().needsDebugInfo() && calleeSaveInfo.isEmpty()) {
       
   510             // This call is a safepoint but no register saving was done so we must ensure that all
       
   511             // registers appear to be killed. The Native ABI may allow caller save registers but
       
   512             // for HotSpot they must be described in a RegisterMap so they are accessible.
       
   513             for (Register r : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
       
   514                 destroyedRegisters.add(r);
       
   515             }
       
   516         }
       
   517 
   483         stub.initDestroyedCallerRegisters(destroyedRegisters);
   518         stub.initDestroyedCallerRegisters(destroyedRegisters);
   484 
   519 
   485         MapCursor<LIRFrameState, SaveRegistersOp> cursor = calleeSaveInfo.getEntries();
   520         MapCursor<LIRFrameState, SaveRegistersOp> cursor = calleeSaveInfo.getEntries();
   486         while (cursor.advance()) {
   521         while (cursor.advance()) {
   487             SaveRegistersOp save = cursor.getValue();
   522             SaveRegistersOp save = cursor.getValue();
   488             if (save.supportsRemove()) {
   523             save.remove(destroyedRegisters);
   489                 save.remove(destroyedRegisters);
       
   490             }
       
   491             if (cursor.getKey() != LIRFrameState.NO_STATE) {
   524             if (cursor.getKey() != LIRFrameState.NO_STATE) {
   492                 cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap));
   525                 cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap));
   493             }
   526             }
   494         }
   527         }
   495     }
   528     }