< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java

Print this page

 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.internal.foreign.abi.x64.sysv;
 27 
 28 import jdk.incubator.foreign.FunctionDescriptor;
 29 import jdk.incubator.foreign.GroupLayout;
 30 import jdk.incubator.foreign.MemoryAddress;
 31 import jdk.incubator.foreign.MemoryLayout;
 32 import jdk.incubator.foreign.MemorySegment;


 33 import jdk.internal.foreign.abi.CallingSequenceBuilder;
 34 import jdk.internal.foreign.abi.UpcallHandler;
 35 import jdk.internal.foreign.abi.ABIDescriptor;
 36 import jdk.internal.foreign.abi.Binding;
 37 import jdk.internal.foreign.abi.CallingSequence;
 38 import jdk.internal.foreign.abi.ProgrammableInvoker;
 39 import jdk.internal.foreign.abi.ProgrammableUpcallHandler;
 40 import jdk.internal.foreign.abi.VMStorage;
 41 import jdk.internal.foreign.abi.x64.X86_64Architecture;
 42 import jdk.internal.foreign.abi.SharedUtils;
 43 
 44 import java.lang.invoke.MethodHandle;
 45 import java.lang.invoke.MethodHandles;
 46 import java.lang.invoke.MethodType;
 47 import java.util.List;
 48 import java.util.Optional;
 49 
 50 import static jdk.internal.foreign.PlatformLayouts.*;
 51 import static jdk.internal.foreign.abi.Binding.*;
 52 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
 53 import static jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.MAX_INTEGER_ARGUMENT_REGISTERS;
 54 import static jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.MAX_VECTOR_ARGUMENT_REGISTERS;

 69         new VMStorage[] { r10, r11 },
 70         new VMStorage[] { xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 },
 71         16,
 72         0 //no shadow space
 73     );
 74 
 75     // record
 76     public static class Bindings {
 77         public final CallingSequence callingSequence;
 78         public final boolean isInMemoryReturn;
 79         public final int nVectorArgs;
 80 
 81         Bindings(CallingSequence callingSequence, boolean isInMemoryReturn, int nVectorArgs) {
 82             this.callingSequence = callingSequence;
 83             this.isInMemoryReturn = isInMemoryReturn;
 84             this.nVectorArgs = nVectorArgs;
 85         }
 86     }
 87 
 88     public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) {
 89         SharedUtils.checkFunctionTypes(mt, cDesc, SysVx64Linker.ADDRESS_SIZE);
 90 
 91         CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall);
 92 
 93         BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true);
 94         BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false);
 95 
 96         boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout());
 97         if (returnInMemory) {
 98             Class<?> carrier = MemoryAddress.class;
 99             MemoryLayout layout = SysV.C_POINTER;
100             csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));
101         } else if (cDesc.returnLayout().isPresent()) {
102             Class<?> carrier = mt.returnType();
103             MemoryLayout layout = cDesc.returnLayout().get();
104             csb.setReturnBindings(carrier, layout, retCalc.getBindings(carrier, layout));
105         }
106 
107         for (int i = 0; i < mt.parameterCount(); i++) {
108             Class<?> carrier = mt.parameterType(i);
109             MemoryLayout layout = cDesc.argumentLayouts().get(i);
110             csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));

