src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java
changeset 58299 6df94ce3ab2f
parent 52910 583fd71c47d6
equal deleted inserted replaced
58298:0152ad7b38b8 58299:6df94ce3ab2f
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
     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.
     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.
    24 
    24 
    25 package org.graalvm.compiler.lir.amd64;
    25 package org.graalvm.compiler.lir.amd64;
    26 
    26 
    27 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
    27 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
    28 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
    28 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
    29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
       
    30 
       
    31 import java.util.Arrays;
       
    32 
    29 
    33 import jdk.internal.vm.compiler.collections.EconomicSet;
    30 import jdk.internal.vm.compiler.collections.EconomicSet;
    34 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
    31 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
    35 import org.graalvm.compiler.lir.LIRInstructionClass;
    32 import org.graalvm.compiler.lir.LIRInstructionClass;
    36 import org.graalvm.compiler.lir.LIRValueUtil;
       
    37 import org.graalvm.compiler.lir.Opcode;
    33 import org.graalvm.compiler.lir.Opcode;
    38 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
    34 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
       
    35 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorMove;
    39 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
    36 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
    40 import org.graalvm.compiler.lir.framemap.FrameMap;
       
    41 
    37 
    42 import jdk.vm.ci.amd64.AMD64Kind;
    38 import jdk.vm.ci.amd64.AMD64Kind;
    43 import jdk.vm.ci.code.Register;
    39 import jdk.vm.ci.code.Register;
    44 import jdk.vm.ci.code.RegisterSaveLayout;
       
    45 import jdk.vm.ci.code.StackSlot;
    40 import jdk.vm.ci.code.StackSlot;
    46 import jdk.vm.ci.meta.AllocatableValue;
    41 import jdk.vm.ci.meta.AllocatableValue;
    47 
    42 
    48 /**
    43 /**
    49  * Saves registers to stack slots.
    44  * Saves registers to stack slots.
    50  */
    45  */
    51 @Opcode("SAVE_REGISTER")
    46 @Opcode("SAVE_REGISTER")
    52 public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveRegistersOp {
    47 public class AMD64SaveRegistersOp extends SaveRegistersOp {
    53     public static final LIRInstructionClass<AMD64SaveRegistersOp> TYPE = LIRInstructionClass.create(AMD64SaveRegistersOp.class);
    48     public static final LIRInstructionClass<AMD64SaveRegistersOp> TYPE = LIRInstructionClass.create(AMD64SaveRegistersOp.class);
    54 
       
    55     /**
       
    56      * The registers (potentially) saved by this operation.
       
    57      */
       
    58     protected final Register[] savedRegisters;
       
    59 
       
    60     /**
       
    61      * The slots to which the registers are saved.
       
    62      */
       
    63     @Def(STACK) protected final AllocatableValue[] slots;
       
    64 
       
    65     /**
       
    66      * Specifies if {@link #remove(EconomicSet)} should have an effect.
       
    67      */
       
    68     protected final boolean supportsRemove;
       
    69 
    49 
    70     /**
    50     /**
    71      *
    51      *
    72      * @param savedRegisters the registers saved by this operation which may be subject to
    52      * @param savedRegisters the registers saved by this operation which may be subject to
    73      *            {@linkplain #remove(EconomicSet) pruning}
    53      *            {@linkplain #remove(EconomicSet) pruning}
    74      * @param savedRegisterLocations the slots to which the registers are saved
    54      * @param savedRegisterLocations the slots to which the registers are saved
    75      * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned}
       
    76      */
    55      */
    77     public AMD64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
    56     public AMD64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
    78         this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove);
    57         super(TYPE, savedRegisters, savedRegisterLocations);
    79     }
    58     }
    80 
    59 
    81     public AMD64SaveRegistersOp(LIRInstructionClass<? extends AMD64SaveRegistersOp> c, Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
    60     protected AMD64SaveRegistersOp(LIRInstructionClass<AMD64VectorMove.SaveRegistersOp> type, Register[] savedRegisters, AllocatableValue[] slots) {
    82         super(c);
    61         super(type, savedRegisters, slots);
    83         assert Arrays.asList(savedRegisterLocations).stream().allMatch(LIRValueUtil::isVirtualStackSlot);
       
    84         this.savedRegisters = savedRegisters;
       
    85         this.slots = savedRegisterLocations;
       
    86         this.supportsRemove = supportsRemove;
       
    87     }
    62     }
    88 
    63 
    89     protected void saveRegister(CompilationResultBuilder crb, AMD64MacroAssembler masm, StackSlot result, Register input) {
    64     protected void saveRegister(CompilationResultBuilder crb, AMD64MacroAssembler masm, StackSlot result, Register input) {
    90         AMD64Move.reg2stack((AMD64Kind) result.getPlatformKind(), crb, masm, result, input);
    65         AMD64Move.reg2stack((AMD64Kind) result.getPlatformKind(), crb, masm, result, input);
    91     }
    66     }
    92 
    67 
    93     @Override
    68     @Override
    94     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
    69     public void emitCode(CompilationResultBuilder crb) {
       
    70         AMD64MacroAssembler masm = (AMD64MacroAssembler) crb.asm;
    95         for (int i = 0; i < savedRegisters.length; i++) {
    71         for (int i = 0; i < savedRegisters.length; i++) {
    96             if (savedRegisters[i] != null) {
    72             if (savedRegisters[i] != null) {
    97                 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
    73                 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
    98                 saveRegister(crb, masm, asStackSlot(slots[i]), savedRegisters[i]);
    74                 saveRegister(crb, masm, asStackSlot(slots[i]), savedRegisters[i]);
    99             }
    75             }
   100         }
    76         }
   101     }
    77     }
   102 
       
   103     public AllocatableValue[] getSlots() {
       
   104         return slots;
       
   105     }
       
   106 
       
   107     @Override
       
   108     public boolean supportsRemove() {
       
   109         return supportsRemove;
       
   110     }
       
   111 
       
   112     @Override
       
   113     public int remove(EconomicSet<Register> doNotSave) {
       
   114         if (!supportsRemove) {
       
   115             throw new UnsupportedOperationException();
       
   116         }
       
   117         return prune(doNotSave, savedRegisters);
       
   118     }
       
   119 
       
   120     static int prune(EconomicSet<Register> toRemove, Register[] registers) {
       
   121         int pruned = 0;
       
   122         for (int i = 0; i < registers.length; i++) {
       
   123             if (registers[i] != null) {
       
   124                 if (toRemove.contains(registers[i])) {
       
   125                     registers[i] = null;
       
   126                     pruned++;
       
   127                 }
       
   128             }
       
   129         }
       
   130         return pruned;
       
   131     }
       
   132 
       
   133     @Override
       
   134     public RegisterSaveLayout getMap(FrameMap frameMap) {
       
   135         int total = 0;
       
   136         for (int i = 0; i < savedRegisters.length; i++) {
       
   137             if (savedRegisters[i] != null) {
       
   138                 total++;
       
   139             }
       
   140         }
       
   141         Register[] keys = new Register[total];
       
   142         int[] values = new int[total];
       
   143         if (total != 0) {
       
   144             int mapIndex = 0;
       
   145             for (int i = 0; i < savedRegisters.length; i++) {
       
   146                 if (savedRegisters[i] != null) {
       
   147                     keys[mapIndex] = savedRegisters[i];
       
   148                     assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
       
   149                     StackSlot slot = asStackSlot(slots[i]);
       
   150                     values[mapIndex] = indexForStackSlot(frameMap, slot);
       
   151                     mapIndex++;
       
   152                 }
       
   153             }
       
   154             assert mapIndex == total;
       
   155         }
       
   156         return new RegisterSaveLayout(keys, values);
       
   157     }
       
   158 
       
   159     /**
       
   160      * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack
       
   161      * slots in the reference map.
       
   162      *
       
   163      * @param slot a stack slot
       
   164      * @return the index of the stack slot
       
   165      */
       
   166     private static int indexForStackSlot(FrameMap frameMap, StackSlot slot) {
       
   167         assert frameMap.offsetForStackSlot(slot) % frameMap.getTarget().wordSize == 0;
       
   168         int value = frameMap.offsetForStackSlot(slot) / frameMap.getTarget().wordSize;
       
   169         return value;
       
   170     }
       
   171 }
    78 }