< 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

        

@@ -103,11 +103,13 @@
         return attributesMap.clone();
     }
 
     private final RegisterArray javaGeneralParameterRegisters;
     private final RegisterArray nativeGeneralParameterRegisters;
-    private final RegisterArray xmmParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
+    private final RegisterArray javaXMMParameterRegisters;
+    private final RegisterArray nativeXMMParameterRegisters;
+    private final boolean windowsOS;
 
     /*
      * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
      * to store the argument registers
      */

@@ -141,27 +143,31 @@
     public AMD64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops, boolean windowsOs) {
         this(target, initAllocatable(target.arch, useCompressedOops), windowsOs);
         assert callerSaved.size() >= allocatable.size();
     }
 
-    public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable, boolean windowsOs) {
+    public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable, boolean windowsOS) {
         this.target = target;
+        this.windowsOS = windowsOS;
 
-        if (windowsOs) {
+        if (windowsOS) {
             javaGeneralParameterRegisters = new RegisterArray(rdx, r8, r9, rdi, rsi, rcx);
             nativeGeneralParameterRegisters = new RegisterArray(rcx, rdx, r8, r9);
+            nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3);
             this.needsNativeStackHomeSpace = true;
         } else {
             javaGeneralParameterRegisters = new RegisterArray(rsi, rdx, rcx, r8, r9, rdi);
             nativeGeneralParameterRegisters = new RegisterArray(rdi, rsi, rdx, rcx, r8, r9);
+            nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
             this.needsNativeStackHomeSpace = false;
         }
+        javaXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
 
         this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
         allocatable.addTo(callerSaveSet);
-        xmmParameterRegisters.addTo(callerSaveSet);
+        javaXMMParameterRegisters.addTo(callerSaveSet);
         callerSaveSet.addAll(javaGeneralParameterRegisters.asList());
         nativeGeneralParameterRegisters.addTo(callerSaveSet);
         callerSaved = new RegisterArray(callerSaveSet);
 
         allAllocatableAreCallerSaved = true;

@@ -185,15 +191,15 @@
 
     @Override
     public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         if (type == HotSpotCallingConventionType.NativeCall) {
-            return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+            return callingConvention(nativeGeneralParameterRegisters, nativeXMMParameterRegisters, windowsOS, returnType, parameterTypes, hotspotType, valueKindFactory);
         }
         // On x64, parameter locations are the same whether viewed
         // from the caller or callee perspective
-        return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
+        return callingConvention(javaGeneralParameterRegisters, javaXMMParameterRegisters, false, returnType, parameterTypes, hotspotType, valueKindFactory);
     }
 
     @Override
     public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;

@@ -206,18 +212,37 @@
             case Long:
             case Object:
                 return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
             case Float:
             case Double:
-                return xmmParameterRegisters;
+                return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeXMMParameterRegisters : javaXMMParameterRegisters;
             default:
                 throw JVMCIError.shouldNotReachHere();
         }
     }
 
-    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    /**
+     * Hand out registers matching the calling convention from the {@code generalParameterRegisters}
+     * and {@code xmmParameterRegisters} sets. Normally registers are handed out from each set
+     * individually based on the type of the argument. If the {@code unified} flag is true then hand
+     * out registers in a single sequence, selecting between the sets based on the type. This is to
+     * support the Windows calling convention which only ever passes 4 arguments in registers, no
+     * matter their types.
+     *
+     * @param generalParameterRegisters
+     * @param xmmParameterRegisters
+     * @param unified
+     * @param returnType
+     * @param parameterTypes
+     * @param type
+     * @param valueKindFactory
+     * @return the resulting calling convention
+     */
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, RegisterArray xmmParameterRegisters, boolean unified, JavaType returnType, JavaType[] parameterTypes,
+                    HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
+        assert !unified || generalParameterRegisters.size() == xmmParameterRegisters.size() : "must be same size in unified mode";
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
         int currentGeneral = 0;
         int currentXMM = 0;
         int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.size() * target.wordSize : 0;

@@ -238,12 +263,12 @@
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentXMM < xmmParameterRegisters.size()) {
-                        Register register = xmmParameterRegisters.get(currentXMM++);
+                    if ((unified ? currentGeneral : currentXMM) < xmmParameterRegisters.size()) {
+                        Register register = xmmParameterRegisters.get(unified ? currentGeneral++ : currentXMM++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 default:
                     throw JVMCIError.shouldNotReachHere();

@@ -253,10 +278,11 @@
                 ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
                 locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out);
                 currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
             }
         }
+        assert !unified || currentXMM == 0 : "shouldn't be used in unified mode";
 
         JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
         AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
         return new CallingConvention(currentStackOffset, returnLocation, locations);
     }
< prev index next >