117         }
118 
119         csb.setTrivial(SharedUtils.isTrivial(cDesc));
120 
121         return new Bindings(csb.build(), returnInMemory, argCalc.storageCalculator.nVectorReg);
122     }
123 
124     public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) {
125         Bindings bindings = getBindings(mt, cDesc, false);
126 
127         MethodHandle handle = new ProgrammableInvoker(CSysV, bindings.callingSequence).getBoundMethodHandle();
128         handle = MethodHandles.insertArguments(handle, handle.type().parameterCount() - 1, bindings.nVectorArgs);
129 
130         if (bindings.isInMemoryReturn) {
131             handle = SharedUtils.adaptDowncallForIMR(handle, cDesc);
132         }
133 
134         return handle;
135     }
136 
137     public static UpcallHandler arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc) {
138         Bindings bindings = getBindings(mt, cDesc, true);
139 
140         if (bindings.isInMemoryReturn) {
141             target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */);
142         }
143 
144         return ProgrammableUpcallHandler.make(CSysV, target, bindings.callingSequence);
145     }
146 
147     private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {
148         return returnLayout
149                 .filter(GroupLayout.class::isInstance)
150                 .filter(g -> TypeClass.classifyLayout(g).inMemory())
151                 .isPresent();
152     }
153 
154     static class StorageCalculator {
155         private final boolean forArguments;
156 
157         private int nVectorReg = 0;
158         private int nIntegerReg = 0;
159         private long stackOffset = 0;
160 
161         public StorageCalculator(boolean forArguments) {
162             this.forArguments = forArguments;
163         }
164 

263                 case STRUCT: {
264                     assert carrier == MemorySegment.class;
265                     VMStorage[] regs = storageCalculator.structStorages(argumentClass);
266                     int regIndex = 0;
267                     long offset = 0;
268                     while (offset < layout.byteSize()) {
269                         final long copy = Math.min(layout.byteSize() - offset, 8);
270                         VMStorage storage = regs[regIndex++];
271                         if (offset + copy < layout.byteSize()) {
272                             bindings.dup();
273                         }
274                         boolean useFloat = storage.type() == StorageClasses.VECTOR;
275                         Class<?> type = SharedUtils.primitiveCarrierForSize(copy, useFloat);
276                         bindings.bufferLoad(offset, type)
277                                 .vmStore(storage, type);
278                         offset += copy;
279                     }
280                     break;
281                 }
282                 case POINTER: {
283                     bindings.unboxAddress();
284                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER);
285                     bindings.vmStore(storage, long.class);
286                     break;
287                 }
288                 case INTEGER: {
289                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER);
290                     bindings.vmStore(storage, carrier);
291                     break;
292                 }
293                 case FLOAT: {
294                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR);
295                     bindings.vmStore(storage, carrier);
296                     break;
297                 }
298                 default:
299                     throw new UnsupportedOperationException("Unhandled class " + argumentClass);
300             }
301             return bindings.build();
302         }
303     }

 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.internal.foreign.abi.x64.sysv;
 27 
 28 import jdk.incubator.foreign.FunctionDescriptor;
 29 import jdk.incubator.foreign.GroupLayout;
 30 import jdk.incubator.foreign.MemoryAddress;
 31 import jdk.incubator.foreign.MemoryLayout;
 32 import jdk.incubator.foreign.MemorySegment;
 33 import jdk.incubator.foreign.NativeSymbol;
 34 import jdk.incubator.foreign.ResourceScope;
 35 import jdk.internal.foreign.abi.CallingSequenceBuilder;

 36 import jdk.internal.foreign.abi.ABIDescriptor;
 37 import jdk.internal.foreign.abi.Binding;
 38 import jdk.internal.foreign.abi.CallingSequence;
 39 import jdk.internal.foreign.abi.ProgrammableInvoker;
 40 import jdk.internal.foreign.abi.ProgrammableUpcallHandler;
 41 import jdk.internal.foreign.abi.VMStorage;
 42 import jdk.internal.foreign.abi.x64.X86_64Architecture;
 43 import jdk.internal.foreign.abi.SharedUtils;
 44 
 45 import java.lang.invoke.MethodHandle;
 46 import java.lang.invoke.MethodHandles;
 47 import java.lang.invoke.MethodType;
 48 import java.util.List;
 49 import java.util.Optional;
 50 
 51 import static jdk.internal.foreign.PlatformLayouts.*;
 52 import static jdk.internal.foreign.abi.Binding.*;
 53 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
 54 import static jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.MAX_INTEGER_ARGUMENT_REGISTERS;
 55 import static jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.MAX_VECTOR_ARGUMENT_REGISTERS;

 70         new VMStorage[] { r10, r11 },
 71         new VMStorage[] { xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 },
 72         16,
 73         0 //no shadow space
 74     );
 75 
 76     // record
 77     public static class Bindings {
 78         public final CallingSequence callingSequence;
 79         public final boolean isInMemoryReturn;
 80         public final int nVectorArgs;
 81 
 82         Bindings(CallingSequence callingSequence, boolean isInMemoryReturn, int nVectorArgs) {
 83             this.callingSequence = callingSequence;
 84             this.isInMemoryReturn = isInMemoryReturn;
 85             this.nVectorArgs = nVectorArgs;
 86         }
 87     }
 88 
 89     public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) {


 90         CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall);
 91 
 92         BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true);
 93         BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false);
 94 
 95         boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout());
 96         if (returnInMemory) {
 97             Class<?> carrier = MemoryAddress.class;
 98             MemoryLayout layout = SysV.C_POINTER;
 99             csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));
