< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/BindingInterpreter.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.MemoryAddress;
 26 import jdk.incubator.foreign.MemoryHandles;
 27 import jdk.incubator.foreign.MemorySegment;
 28 import jdk.internal.foreign.MemoryAddressImpl;
 29 import jdk.internal.foreign.Utils;
 30 
 31 import java.lang.invoke.VarHandle;
 32 import java.nio.ByteOrder;
 33 import java.util.ArrayDeque;
 34 import java.util.Deque;
 35 import java.util.List;
 36 import java.util.function.Function;
 37 
 38 public class BindingInterpreter {
 39     private static final VarHandle VH_BYTE = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder());
 40     private static final VarHandle VH_CHAR = MemoryHandles.varHandle(char.class, ByteOrder.nativeOrder());
 41     private static final VarHandle VH_SHORT = MemoryHandles.varHandle(short.class, ByteOrder.nativeOrder());
 42     private static final VarHandle VH_INT = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
 43     private static final VarHandle VH_LONG = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder());
 44     private static final VarHandle VH_FLOAT = MemoryHandles.varHandle(float.class, ByteOrder.nativeOrder());
 45     private static final VarHandle VH_DOUBLE = MemoryHandles.varHandle(double.class, ByteOrder.nativeOrder());
 46 
 47     static void unbox(Object arg, List<Binding> bindings, Function<VMStorage,
 48             MemoryAddress> ptrFunction, List<? super MemorySegment> buffers) {
 49         Deque<Object> stack = new ArrayDeque<>();
 50         stack.push(arg);
 51         for (Binding b : bindings) {
 52             switch (b.tag()) {
 53                 case MOVE -> {
 54                     Binding.Move binding = (Binding.Move) b;
 55                     MemoryAddress ptr = ptrFunction.apply(binding.storage());
 56                     writeOverSized(ptr, binding.type(), stack.pop());
 57                 }
 58                 case DEREFERENCE -> {
 59                     Binding.Dereference deref = (Binding.Dereference) b;
 60                     MemorySegment operand = (MemorySegment) stack.pop();
 61                     MemoryAddress baseAddress = operand.baseAddress();
 62                     MemoryAddress readAddress = baseAddress.addOffset(deref.offset());
 63                     stack.push(read(readAddress, deref.type()));
 64                 }
 65                 case COPY_BUFFER -> {
 66                     Binding.Copy binding = (Binding.Copy) b;
 67                     MemorySegment operand = (MemorySegment) stack.pop();
 68                     assert operand.byteSize() == binding.size() : "operand size mismatch";
 69                     MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment());
 70                     copy.copyFrom(operand.asSlice(0, binding.size()));
 71                     buffers.add(copy);
 72                     stack.push(copy);
 73                 }
 74                 case ALLOC_BUFFER ->
 75                     throw new UnsupportedOperationException();
 76                 case CONVERT_ADDRESS ->
 77                     stack.push(((MemoryAddress) stack.pop()).toRawLongValue());
 78                 case BASE_ADDRESS ->
 79                     stack.push(((MemorySegment) stack.pop()).baseAddress());
 80                 case DUP ->
 81                     stack.push(stack.peekLast());
 82                 default -> throw new IllegalArgumentException("Unsupported tag: " + b);
 83             }
 84         }
 85     }
 86 
 87     static Object box(List<Binding> bindings, Function<VMStorage, MemoryAddress> ptrFunction) {
 88         Deque<Object> stack = new ArrayDeque<>();
 89         for (Binding b : bindings) {
 90             switch (b.tag()) {
 91                 case MOVE -> {
 92                     Binding.Move binding = (Binding.Move) b;
 93                     MemoryAddress ptr = ptrFunction.apply(binding.storage());
 94                     stack.push(read(ptr, binding.type()));
 95                 }
 96                 case DEREFERENCE -> {
 97                     Binding.Dereference binding = (Binding.Dereference) b;
 98                     Object value = stack.pop();
 99                     MemorySegment operand = (MemorySegment) stack.pop();
100                     MemoryAddress baseAddress = operand.baseAddress();
101                     MemoryAddress writeAddress = baseAddress.addOffset(binding.offset());
102                     write(writeAddress, binding.type(), value);
103                 }
104                 case COPY_BUFFER -> {
105                     Binding.Copy binding = (Binding.Copy) b;
106                     MemoryAddress operand = (MemoryAddress) stack.pop();
107                     operand = MemoryAddressImpl.ofLongUnchecked(operand.toRawLongValue(), binding.size());
108                     MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment());
109                     copy.copyFrom(operand.segment().asSlice(0, binding.size()));
110                     stack.push(copy); // leaked
111                 }
112                 case ALLOC_BUFFER -> {
113                     Binding.Allocate binding = (Binding.Allocate) b;
114                     stack.push(MemorySegment.allocateNative(binding.size(), binding.alignment()));
115                 }
116                 case CONVERT_ADDRESS ->
117                     stack.push(MemoryAddress.ofLong((long) stack.pop()));
118                 case BASE_ADDRESS ->
119                     stack.push(((MemorySegment) stack.pop()).baseAddress());
120                 case DUP ->
121                     stack.push(stack.peekLast());
122                 default -> throw new IllegalArgumentException("Unsupported tag: " + b);
123             }
124         }
125 
126        return stack.pop();
127     }
128 
129     private static void writeOverSized(MemoryAddress ptr, Class<?> type, Object o) {
130         // use VH_LONG for integers to zero out the whole register in the process
131         if (type == long.class) {
132             VH_LONG.set(ptr, (long) o);
133         } else if (type == int.class) {
134             VH_LONG.set(ptr, (long) (int) o);
135         } else if (type == short.class) {
136             VH_LONG.set(ptr, (long) (short) o);
137         } else if (type == char.class) {
138             VH_LONG.set(ptr, (long) (char) o);
139         } else if (type == byte.class) {
140             VH_LONG.set(ptr, (long) (byte) o);
141         } else if (type == float.class) {
142             VH_FLOAT.set(ptr, (float) o);
143         } else if (type == double.class) {
144             VH_DOUBLE.set(ptr, (double) o);
145         } else {
146             throw new IllegalArgumentException("Unsupported carrier: " + type);
147         }
148     }
149 
150     private static void write(MemoryAddress ptr, Class<?> type, Object o) {
151         if (type == long.class) {
152             VH_LONG.set(ptr, (long) o);
153         } else if (type == int.class) {
154             VH_INT.set(ptr, (int) o);
155         } else if (type == short.class) {
156             VH_SHORT.set(ptr, (short) o);
157         } else if (type == char.class) {
158             VH_CHAR.set(ptr, (char) o);
159         } else if (type == byte.class) {
160             VH_BYTE.set(ptr, (byte) o);
161         } else if (type == float.class) {
162             VH_FLOAT.set(ptr, (float) o);
163         } else if (type == double.class) {
164             VH_DOUBLE.set(ptr, (double) o);
165         } else {
166             throw new IllegalArgumentException("Unsupported carrier: " + type);
167         }
168     }
169 
170     private static Object read(MemoryAddress ptr, Class<?> type) {
171         if (type == long.class) {
172             return (long) VH_LONG.get(ptr);
173         } else if (type == int.class) {
174             return (int) VH_INT.get(ptr);
175         } else if (type == short.class) {
176             return (short) VH_SHORT.get(ptr);
177         } else if (type == char.class) {
178             return (char) VH_CHAR.get(ptr);
179         } else if (type == byte.class) {
180             return (byte) VH_BYTE.get(ptr);
181         } else if (type == float.class) {
182             return (float) VH_FLOAT.get(ptr);
183         } else if (type == double.class) {
184             return (double) VH_DOUBLE.get(ptr);
185         } else {
186             throw new IllegalArgumentException("Unsupported carrier: " + type);
187         }
188     }
189 }

  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.MemoryAddress;

 26 import jdk.incubator.foreign.MemorySegment;
 27 import jdk.internal.foreign.MemoryAddressImpl;
 28 import jdk.internal.foreign.Utils;
 29 


 30 import java.util.ArrayDeque;
 31 import java.util.Deque;
 32 import java.util.List;

 33 
 34 public class BindingInterpreter {







 35 
 36     static void unbox(Object arg, List<Binding> bindings, StoreFunc storeFunc, List<? super MemorySegment> buffers) {

 37         Deque<Object> stack = new ArrayDeque<>();
 38         stack.push(arg);
 39         for (Binding b : bindings) {
 40             switch (b.tag()) {
 41                 case MOVE -> {
 42                     Binding.Move binding = (Binding.Move) b;
 43                     storeFunc.store(binding.storage(), binding.type(), stack.pop());

 44                 }
 45                 case DEREFERENCE -> {
 46                     Binding.Dereference deref = (Binding.Dereference) b;
 47                     MemorySegment operand = (MemorySegment) stack.pop();
 48                     MemoryAddress baseAddress = operand.baseAddress();
 49                     MemoryAddress readAddress = baseAddress.addOffset(deref.offset());
 50                     stack.push(SharedUtils.read(readAddress, deref.type()));
 51                 }
 52                 case COPY_BUFFER -> {
 53                     Binding.Copy binding = (Binding.Copy) b;
 54                     MemorySegment operand = (MemorySegment) stack.pop();
 55                     assert operand.byteSize() == binding.size() : "operand size mismatch";
 56                     MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment());
 57                     copy.copyFrom(operand.asSlice(0, binding.size()));
 58                     buffers.add(copy);
 59                     stack.push(copy);
 60                 }
 61                 case ALLOC_BUFFER ->
 62                     throw new UnsupportedOperationException();
 63                 case CONVERT_ADDRESS ->
 64                     stack.push(((MemoryAddress) stack.pop()).toRawLongValue());
 65                 case BASE_ADDRESS ->
 66                     stack.push(((MemorySegment) stack.pop()).baseAddress());
 67                 case DUP ->
 68                     stack.push(stack.peekLast());
 69                 default -> throw new IllegalArgumentException("Unsupported tag: " + b);
 70             }
 71         }
 72     }
 73 
 74     static Object box(List<Binding> bindings, LoadFunc loadFunc) {
 75         Deque<Object> stack = new ArrayDeque<>();
 76         for (Binding b : bindings) {
 77             switch (b.tag()) {
 78                 case MOVE -> {
 79                     Binding.Move binding = (Binding.Move) b;
 80                     stack.push(loadFunc.load(binding.storage(), binding.type()));

 81                 }
 82                 case DEREFERENCE -> {
 83                     Binding.Dereference binding = (Binding.Dereference) b;
 84                     Object value = stack.pop();
 85                     MemorySegment operand = (MemorySegment) stack.pop();
 86                     MemoryAddress baseAddress = operand.baseAddress();
 87                     MemoryAddress writeAddress = baseAddress.addOffset(binding.offset());
 88                     SharedUtils.write(writeAddress, binding.type(), value);
 89                 }
 90                 case COPY_BUFFER -> {
 91                     Binding.Copy binding = (Binding.Copy) b;
 92                     MemoryAddress operand = (MemoryAddress) stack.pop();
 93                     operand = MemoryAddressImpl.ofLongUnchecked(operand.toRawLongValue(), binding.size());
 94                     MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment());
 95                     copy.copyFrom(operand.segment().asSlice(0, binding.size()));
 96                     stack.push(copy); // leaked
 97                 }
 98                 case ALLOC_BUFFER -> {
 99                     Binding.Allocate binding = (Binding.Allocate) b;
100                     stack.push(MemorySegment.allocateNative(binding.size(), binding.alignment()));
101                 }
102                 case CONVERT_ADDRESS ->
103                     stack.push(MemoryAddress.ofLong((long) stack.pop()));
104                 case BASE_ADDRESS ->
105                     stack.push(((MemorySegment) stack.pop()).baseAddress());
106                 case DUP ->
107                     stack.push(stack.peekLast());
108                 default -> throw new IllegalArgumentException("Unsupported tag: " + b);
109             }
110         }
111 
112        return stack.pop();
113     }
114 
115     interface StoreFunc {
116         void store(VMStorage storage, Class<?> type, Object o);

















117     }
118 
119     interface LoadFunc {
120         Object load(VMStorage storage, Class<?> type);




































121     }
122 }
< prev index next >