< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java

Print this page

  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.internal.foreign.abi;
 24 
 25 import jdk.incubator.foreign.FunctionDescriptor;
 26 import jdk.incubator.foreign.MemoryAddress;
 27 import jdk.incubator.foreign.MemoryLayout;
 28 import jdk.incubator.foreign.MemorySegment;
 29 import sun.security.action.GetPropertyAction;
 30 
 31 import java.lang.invoke.MethodType;
 32 import java.util.ArrayDeque;
 33 import java.util.ArrayList;
 34 import java.util.Deque;
 35 import java.util.List;
 36 
 37 public class CallingSequenceBuilder {
 38     private static final boolean VERIFY_BINDINGS = Boolean.parseBoolean(
 39             GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.VERIFY_BINDINGS", "true"));
 40 
 41     private final boolean forUpcall;
 42     private final List<List<Binding>> inputBindings = new ArrayList<>();
 43     private List<Binding> outputBindings = List.of();
 44 
 45     private MethodType mt = MethodType.methodType(void.class);
 46     private FunctionDescriptor desc = FunctionDescriptor.ofVoid();
 47 
 48     public CallingSequenceBuilder(boolean forUpcall) {

 64         this.outputBindings = bindings;
 65         mt = mt.changeReturnType(carrier);
 66         desc = desc.changeReturnLayout(layout);
 67         return this;
 68     }
 69 
 70     public CallingSequence build() {
 71         return new CallingSequence(mt, desc, inputBindings, outputBindings);
 72     }
 73 
 74     private void verifyBindings(boolean forArguments, Class<?> carrier, List<Binding> bindings) {
 75         if (VERIFY_BINDINGS) {
 76             if (forUpcall == forArguments) {
 77                 verifyBoxBindings(carrier, bindings);
 78             } else {
 79                 verifyUnboxBindings(carrier, bindings);
 80             }
 81         }
 82     }
 83 
 84     private static void checkType(Class<?> actualType, Class<?> expectedType) {
 85         if (expectedType != actualType) {
 86             throw new IllegalArgumentException(
 87                     String.format("Invalid operand type: %s. %s expected", actualType, expectedType));
 88         }
 89     }
 90 
 91     private static void verifyUnboxBindings(Class<?> inType, List<Binding> bindings) {
 92         Deque<Class<?>> stack = new ArrayDeque<>();
 93         stack.push(inType);
 94 
 95         for (Binding b : bindings) {
 96             switch (b.tag()) {
 97                 case MOVE -> {
 98                     Class<?> actualType = stack.pop();
 99                     Class<?> expectedType = ((Binding.Move) b).type();
100                     checkType(actualType, expectedType);
101                 }
102                 case DEREFERENCE -> {
103                     Class<?> actualType = stack.pop();
104                     checkType(actualType, MemorySegment.class);
105                     Class<?> newType = ((Binding.Dereference) b).type();
106                     stack.push(newType);
107                 }
108                 case BASE_ADDRESS -> {
109                     Class<?> actualType = stack.pop();
110                     checkType(actualType, MemorySegment.class);
111                     stack.push(MemoryAddress.class);
112                 }
113                 case CONVERT_ADDRESS -> {
114                     Class<?> actualType = stack.pop();
115                     checkType(actualType, MemoryAddress.class);
116                     stack.push(long.class);
117                 }
118                 case ALLOC_BUFFER ->
119                     throw new UnsupportedOperationException();
120                 case COPY_BUFFER -> {
121                     Class<?> actualType = stack.pop();
122                     checkType(actualType, MemorySegment.class);
123                     stack.push(MemorySegment.class);
124                 }
125                 case DUP ->
126                     stack.push(stack.peekLast());
127                 default -> throw new IllegalArgumentException("Unknown binding: " + b);
128             }
129         }
130 
131         if (!stack.isEmpty()) {
132             throw new IllegalArgumentException("Stack must be empty after recipe");
133         }
134     }
135 
136     private static void verifyBoxBindings(Class<?> outType, List<Binding> bindings) {
137         Deque<Class<?>> stack = new ArrayDeque<>();
138 
139         for (Binding b : bindings) {
140             switch (b.tag()) {
141                 case MOVE -> {
142                     Class<?> newType = ((Binding.Move) b).type();
143                     stack.push(newType);
144                 }
145                 case DEREFERENCE -> {
146                     Class<?> storeType = stack.pop();
147                     checkType(storeType, ((Binding.Dereference) b).type());
148                     Class<?> segmentType = stack.pop();
149                     checkType(segmentType, MemorySegment.class);
150                 }
151                 case CONVERT_ADDRESS -> {
152                     Class<?> actualType = stack.pop();
153                     checkType(actualType, long.class);
154                     stack.push(MemoryAddress.class);
155                 }
156                 case BASE_ADDRESS -> {
157                     Class<?> actualType = stack.pop();
158                     checkType(actualType, MemorySegment.class);
159                     stack.push(MemoryAddress.class);
160                 }
161                 case ALLOC_BUFFER -> {
162                     stack.push(MemorySegment.class);
163                 }
164                 case COPY_BUFFER -> {
165                     Class<?> actualType = stack.pop();
166                     checkType(actualType, MemoryAddress.class);
167                     stack.push(MemorySegment.class);
168                 }
169                 case DUP ->
170                     stack.push(stack.peekLast());
171                 default -> throw new IllegalArgumentException("Unknown binding: " + b);
172             }
173         }
174 
175         if (stack.size() != 1) {
176             throw new IllegalArgumentException("Stack must contain exactly 1 value");
177         }
178 
179         Class<?> actualReturnType = stack.pop();
180         checkType(actualReturnType, outType);
181     }
182 }

  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.internal.foreign.abi;
 24 
 25 import jdk.incubator.foreign.FunctionDescriptor;

 26 import jdk.incubator.foreign.MemoryLayout;

 27 import sun.security.action.GetPropertyAction;
 28 
 29 import java.lang.invoke.MethodType;
 30 import java.util.ArrayDeque;
 31 import java.util.ArrayList;
 32 import java.util.Deque;
 33 import java.util.List;
 34 
 35 public class CallingSequenceBuilder {
 36     private static final boolean VERIFY_BINDINGS = Boolean.parseBoolean(
 37             GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.VERIFY_BINDINGS", "true"));
 38 
 39     private final boolean forUpcall;
 40     private final List<List<Binding>> inputBindings = new ArrayList<>();
 41     private List<Binding> outputBindings = List.of();
 42 
 43     private MethodType mt = MethodType.methodType(void.class);
 44     private FunctionDescriptor desc = FunctionDescriptor.ofVoid();
 45 
 46     public CallingSequenceBuilder(boolean forUpcall) {

 62         this.outputBindings = bindings;
 63         mt = mt.changeReturnType(carrier);
 64         desc = desc.changeReturnLayout(layout);
 65         return this;
 66     }
 67 
 68     public CallingSequence build() {
 69         return new CallingSequence(mt, desc, inputBindings, outputBindings);
 70     }
 71 
 72     private void verifyBindings(boolean forArguments, Class<?> carrier, List<Binding> bindings) {
 73         if (VERIFY_BINDINGS) {
 74             if (forUpcall == forArguments) {
 75                 verifyBoxBindings(carrier, bindings);
 76             } else {
 77                 verifyUnboxBindings(carrier, bindings);
 78             }
 79         }
 80     }
 81 







 82     private static void verifyUnboxBindings(Class<?> inType, List<Binding> bindings) {
 83         Deque<Class<?>> stack = new ArrayDeque<>();
 84         stack.push(inType);
 85 
 86         for (Binding b : bindings) {
 87             b.verifyUnbox(stack);
































 88         }
 89 
 90         if (!stack.isEmpty()) {
 91             throw new IllegalArgumentException("Stack must be empty after recipe");
 92         }
 93     }
 94 
 95     private static void verifyBoxBindings(Class<?> expectedReturnType, List<Binding> bindings) {
 96         Deque<Class<?>> stack = new ArrayDeque<>();
 97 
 98         for (Binding b : bindings) {
 99             b.verifyBox(stack);
































100         }
101 
102         if (stack.size() != 1) {
103             throw new IllegalArgumentException("Stack must contain exactly 1 value");
104         }
105 
106         Class<?> actualReturnType = stack.pop();
107         SharedUtils.checkType(actualReturnType, expectedReturnType);
108     }
109 }
< prev index next >