< prev index next >

src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallingSequenceBuilderImpl.java

Print this page

        

@@ -20,113 +20,109 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 package jdk.internal.foreign.abi.x64.sysv;
 
-import java.foreign.NativeMethodType;
-import java.foreign.NativeTypes;
 import java.foreign.layout.Address;
 import java.foreign.layout.Group;
 import java.foreign.layout.Group.Kind;
 import java.foreign.layout.Layout;
 import java.foreign.layout.Padding;
 import java.foreign.layout.Sequence;
 import java.foreign.layout.Value;
-import java.foreign.memory.LayoutType;
 import java.util.ArrayList;
-import java.util.stream.Stream;
+import java.util.List;
+import java.util.function.BiConsumer;
+
 import jdk.internal.foreign.Util;
 import jdk.internal.foreign.abi.Argument;
 import jdk.internal.foreign.abi.ArgumentBinding;
-import jdk.internal.foreign.abi.CallingSequence;
+import jdk.internal.foreign.abi.CallingSequenceBuilder;
 import jdk.internal.foreign.abi.Storage;
 import jdk.internal.foreign.abi.StorageClass;
-import jdk.internal.foreign.abi.x64.CallingSequenceBuilder;
 import jdk.internal.foreign.abi.x64.ArgumentClass;
-import jdk.internal.foreign.abi.x64.SharedConstants;
+import jdk.internal.foreign.abi.x64.SharedUtils;
 
 import static sun.security.action.GetBooleanAction.privilegedGetProperty;
 
