src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java
changeset 58299 6df94ce3ab2f
parent 57537 ecc6e394475f
child 58679 9c3209ff7550
equal deleted inserted replaced
58298:0152ad7b38b8 58299:6df94ce3ab2f
     1 /*
     1 /*
     2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    22  */
    22  */
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.lir;
    25 package org.graalvm.compiler.lir;
    26 
    26 
       
    27 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
       
    28 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
    27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
    29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
    28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
    30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
    29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.OUTGOING;
    31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.OUTGOING;
    30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
    32 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
    31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
    33 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
    32 
    34 
    33 import java.util.ArrayList;
    35 import java.util.ArrayList;
       
    36 import java.util.Arrays;
    34 import java.util.EnumSet;
    37 import java.util.EnumSet;
    35 
    38 
    36 import jdk.internal.vm.compiler.collections.EconomicSet;
    39 import jdk.internal.vm.compiler.collections.EconomicSet;
       
    40 import jdk.internal.vm.compiler.collections.Equivalence;
    37 import org.graalvm.compiler.asm.Label;
    41 import org.graalvm.compiler.asm.Label;
    38 import org.graalvm.compiler.core.common.GraalOptions;
    42 import org.graalvm.compiler.core.common.GraalOptions;
    39 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
    43 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
    40 import org.graalvm.compiler.debug.GraalError;
    44 import org.graalvm.compiler.debug.GraalError;
    41 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
    45 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
   298     /**
   302     /**
   299      * An operation that saves registers to the stack. The set of saved registers can be
   303      * An operation that saves registers to the stack. The set of saved registers can be
   300      * {@linkplain #remove(EconomicSet) pruned} and a mapping from registers to the frame slots in
   304      * {@linkplain #remove(EconomicSet) pruned} and a mapping from registers to the frame slots in
   301      * which they are saved can be {@linkplain #getMap(FrameMap) retrieved}.
   305      * which they are saved can be {@linkplain #getMap(FrameMap) retrieved}.
   302      */
   306      */
   303     public interface SaveRegistersOp {
   307     public abstract static class SaveRegistersOp extends LIRInstruction {
   304 
   308         public static final LIRInstructionClass<SaveRegistersOp> TYPE = LIRInstructionClass.create(SaveRegistersOp.class);
   305         /**
   309 
   306          * Determines if the {@link #remove(EconomicSet)} operation is supported for this object.
   310         /**
   307          */
   311          * The registers (potentially) saved by this operation.
   308         boolean supportsRemove();
   312          */
       
   313         protected final Register[] savedRegisters;
       
   314 
       
   315         /**
       
   316          * The slots to which the registers are saved.
       
   317          */
       
   318         @Def(STACK) protected final AllocatableValue[] slots;
       
   319 
       
   320         /**
       
   321          *
       
   322          * @param savedRegisters the registers saved by this operation which may be subject to
       
   323          *            {@linkplain #remove(EconomicSet) pruning}
       
   324          * @param savedRegisterLocations the slots to which the registers are saved
       
   325          */
       
   326         protected SaveRegistersOp(LIRInstructionClass<? extends SaveRegistersOp> c, Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
       
   327             super(c);
       
   328             assert Arrays.asList(savedRegisterLocations).stream().allMatch(LIRValueUtil::isVirtualStackSlot);
       
   329             this.savedRegisters = savedRegisters;
       
   330             this.slots = savedRegisterLocations;
       
   331         }
   309 
   332 
   310         /**
   333         /**
   311          * Prunes {@code doNotSave} from the registers saved by this operation.
   334          * Prunes {@code doNotSave} from the registers saved by this operation.
   312          *
   335          *
   313          * @param doNotSave registers that should not be saved by this operation
   336          * @param doNotSave registers that should not be saved by this operation
   314          * @return the number of registers pruned
   337          * @return the number of registers pruned
   315          * @throws UnsupportedOperationException if removal is not {@linkplain #supportsRemove()
   338          */
   316          *             supported}
   339         public int remove(EconomicSet<Register> doNotSave) {
   317          */
   340             return prune(doNotSave, savedRegisters);
   318         int remove(EconomicSet<Register> doNotSave);
   341         }
   319 
   342 
   320         /**
   343         /**
   321          * Gets a map from the saved registers saved by this operation to the frame slots in which
   344          * Gets a map from the saved registers saved by this operation to the frame slots in which
   322          * they are saved.
   345          * they are saved.
   323          *
   346          *
   324          * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a
   347          * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a
   325          *            virtual slot to a frame slot index
   348          *            virtual slot to a frame slot index
   326          */
   349          */
   327         RegisterSaveLayout getMap(FrameMap frameMap);
   350 
   328 
   351         public RegisterSaveLayout getMap(FrameMap frameMap) {
       
   352             int total = 0;
       
   353             for (int i = 0; i < savedRegisters.length; i++) {
       
   354                 if (savedRegisters[i] != null) {
       
   355                     total++;
       
   356                 }
       
   357             }
       
   358             Register[] keys = new Register[total];
       
   359             int[] values = new int[total];
       
   360             if (total != 0) {
       
   361                 int mapIndex = 0;
       
   362                 for (int i = 0; i < savedRegisters.length; i++) {
       
   363                     if (savedRegisters[i] != null) {
       
   364                         keys[mapIndex] = savedRegisters[i];
       
   365                         assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
       
   366                         StackSlot slot = asStackSlot(slots[i]);
       
   367                         values[mapIndex] = indexForStackSlot(frameMap, slot);
       
   368                         mapIndex++;
       
   369                     }
       
   370                 }
       
   371                 assert mapIndex == total;
       
   372             }
       
   373             return new RegisterSaveLayout(keys, values);
       
   374         }
       
   375 
       
   376         public Register[] getSavedRegisters() {
       
   377             return savedRegisters;
       
   378         }
       
   379 
       
   380         public EconomicSet<Register> getSaveableRegisters() {
       
   381             EconomicSet<Register> registers = EconomicSet.create(Equivalence.IDENTITY);
       
   382             for (Register r : savedRegisters) {
       
   383                 registers.add(r);
       
   384             }
       
   385             return registers;
       
   386         }
       
   387 
       
   388         public AllocatableValue[] getSlots() {
       
   389             return slots;
       
   390         }
       
   391 
       
   392         @Override
       
   393         public abstract void emitCode(CompilationResultBuilder crb);
       
   394 
       
   395         static int prune(EconomicSet<Register> toRemove, Register[] registers) {
       
   396             int pruned = 0;
       
   397             for (int i = 0; i < registers.length; i++) {
       
   398                 if (registers[i] != null) {
       
   399                     if (toRemove.contains(registers[i])) {
       
   400                         registers[i] = null;
       
   401                         pruned++;
       
   402                     }
       
   403                 }
       
   404             }
       
   405             return pruned;
       
   406         }
       
   407 
       
   408         /**
       
   409          * Computes the index of a stack slot relative to slot 0. This is also the bit index of
       
   410          * stack slots in the reference map.
       
   411          *
       
   412          * @param slot a stack slot
       
   413          * @return the index of the stack slot
       
   414          */
       
   415         private static int indexForStackSlot(FrameMap frameMap, StackSlot slot) {
       
   416             assert frameMap.offsetForStackSlot(slot) % frameMap.getTarget().wordSize == 0;
       
   417             int value = frameMap.offsetForStackSlot(slot) / frameMap.getTarget().wordSize;
       
   418             return value;
       
   419         }
       
   420     }
       
   421 
       
   422     /**
       
   423      * Marker interface for an operation that restores the registers saved by
       
   424      * {@link SaveRegistersOp}.
       
   425      */
       
   426     public interface RestoreRegistersOp {
       
   427     }
       
   428 
       
   429     /**
       
   430      * Marker interface for an operation that kills some set register and stack locations.
       
   431      */
       
   432     public interface ZapRegistersOp {
   329     }
   433     }
   330 
   434 
   331     /**
   435     /**
   332      * A LIR operation that does nothing. If the operation records its position, it can be
   436      * A LIR operation that does nothing. If the operation records its position, it can be
   333      * subsequently {@linkplain #replace(LIR, LIRInstruction) replaced}.
   437      * subsequently {@linkplain #replace(LIR, LIRInstruction) replaced}.