< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java

Print this page




   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 package jdk.vm.ci.hotspot.amd64;
  24 
  25 import static jdk.vm.ci.amd64.AMD64.*;
  26 
  27 import java.util.*;
  28 
  29 import jdk.vm.ci.amd64.*;
  30 import jdk.vm.ci.code.*;
  31 import jdk.vm.ci.code.CallingConvention.*;
  32 import jdk.vm.ci.common.*;
  33 import jdk.vm.ci.hotspot.*;
  34 import jdk.vm.ci.meta.*;































  35 
  36 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
  37 
  38     private final Architecture architecture;
  39 
  40     private final Register[] allocatable;
  41 
  42     private final int maxFrameSize;
  43 
  44     /**
  45      * The caller saved registers always include all parameter registers.
  46      */
  47     private final Register[] callerSaved;
  48 
  49     private final boolean allAllocatableAreCallerSaved;
  50 
  51     private final RegisterAttributes[] attributesMap;
  52 
  53     public int getMaximumFrameSize() {
  54         return maxFrameSize;


  69 
  70         Register[] ret = list.toArray(new Register[list.size()]);
  71         return ret;
  72     }
  73 
  74     @Override
  75     public RegisterAttributes[] getAttributesMap() {
  76         return attributesMap.clone();
  77     }
  78 
  79     private final Register[] javaGeneralParameterRegisters;
  80     private final Register[] nativeGeneralParameterRegisters;
  81     private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
  82 
  83     /*
  84      * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
  85      * to store the argument registers
  86      */
  87     private final boolean needsNativeStackHomeSpace;
  88 
  89     private static Register[] initAllocatable(boolean reserveForHeapBase) {
  90         Register[] registers = null;
  91         // @formatter:off
  92         if (reserveForHeapBase) {
  93             registers = new Register[] {
  94                         rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, /*r12,*/ r13, r14, /*r15, */
  95                         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
  96                         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
  97                       };
  98         } else {
  99             registers = new Register[] {
 100                         rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, r12, r13, r14, /*r15, */
 101                         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
 102                         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
 103                       };
 104         }
 105        // @formatter:on








 106         return registers;
 107     }
 108 
 109     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
 110         this(architecture, config, initAllocatable(config.useCompressedOops));
 111         assert callerSaved.length >= allocatable.length;
 112     }
 113 
 114     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, Register[] allocatable) {
 115         this.architecture = architecture;
 116         this.maxFrameSize = config.maxFrameSize;
 117 
 118         if (config.windowsOs) {
 119             javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
 120             nativeGeneralParameterRegisters = new Register[]{rcx, rdx, r8, r9};
 121             this.needsNativeStackHomeSpace = true;
 122         } else {
 123             javaGeneralParameterRegisters = new Register[]{rsi, rdx, rcx, r8, r9, rdi};
 124             nativeGeneralParameterRegisters = new Register[]{rdi, rsi, rdx, rcx, r8, r9};
 125             this.needsNativeStackHomeSpace = false;
 126         }
 127 
 128         this.allocatable = allocatable.clone();
 129         Set<Register> callerSaveSet = new HashSet<>();
 130         Collections.addAll(callerSaveSet, allocatable);
 131         Collections.addAll(callerSaveSet, xmmParameterRegisters);
 132         Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
 133         Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
 134         callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
 135 
 136         allAllocatableAreCallerSaved = true;
 137         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
 138     }
 139 
 140     @Override
 141     public Register[] getCallerSaveRegisters() {
 142         return callerSaved;
 143     }
 144 
 145     public Register[] getCalleeSaveRegisters() {
 146         return null;
 147     }
 148 
 149     @Override
 150     public boolean areAllAllocatableRegistersCallerSaved() {
 151         return allAllocatableAreCallerSaved;
 152     }
 153 
 154     @Override
 155     public Register getRegisterForRole(int index) {
 156         throw new UnsupportedOperationException();
 157     }


 204                 case Object:
 205                     if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
 206                         Register register = generalParameterRegisters[currentGeneral++];
 207                         locations[i] = register.asValue(target.getLIRKind(kind));
 208                     }
 209                     break;
 210                 case Float:
 211                 case Double:
 212                     if (!stackOnly && currentXMM < xmmParameterRegisters.length) {
 213                         Register register = xmmParameterRegisters[currentXMM++];
 214                         locations[i] = register.asValue(target.getLIRKind(kind));
 215                     }
 216                     break;
 217                 default:
 218                     throw JVMCIError.shouldNotReachHere();
 219             }
 220 
 221             if (locations[i] == null) {
 222                 LIRKind lirKind = target.getLIRKind(kind);
 223                 locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
 224                 currentStackOffset += Math.max(target.getSizeInBytes(lirKind.getPlatformKind()), target.wordSize);
 225             }
 226         }
 227 
 228         JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
 229         AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(target.getLIRKind(returnKind.getStackKind()));
 230         return new CallingConvention(currentStackOffset, returnLocation, locations);
 231     }
 232 
 233     @Override
 234     public Register getReturnRegister(JavaKind kind) {
 235         switch (kind) {
 236             case Boolean:
 237             case Byte:
 238             case Char:
 239             case Short:
 240             case Int:
 241             case Long:
 242             case Object:
 243                 return rax;
 244             case Float:


   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 package jdk.vm.ci.hotspot.amd64;
  24 
  25 import static jdk.vm.ci.amd64.AMD64.r12;
  26 import static jdk.vm.ci.amd64.AMD64.r15;
  27 import static jdk.vm.ci.amd64.AMD64.r8;
  28 import static jdk.vm.ci.amd64.AMD64.r9;
  29 import static jdk.vm.ci.amd64.AMD64.rax;
  30 import static jdk.vm.ci.amd64.AMD64.rcx;
  31 import static jdk.vm.ci.amd64.AMD64.rdi;
  32 import static jdk.vm.ci.amd64.AMD64.rdx;
  33 import static jdk.vm.ci.amd64.AMD64.rsi;
  34 import static jdk.vm.ci.amd64.AMD64.rsp;
  35 import static jdk.vm.ci.amd64.AMD64.xmm0;
  36 import static jdk.vm.ci.amd64.AMD64.xmm1;
  37 import static jdk.vm.ci.amd64.AMD64.xmm2;
  38 import static jdk.vm.ci.amd64.AMD64.xmm3;
  39 import static jdk.vm.ci.amd64.AMD64.xmm4;
  40 import static jdk.vm.ci.amd64.AMD64.xmm5;
  41 import static jdk.vm.ci.amd64.AMD64.xmm6;
  42 import static jdk.vm.ci.amd64.AMD64.xmm7;
  43 
  44 import java.util.ArrayList;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.HashSet;
  48 import java.util.Set;
  49 
  50 import jdk.vm.ci.code.Architecture;
  51 import jdk.vm.ci.code.CallingConvention;
  52 import jdk.vm.ci.code.CallingConvention.Type;
  53 import jdk.vm.ci.code.Register;
  54 import jdk.vm.ci.code.RegisterAttributes;
  55 import jdk.vm.ci.code.RegisterConfig;
  56 import jdk.vm.ci.code.StackSlot;
  57 import jdk.vm.ci.code.TargetDescription;
  58 import jdk.vm.ci.common.JVMCIError;
  59 import jdk.vm.ci.hotspot.HotSpotVMConfig;
  60 import jdk.vm.ci.meta.AllocatableValue;
  61 import jdk.vm.ci.meta.JavaKind;
  62 import jdk.vm.ci.meta.JavaType;
  63 import jdk.vm.ci.meta.LIRKind;
  64 import jdk.vm.ci.meta.PlatformKind;
  65 import jdk.vm.ci.meta.Value;
  66 
  67 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
  68 
  69     private final Architecture architecture;
  70 
  71     private final Register[] allocatable;
  72 
  73     private final int maxFrameSize;
  74 
  75     /**
  76      * The caller saved registers always include all parameter registers.
  77      */
  78     private final Register[] callerSaved;
  79 
  80     private final boolean allAllocatableAreCallerSaved;
  81 
  82     private final RegisterAttributes[] attributesMap;
  83 
  84     public int getMaximumFrameSize() {
  85         return maxFrameSize;


 100 
 101         Register[] ret = list.toArray(new Register[list.size()]);
 102         return ret;
 103     }
 104 
 105     @Override
 106     public RegisterAttributes[] getAttributesMap() {
 107         return attributesMap.clone();
 108     }
 109 
 110     private final Register[] javaGeneralParameterRegisters;
 111     private final Register[] nativeGeneralParameterRegisters;
 112     private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
 113 
 114     /*
 115      * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
 116      * to store the argument registers
 117      */
 118     private final boolean needsNativeStackHomeSpace;
 119 
 120     private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
 121         Register[] allRegisters = arch.getAvailableValueRegisters();
 122         Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)];
 123 
 124         int idx = 0;
 125         for (Register reg : allRegisters) {
 126             if (reg.equals(rsp) || reg.equals(r15)) {
 127                 // skip stack pointer and thread register
 128                 continue;






 129             }
 130             if (reserveForHeapBase && reg.equals(r12)) {
 131                 // skip heap base register
 132                 continue;
 133             }
 134 
 135             registers[idx++] = reg;
 136         }
 137 
 138         assert idx == registers.length;
 139         return registers;
 140     }
 141 
 142     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
 143         this(architecture, config, initAllocatable(architecture, config.useCompressedOops));
 144         assert callerSaved.length >= allocatable.length;
 145     }
 146 
 147     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, Register[] allocatable) {
 148         this.architecture = architecture;
 149         this.maxFrameSize = config.maxFrameSize;
 150 
 151         if (config.windowsOs) {
 152             javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
 153             nativeGeneralParameterRegisters = new Register[]{rcx, rdx, r8, r9};
 154             this.needsNativeStackHomeSpace = true;
 155         } else {
 156             javaGeneralParameterRegisters = new Register[]{rsi, rdx, rcx, r8, r9, rdi};
 157             nativeGeneralParameterRegisters = new Register[]{rdi, rsi, rdx, rcx, r8, r9};
 158             this.needsNativeStackHomeSpace = false;
 159         }
 160 
 161         this.allocatable = allocatable;
 162         Set<Register> callerSaveSet = new HashSet<>();
 163         Collections.addAll(callerSaveSet, allocatable);
 164         Collections.addAll(callerSaveSet, xmmParameterRegisters);
 165         Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
 166         Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
 167         callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
 168 
 169         allAllocatableAreCallerSaved = true;
 170         attributesMap = RegisterAttributes.createMap(this, architecture.getRegisters());
 171     }
 172 
 173     @Override
 174     public Register[] getCallerSaveRegisters() {
 175         return callerSaved;
 176     }
 177 
 178     public Register[] getCalleeSaveRegisters() {
 179         return null;
 180     }
 181 
 182     @Override
 183     public boolean areAllAllocatableRegistersCallerSaved() {
 184         return allAllocatableAreCallerSaved;
 185     }
 186 
 187     @Override
 188     public Register getRegisterForRole(int index) {
 189         throw new UnsupportedOperationException();
 190     }


 237                 case Object:
 238                     if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
 239                         Register register = generalParameterRegisters[currentGeneral++];
 240                         locations[i] = register.asValue(target.getLIRKind(kind));
 241                     }
 242                     break;
 243                 case Float:
 244                 case Double:
 245                     if (!stackOnly && currentXMM < xmmParameterRegisters.length) {
 246                         Register register = xmmParameterRegisters[currentXMM++];
 247                         locations[i] = register.asValue(target.getLIRKind(kind));
 248                     }
 249                     break;
 250                 default:
 251                     throw JVMCIError.shouldNotReachHere();
 252             }
 253 
 254             if (locations[i] == null) {
 255                 LIRKind lirKind = target.getLIRKind(kind);
 256                 locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
 257                 currentStackOffset += Math.max(lirKind.getPlatformKind().getSizeInBytes(), target.wordSize);
 258             }
 259         }
 260 
 261         JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
 262         AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(target.getLIRKind(returnKind.getStackKind()));
 263         return new CallingConvention(currentStackOffset, returnLocation, locations);
 264     }
 265 
 266     @Override
 267     public Register getReturnRegister(JavaKind kind) {
 268         switch (kind) {
 269             case Boolean:
 270             case Byte:
 271             case Char:
 272             case Short:
 273             case Int:
 274             case Long:
 275             case Object:
 276                 return rax;
 277             case Float:
< prev index next >