changeset 23693:0d09e13523b4 jvmci-0.14

SPARCHotSpotRegisterConfig.callingConvention gives incorrect calling convention for native calls containing fp args (JDK-8159368)
author Doug Simon <doug.simon@oracle.com>
date Thu, 16 Jun 2016 18:39:34 +0200
parents 93be30973b26
children 46b440623a7f
files jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java
diffstat 1 files changed, 101 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Jun 16 18:23:03 2016 +0200
+++ b/jvmci/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Jun 16 18:39:34 2016 +0200
@@ -26,17 +26,41 @@
 import static jdk.vm.ci.meta.Value.ILLEGAL;
 import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE;
 import static jdk.vm.ci.sparc.SPARC.d0;
+import static jdk.vm.ci.sparc.SPARC.d10;
+import static jdk.vm.ci.sparc.SPARC.d12;
+import static jdk.vm.ci.sparc.SPARC.d14;
+import static jdk.vm.ci.sparc.SPARC.d16;
+import static jdk.vm.ci.sparc.SPARC.d18;
 import static jdk.vm.ci.sparc.SPARC.d2;
+import static jdk.vm.ci.sparc.SPARC.d20;
+import static jdk.vm.ci.sparc.SPARC.d22;
+import static jdk.vm.ci.sparc.SPARC.d24;
+import static jdk.vm.ci.sparc.SPARC.d26;
+import static jdk.vm.ci.sparc.SPARC.d28;
+import static jdk.vm.ci.sparc.SPARC.d30;
 import static jdk.vm.ci.sparc.SPARC.d4;
 import static jdk.vm.ci.sparc.SPARC.d6;
+import static jdk.vm.ci.sparc.SPARC.d8;
 import static jdk.vm.ci.sparc.SPARC.f0;
 import static jdk.vm.ci.sparc.SPARC.f1;
+import static jdk.vm.ci.sparc.SPARC.f11;
+import static jdk.vm.ci.sparc.SPARC.f13;
+import static jdk.vm.ci.sparc.SPARC.f15;
+import static jdk.vm.ci.sparc.SPARC.f17;
+import static jdk.vm.ci.sparc.SPARC.f19;
 import static jdk.vm.ci.sparc.SPARC.f2;
+import static jdk.vm.ci.sparc.SPARC.f21;
+import static jdk.vm.ci.sparc.SPARC.f23;
+import static jdk.vm.ci.sparc.SPARC.f25;
+import static jdk.vm.ci.sparc.SPARC.f27;
+import static jdk.vm.ci.sparc.SPARC.f29;
 import static jdk.vm.ci.sparc.SPARC.f3;
+import static jdk.vm.ci.sparc.SPARC.f31;
 import static jdk.vm.ci.sparc.SPARC.f4;
 import static jdk.vm.ci.sparc.SPARC.f5;
 import static jdk.vm.ci.sparc.SPARC.f6;
 import static jdk.vm.ci.sparc.SPARC.f7;
+import static jdk.vm.ci.sparc.SPARC.f9;
 import static jdk.vm.ci.sparc.SPARC.g0;
 import static jdk.vm.ci.sparc.SPARC.g2;
 import static jdk.vm.ci.sparc.SPARC.g6;
@@ -96,11 +120,6 @@
 
     private final RegisterAttributes[] attributesMap;
 