100         } else if (cDesc.returnLayout().isPresent()) {
101             Class<?> carrier = mt.returnType();
102             MemoryLayout layout = cDesc.returnLayout().get();
103             csb.setReturnBindings(carrier, layout, retCalc.getBindings(carrier, layout));
104         }
105 
106         for (int i = 0; i < mt.parameterCount(); i++) {
107             Class<?> carrier = mt.parameterType(i);
108             MemoryLayout layout = cDesc.argumentLayouts().get(i);
109             csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));

116         }
117 
118         csb.setTrivial(SharedUtils.isTrivial(cDesc));
119 
120         return new Bindings(csb.build(), returnInMemory, argCalc.storageCalculator.nVectorReg);
121     }
122 
123     public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) {
124         Bindings bindings = getBindings(mt, cDesc, false);
125 
126         MethodHandle handle = new ProgrammableInvoker(CSysV, bindings.callingSequence).getBoundMethodHandle();
127         handle = MethodHandles.insertArguments(handle, handle.type().parameterCount() - 1, bindings.nVectorArgs);
128 
129         if (bindings.isInMemoryReturn) {
130             handle = SharedUtils.adaptDowncallForIMR(handle, cDesc);
131         }
132 
133         return handle;
134     }
135 
136     public static NativeSymbol arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, ResourceScope scope) {
137         Bindings bindings = getBindings(mt, cDesc, true);
138 
139         if (bindings.isInMemoryReturn) {
140             target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */);
141         }
142 
143         return ProgrammableUpcallHandler.make(CSysV, target, bindings.callingSequence, scope);
144     }
145 
146     private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {
147         return returnLayout
148                 .filter(GroupLayout.class::isInstance)
149                 .filter(g -> TypeClass.classifyLayout(g).inMemory())
150                 .isPresent();
151     }
152 
153     static class StorageCalculator {
154         private final boolean forArguments;
155 
156         private int nVectorReg = 0;
157         private int nIntegerReg = 0;
158         private long stackOffset = 0;
159 
160         public StorageCalculator(boolean forArguments) {
161             this.forArguments = forArguments;
162         }
163 

262                 case STRUCT: {
263                     assert carrier == MemorySegment.class;
264                     VMStorage[] regs = storageCalculator.structStorages(argumentClass);
265                     int regIndex = 0;
266                     long offset = 0;
267                     while (offset < layout.byteSize()) {
268                         final long copy = Math.min(layout.byteSize() - offset, 8);
269                         VMStorage storage = regs[regIndex++];
270                         if (offset + copy < layout.byteSize()) {
271                             bindings.dup();
272                         }
273                         boolean useFloat = storage.type() == StorageClasses.VECTOR;
274                         Class<?> type = SharedUtils.primitiveCarrierForSize(copy, useFloat);
275                         bindings.bufferLoad(offset, type)
276                                 .vmStore(storage, type);
277                         offset += copy;
278                     }
279                     break;
280                 }
281                 case POINTER: {
282                     bindings.unboxAddress(carrier);
283                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER);
284                     bindings.vmStore(storage, long.class);
285                     break;
286                 }
287                 case INTEGER: {
288                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER);
289                     bindings.vmStore(storage, carrier);
290                     break;
291                 }
292                 case FLOAT: {
293                     VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR);
294                     bindings.vmStore(storage, carrier);
295                     break;
296                 }
297                 default:
298                     throw new UnsupportedOperationException("Unhandled class " + argumentClass);
299             }
300             return bindings.build();
301         }
302     }
< prev index next >