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 }
|