-    /**
-     * Does native code (C++ code) spill arguments in registers to the parent frame?
-     */
-    private final boolean addNativeRegisterArgumentSlots;
-
     @Override
     public Register[] getAllocatableRegisters() {
         return allocatable.clone();
@@ -126,17 +145,25 @@
     private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
     private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
 
-    private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
-    private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
+    private final Register[] fpuFloatJavaParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
+    private final Register[] fpuDoubleJavaParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
 
     // @formatter:off
+    private final Register[] fpuFloatNativeParameterRegisters = {
+                    f1,   f3,  f5,  f7,  f9, f11, f13, f15,
+                    f17, f19, f21, f23, f25, f27, f29, f31};
+
+    private final Register[] fpuDoubleNativeParameterRegisters = {
+                     d0,  d2,  d4,  d6,  d8, d10, d12, d14,
+                    d16, d18, d20, d22, d24, d26, d28, d30};
+
     private final Register[] callerSaveRegisters;
 
     /**
      * Registers saved by the callee. This lists all L and I registers which are saved in the
      * register window.
      */
-    private final Register[] windowSaveRegisters = {
+    private final Register[] calleeSaveRegisters = {
                     l0, l1, l2, l3, l4, l5, l6, l7,
                     i0, i1, i2, i3, i4, i5, i6, i7};
     // @formatter:on
@@ -173,10 +200,9 @@
     public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
         this.target = target;
         this.allocatable = allocatable.clone();
-        this.addNativeRegisterArgumentSlots = false;
         HashSet<Register> callerSaveSet = new HashSet<>();
         Collections.addAll(callerSaveSet, target.arch.getAvailableValueRegisters());
-        for (Register cs : windowSaveRegisters) {
+        for (Register cs : calleeSaveRegisters) {
             callerSaveSet.remove(cs);
         }
         this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
@@ -189,7 +215,7 @@
     }
 
     public Register[] getCalleeSaveRegisters() {
-        return windowSaveRegisters;
+        return calleeSaveRegisters;
     }
 
     @Override
@@ -223,7 +249,7 @@
                 return hotspotType == HotSpotCallingConventionType.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
             case Double:
             case Float:
-                return fpuFloatParameterRegisters;
+                return fpuFloatJavaParameterRegisters;
             default:
                 throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
         }
@@ -236,48 +262,77 @@
         int currentGeneral = 0;
         int currentFloating = 0;
         int currentStackOffset = 0;
+        boolean isNative = type == HotSpotCallingConventionType.NativeCall;
 
         for (int i = 0; i < parameterTypes.length; i++) {
             final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
-
-            switch (kind) {
-                case Byte:
-                case Boolean:
-                case Short:
-                case Char:
-                case Int:
-                case Long:
-                case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
-                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
-                    }
-                    break;
-                case Double:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
-                        if (currentFloating % 2 != 0) {
-                            // Make register number even to be a double reg
-                            currentFloating++;
+            if (isNative) {
+                Register[] registerSet;
+                switch (kind) {
+                    case Byte:
+                    case Boolean:
+                    case Short:
+                    case Char:
+                    case Int:
+                    case Long:
+                    case Object:
+                        registerSet = generalParameterRegisters;
+                        break;
+                    case Double:
+                        registerSet = fpuDoubleNativeParameterRegisters;
+                        break;
+                    case Float:
+                        registerSet = fpuFloatNativeParameterRegisters;
+                        break;
+                    default:
+                        throw JVMCIError.shouldNotReachHere();
+                }
+                if (i < registerSet.length) {
+                    locations[i] = registerSet[i].asValue(valueKindFactory.getValueKind(kind));
+                    currentStackOffset += target.arch.getWordSize();
+                }
+            } else {
+                switch (kind) {
+                    case Byte:
+                    case Boolean:
+                    case Short:
+                    case Char:
+                    case Int:
+                    case Long:
+                    case Object:
+                        if (currentGeneral < generalParameterRegisters.length) {
+                            Register register = generalParameterRegisters[currentGeneral++];
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                         }
-                        Register register = fpuDoubleParameterRegisters[currentFloating];
-                        currentFloating += 2; // Only every second is a double register
-                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
-                    }
-                    break;
-                case Float:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
-                        Register register = fpuFloatParameterRegisters[currentFloating++];
-                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
-                    }
-                    break;
-                default:
-                    throw JVMCIError.shouldNotReachHere();
+                        break;
+                    case Double:
+                        if (currentFloating < fpuFloatJavaParameterRegisters.length) {
+                            if (currentFloating % 2 != 0) {
+                                // Make register number even to be a double reg
+                                currentFloating++;
+                            }
+                            Register register = fpuDoubleJavaParameterRegisters[currentFloating];
+                            currentFloating += 2; // Only every second is a double register
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                        }
+                        break;
+                    case Float:
+                        if (currentFloating < fpuFloatJavaParameterRegisters.length) {
+                            Register register = fpuFloatJavaParameterRegisters[currentFloating++];
+                            locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
+                        }
+                        break;
+                    default:
+                        throw JVMCIError.shouldNotReachHere();
+                }
             }
 
             if (locations[i] == null) {
                 ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
-                // Stack slot is always aligned to its size in bytes but minimum wordsize
                 int typeSize = valueKind.getPlatformKind().getSizeInBytes();
+                if (isNative) {
+                    currentStackOffset += target.arch.getWordSize() - typeSize;
+                }
                 currentStackOffset = roundUp(currentStackOffset, typeSize);
                 int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
                 locations[i] = StackSlot.get(valueKind, slotOffset, !type.out);
@@ -287,15 +342,7 @@
 
         JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
         AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
-
-        int outArgSpillArea;
-        if (type == HotSpotCallingConventionType.NativeCall && addNativeRegisterArgumentSlots) {
-            // Space for native callee which may spill our outgoing arguments
-            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
-        } else {
-            outArgSpillArea = 0;
-        }
-        return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
     }
 
     private static int roundUp(int number, int mod) {