-public class StandardCall extends CallingSequenceBuilder {
-    private static final String[] INTEGER_ARGUMENT_REGISTER_NAMES = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
-    private static final String[] INTEGER_RETURN_REGISTERS_NAMES = { "rax", "rdx" };
-    private static final String[] X87_RETURN_REGISTERS_NAMES = { "st0", "st1" };
+public class CallingSequenceBuilderImpl extends CallingSequenceBuilder {
+
+    private static final SharedUtils.StorageDebugHelper storageDbgHelper = new SharedUtils.StorageDebugHelper(
+            new String[] { "rdi", "rsi", "rdx", "rcx", "r8", "r9" },
+            new String[] { "rax", "rdx" },
+            new String[] { "st0", "st1" },
+            SysVx64ABI.MAX_VECTOR_ARGUMENT_REGISTERS,
+            SysVx64ABI.MAX_VECTOR_RETURN_REGISTERS
+    );
 
     private static final boolean DEBUG =
         privilegedGetProperty("jdk.internal.foreign.abi.x64.sysv.DEBUG");
 
     // The AVX 512 enlightened ABI says "eight eightbytes"
     // Although AMD64 0.99.6 states 4 eightbytes
     private static final int MAX_AGGREGATE_REGS_SIZE = 8;
 
     private static final ArrayList<ArgumentClass> COMPLEX_X87_CLASSES;
-    private static final SysVx64ABI abi = SysVx64ABI.getInstance();
 
     static {
         COMPLEX_X87_CLASSES = new ArrayList<>();
         COMPLEX_X87_CLASSES.add(ArgumentClass.X87);
         COMPLEX_X87_CLASSES.add(ArgumentClass.X87UP);
         COMPLEX_X87_CLASSES.add(ArgumentClass.X87);
         COMPLEX_X87_CLASSES.add(ArgumentClass.X87UP);
     }
 
-    public StandardCall() {
-        super(INTEGER_ARGUMENT_REGISTER_NAMES, INTEGER_RETURN_REGISTERS_NAMES, X87_RETURN_REGISTERS_NAMES,
-                Constants.MAX_VECTOR_ARGUMENT_REGISTERS, Constants.MAX_VECTOR_RETURN_REGISTERS);
+    public CallingSequenceBuilderImpl(Layout layout) {
+        this(layout, new StorageCalculator(false), new StorageCalculator(true));
     }
 
-    static class ArgumentInfo {
-        private final ArrayList<ArgumentClass> classes;
-        private final int nIntegerRegs, nVectorRegs, nX87Regs;
-        private final boolean inMemory;
-
-        public ArgumentInfo(ArrayList<ArgumentClass> classes, int nIntegerRegs, int nVectorRegs, int nX87Regs) {
-            this.classes = classes;
-
-            this.nIntegerRegs = nIntegerRegs;
-            this.nVectorRegs = nVectorRegs;
-            this.nX87Regs = nX87Regs;
-
-            this.inMemory = false;
+    private CallingSequenceBuilderImpl(Layout layout, StorageCalculator retCalculator, StorageCalculator argCalculator) {
+        super(layout, retCalculator::addBindings, argCalculator::addBindings, argCalculator::addBindings);
         }
 
-        public ArgumentInfo(int n) {
-            this.classes = new ArrayList<>();
-            for (int i = 0; i < n; i++) {
-                classes.add(ArgumentClass.MEMORY);
+    @Override
+    protected ArgumentInfo makeArgument(Layout layout, int pos, String name) {
+        return new ArgumentInfo(layout, pos, name);
             }
 
-            this.inMemory = true;
-            this.nIntegerRegs = 0;
-            this.nVectorRegs = 0;
-            this.nX87Regs = 0;
+    static class ArgumentInfo extends Argument {
+        private final List<ArgumentClass> classes;
+
+        public ArgumentInfo(Layout layout, int argumentIndex, String debugName) {
+            super(layout, argumentIndex, debugName);
+            this.classes = classifyType(layout);
         }
 
         public int getIntegerRegs() {
-            return nIntegerRegs;
+            return (int)classes.stream()
+                    .filter(cl -> cl == ArgumentClass.INTEGER)
+                    .count();
         }
 
         public int getVectorRegs() {
-            return nVectorRegs;
+            return (int)classes.stream()
+                    .filter(cl -> cl == ArgumentClass.SSE)
+                    .count();
         }
 
-        public int getX87Regs() {
-            return nX87Regs;
+        @Override
+        public boolean inMemory() {
+            return classes.stream().allMatch(this::isMemoryClass);
         }
 
-        public boolean inMemory() {
-            return inMemory;
+        private boolean isMemoryClass(ArgumentClass cl) {
+            return cl == ArgumentClass.MEMORY ||
+                    (argumentIndex() != -1 &&
+                            (cl == ArgumentClass.X87 || cl == ArgumentClass.X87UP));
         }
 
-        public ArrayList<ArgumentClass> getClasses() {
+        public List<ArgumentClass> getClasses() {
             return classes;
         }
-
-        static ArgumentInfo EMPTY = new ArgumentInfo(new ArrayList<>(), 0, 0, 0);
     }
 
-    private ArrayList<ArgumentClass> classifyValueType(Value type) {
+    private static List<ArgumentClass> classifyValueType(Value type) {
         ArrayList<ArgumentClass> classes = new ArrayList<>();
 
         switch (type.kind()) {
             case INTEGRAL_SIGNED: case INTEGRAL_UNSIGNED:
                 classes.add(ArgumentClass.INTEGER);

@@ -149,11 +145,11 @@
             default:
                 throw new IllegalArgumentException("Type " + type + " is not yet supported");
         }
     }
 
-    private ArrayList<ArgumentClass> classifyArrayType(Sequence type) {
+    private static List<ArgumentClass> classifyArrayType(Sequence type) {
         long nWords = Util.alignUp((type.bitsSize() / 8), 8) / 8;
         if (nWords > MAX_AGGREGATE_REGS_SIZE) {
             return createMemoryClassArray(nWords);
         }
 

@@ -165,12 +161,12 @@
 
         long offset = 0;
         final long count = type.elementsSize();
         for (long idx = 0; idx < count; idx++) {
             Layout t = type.element();
-            offset = align(t, false, offset);
-            ArrayList<ArgumentClass> subclasses = classifyType(t);
+            offset = SharedUtils.align(t, false, offset);
+            List<ArgumentClass> subclasses = classifyType(t);
             if (subclasses.isEmpty()) {
                 return classes;
             }
 
             for (int i = 0; i < subclasses.size(); i++) {

@@ -215,11 +211,11 @@
         return classes;
     }
 
     // TODO: handle zero length arrays
     // TODO: Handle nested structs (and primitives)
-    private ArrayList<ArgumentClass> classifyStructType(Group type) {
+    private static List<ArgumentClass> classifyStructType(Group type) {
         long nWords = Util.alignUp((type.bitsSize() / 8), 8) / 8;
         if (nWords > MAX_AGGREGATE_REGS_SIZE) {
             return createMemoryClassArray(nWords);
         }
 

@@ -241,12 +237,12 @@
             if (t instanceof Sequence) {
                 if (((Sequence) t).elementsSize() == 0) {
                     continue;
                 }
             }
-            offset = align(t, false, offset);
-            ArrayList<ArgumentClass> subclasses = classifyType(t);
+            offset = SharedUtils.align(t, false, offset);
+            List<ArgumentClass> subclasses = classifyType(t);
             if (subclasses.isEmpty()) {
                 return classes;
             }
 
             for (int i = 0; i < subclasses.size(); i++) {

@@ -292,11 +288,11 @@
         }
 
         return classes;
     }
 
-    private ArrayList<ArgumentClass> classifyType(Layout type) {
+    private static List<ArgumentClass> classifyType(Layout type) {
         try {
             if (type instanceof Value) {
                 return classifyValueType((Value) type);
             } else if (type instanceof Address) {
                 ArrayList<ArgumentClass> classes = new ArrayList<>();

@@ -315,114 +311,71 @@
             System.err.println("Failed to classify layout: " + type);
             throw e;
         }
     }
 
-    private ArrayList<ArgumentClass> createMemoryClassArray(long n) {
+    private static List<ArgumentClass> createMemoryClassArray(long n) {
         ArrayList<ArgumentClass> classes = new ArrayList<>();
         for (int i = 0; i < n; i++) {
             classes.add(ArgumentClass.MEMORY);
         }
 
         return classes;
     }
 
-    private ArgumentInfo examineArgument(boolean forArguments, Layout type) {
-        ArrayList<ArgumentClass> classes = classifyType(type);
-        if (classes.isEmpty()) {
-            return ArgumentInfo.EMPTY;
-        }
-
-        int nIntegerRegs = 0;
-        int nVectorRegs = 0;
-        int nX87Regs = 0;
-
-        for (ArgumentClass c : classes) {
-            switch (c) {
-            case INTEGER:
-                nIntegerRegs++;
-                break;
-            case SSE:
-                nVectorRegs++;
-                break;
-            case X87:
-            case X87UP:
-                if (forArguments) {
-                    return new ArgumentInfo(classes.size());
-                } else {
-                    nX87Regs++;
-                    break;
-                }
-            default:
-                break;
-            }
-        }
-
-        if (nIntegerRegs != 0 || nVectorRegs != 0 || nX87Regs != 0) {
-            return new ArgumentInfo(classes, nIntegerRegs, nVectorRegs, nX87Regs);
-        } else {
-            return new ArgumentInfo(classes.size());
-        }
-    }
-
-    class StorageCalculator {
-        private final ArrayList<ArgumentBinding>[] bindings;
+    static class StorageCalculator {
         private final boolean forArguments;
 
         private int nIntegerRegs = 0;
         private int nVectorRegs = 0;
         private int nX87Regs = 0;
         private long stackOffset = 0;
 
-        StorageCalculator(ArrayList<ArgumentBinding>[] bindings, boolean forArguments) {
-            this.bindings = bindings;
+        StorageCalculator(boolean forArguments) {
             this.forArguments = forArguments;
         }
 
-        void addBindings(Argument arg, ArgumentInfo info) {
+        public void addBindings(Argument arg, BiConsumer<StorageClass, ArgumentBinding> bindingConsumer) {
+            ArgumentInfo info = (ArgumentInfo)arg;
             if (info.inMemory() ||
-                    nIntegerRegs + info.getIntegerRegs() > (forArguments ? Constants.MAX_INTEGER_ARGUMENT_REGISTERS : Constants.MAX_INTEGER_RETURN_REGISTERS) ||
-                    nVectorRegs + info.getVectorRegs() > (forArguments ? Constants.MAX_VECTOR_ARGUMENT_REGISTERS : Constants.MAX_VECTOR_RETURN_REGISTERS)) {
+                    nIntegerRegs + info.getIntegerRegs() > (forArguments ? SysVx64ABI.MAX_INTEGER_ARGUMENT_REGISTERS : SysVx64ABI.MAX_INTEGER_RETURN_REGISTERS) ||
+                    nVectorRegs + info.getVectorRegs() > (forArguments ? SysVx64ABI.MAX_VECTOR_ARGUMENT_REGISTERS : SysVx64ABI.MAX_VECTOR_RETURN_REGISTERS)) {
                 // stack
 
-                long alignment = Math.max(alignment(arg.getType(), true), 8);
+                long alignment = Math.max(SharedUtils.alignment(info.layout(), true), 8);
 
                 long newStackOffset = Util.alignUp(stackOffset, alignment);
-
-                // fill holes on stack with nulls
-                for (int i = 0; i < (newStackOffset - stackOffset) / 8; i++) {
-                    bindings[StorageClass.STACK_ARGUMENT_SLOT.ordinal()].add(null);
-                }
                 stackOffset = newStackOffset;
 
                 long tmpStackOffset = stackOffset;
                 for (int i = 0; i < info.getClasses().size(); i++) {
                     Storage storage = new Storage(StorageClass.STACK_ARGUMENT_SLOT, tmpStackOffset / 8, 8);
-                    bindings[StorageClass.STACK_ARGUMENT_SLOT.ordinal()].add(new ArgumentBinding(storage, arg, i * 8));
+                    bindingConsumer.accept(StorageClass.STACK_ARGUMENT_SLOT, new ArgumentBinding(storage, info, i * 8));
 
                     if (DEBUG) {
-                        System.out.println("Argument " + arg.getName() + " will be passed on stack at offset " + tmpStackOffset);
+                        System.out.println("Argument " + info.name() + " will be passed on stack at offset " + tmpStackOffset);
                     }
 
                     tmpStackOffset += 8;
                 }
 
-                stackOffset += arg.getType().bitsSize() / 8;
+                stackOffset += info.layout().bitsSize() / 8;
             } else {
                 // regs
                 for (int i = 0; i < info.getClasses().size(); i++) {
                     Storage storage;
 
                     ArgumentClass c = info.getClasses().get(i);
 
                     switch (c) {
                     case INTEGER:
-                        storage = new Storage(forArguments ? StorageClass.INTEGER_ARGUMENT_REGISTER : StorageClass.INTEGER_RETURN_REGISTER, nIntegerRegs++, SharedConstants.INTEGER_REGISTER_SIZE);
-                        bindings[storage.getStorageClass().ordinal()].add(new ArgumentBinding(storage, arg, i * 8));
+                        storage = new Storage(forArguments ? StorageClass.INTEGER_ARGUMENT_REGISTER : StorageClass.INTEGER_RETURN_REGISTER, nIntegerRegs++, SharedUtils.INTEGER_REGISTER_SIZE);
+                        bindingConsumer.accept(storage.getStorageClass(), new ArgumentBinding(storage, info, i * 8));
 
                         if (DEBUG) {
-                            System.out.println("Argument " + arg.getName() + " will be passed in register " + getStorageName(storage));
+                            System.out.println("Argument " + info.name() + " will be passed in register " +
+                                    storageDbgHelper.getStorageName(storage));
                         }
                         break;
 
                     case SSE: {
                         int width = 8;

@@ -435,15 +388,18 @@
 
                         if (width > 64) {
                             throw new IllegalArgumentException((width * 8) + "-bit vector arguments not supported");
                         }
 
-                        storage = new Storage(forArguments ? StorageClass.VECTOR_ARGUMENT_REGISTER : StorageClass.VECTOR_RETURN_REGISTER, nVectorRegs++, width);
-                        bindings[storage.getStorageClass().ordinal()].add(new ArgumentBinding(storage, arg, i * 8));
+                        storage = new Storage(forArguments ? StorageClass.VECTOR_ARGUMENT_REGISTER : StorageClass.VECTOR_RETURN_REGISTER,
+                                nVectorRegs++, width, SharedUtils.VECTOR_REGISTER_SIZE);
+
+                        bindingConsumer.accept(storage.getStorageClass(), new ArgumentBinding(storage, info, i * 8));
 
                         if (DEBUG) {
-                            System.out.println("Argument " + arg.getName() + " will be passed in register " + getStorageName(storage));
+                            System.out.println("Argument " + info.name() + " will be passed in register " +
+                                    storageDbgHelper.getStorageName(storage));
                         }
                         break;
                     }
 
                     case SSEUP:

@@ -456,15 +412,16 @@
                             width += 8;
                         }
 
                         assert !forArguments;
 
-                        storage = new Storage(StorageClass.X87_RETURN_REGISTER, nX87Regs++, width);
-                        bindings[storage.getStorageClass().ordinal()].add(new ArgumentBinding(storage, arg, i * 8));
+                        storage = new Storage(StorageClass.X87_RETURN_REGISTER, nX87Regs++, width, SharedUtils.X87_REGISTER_SIZE);
+                        bindingConsumer.accept(storage.getStorageClass(), new ArgumentBinding(storage, info, i * 8));
 
                         if (DEBUG) {
-                            System.out.println("Argument " + arg.getName() + " will be passed in register " + getStorageName(storage));
+                            System.out.println("Argument " + info.name() + " will be passed in register " +
+                                    storageDbgHelper.getStorageName(storage));
                         }
                         break;
                     }
 
                     case X87UP:

@@ -475,52 +432,6 @@
                     }
                 }
             }
         }
     }
-
-    private void addBindings(ArrayList<Argument> members, StorageCalculator calculator) {
-        members.stream().forEach(arg -> calculator.addBindings(arg, examineArgument(calculator.forArguments, arg.getType())));
-    }
-
-    public CallingSequence arrangeCall(NativeMethodType nmt) {
-        return arrangeCall(nmt.returnType() == NativeTypes.VOID ? null : nmt.returnType().layout(),
-                Stream.of(nmt.parameterArray()).map(LayoutType::layout).toArray(Layout[]::new));
-    }
-
-    public CallingSequence arrangeCall(Layout ret, Layout... params) {
-        ArrayList<Argument> returns = new ArrayList<>();
-        ArrayList<Argument> args = new ArrayList<>();
-        boolean returnsInMemory = false;
-
-        if (ret != null) {
-            returnsInMemory = examineArgument(false, ret).inMemory();
-
-            // In some cases the return is passed in as first implicit pointer argument, and a corresponding pointer type is returned
-            if (returnsInMemory) {
-                args = new ArrayList<>();
-
-                Argument returnPointer = new Argument(-1, Address.ofLayout(64, ret), "__retval");
-                args.add(returnPointer);
-                returns.add(returnPointer);
-            } else {
-                returns.add(new Argument(-1, ret, "__retval"));
-            }
-        }
-
-        for (int i = 0; i < params.length; i++) {
-            args.add(new Argument(i, params[i], "arg" + i));
-        }
-
-        @SuppressWarnings("unchecked")
-        ArrayList<ArgumentBinding>[] bindings = (ArrayList<ArgumentBinding>[]) new ArrayList<?>[StorageClass.values().length];
-
-        for (int i = 0; i < StorageClass.values().length; i++) {
-            bindings[i] = new ArrayList<>();
-        }
-
-        addBindings(args, new StorageCalculator(bindings, true));
-        addBindings(returns, new StorageCalculator(bindings, false));
-
-        return new CallingSequence(params.length, bindings, returnsInMemory);
-    }
 }
< prev index next >