69 MH_SAVER = MethodHandles.lookup().findStatic(NativeTestHelper.class, "saver",
70 MethodType.methodType(Object.class, Object[].class, List.class, AtomicReference.class, SegmentAllocator.class, int.class));
71 } catch (ReflectiveOperationException e) {
72 throw new ExceptionInInitializerError(e);
73 }
74 }
75
76 public static boolean isIntegral(MemoryLayout layout) {
77 return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier());
78 }
79
80 static boolean isIntegral(Class<?> clazz) {
81 return clazz == byte.class || clazz == char.class || clazz == short.class
82 || clazz == int.class || clazz == long.class;
83 }
84
85 public static boolean isPointer(MemoryLayout layout) {
86 return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class;
87 }
88
89 // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms.
90
91 /**
92 * The layout for the {@code bool} C type
93 */
94 public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN;
95 /**
96 * The layout for the {@code char} C type
97 */
98 public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE;
99 /**
100 * The layout for the {@code short} C type
101 */
102 public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT;
103 /**
104 * The layout for the {@code int} C type
105 */
106 public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT;
107
108 /**
109 * The layout for the {@code long long} C type.
110 */
111 public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG;
112 /**
113 * The layout for the {@code float} C type
114 */
115 public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT;
116 /**
117 * The layout for the {@code double} C type
118 */
119 public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE;
120 /**
121 * The {@code T*} native type.
122 */
123 public static final AddressLayout C_POINTER = ValueLayout.ADDRESS
124 .withTargetLayout(MemoryLayout.sequenceLayout(C_CHAR));
125
126 public static final Linker LINKER = Linker.nativeLinker();
127
128 private static final MethodHandle FREE = LINKER.downcallHandle(
129 LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER));
130
131 private static final MethodHandle MALLOC = LINKER.downcallHandle(
132 LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(C_POINTER, C_LONG_LONG));
133
134 public static void freeMemory(MemorySegment address) {
135 try {
136 FREE.invokeExact(address);
137 } catch (Throwable ex) {
138 throw new IllegalStateException(ex);
139 }
140 }
141
142 public static MemorySegment allocateMemory(long size) {
143 try {
144 return (MemorySegment) MALLOC.invokeExact(size);
145 } catch (Throwable ex) {
146 throw new IllegalStateException(ex);
231 double value = random.nextDouble();
232 return new TestValue(value, actual -> assertEquals(actual, value));
233 }
234
235 throw new IllegalStateException("Unexpected layout: " + layout);
236 }
237
238 private static Consumer<Object> initField(RandomGenerator random, MemorySegment container, MemoryLayout containerLayout,
239 MemoryLayout fieldLayout, MemoryLayout.PathElement fieldPath,
240 SegmentAllocator allocator) {
241 TestValue fieldValue = genTestValue(random, fieldLayout, allocator);
242 Consumer<Object> fieldCheck = fieldValue.check();
243 if (fieldLayout instanceof GroupLayout || fieldLayout instanceof SequenceLayout) {
244 UnaryOperator<MemorySegment> slicer = slicer(containerLayout, fieldPath);
245 MemorySegment slice = slicer.apply(container);
246 slice.copyFrom((MemorySegment) fieldValue.value());
247 return actual -> fieldCheck.accept(slicer.apply((MemorySegment) actual));
248 } else {
249 VarHandle accessor = containerLayout.varHandle(fieldPath);
250 //set value
251 accessor.set(container, fieldValue.value());
252 return actual -> fieldCheck.accept(accessor.get((MemorySegment) actual));
253 }
254 }
255
256 private static UnaryOperator<MemorySegment> slicer(MemoryLayout containerLayout, MemoryLayout.PathElement fieldPath) {
257 MethodHandle slicer = containerLayout.sliceHandle(fieldPath);
258 return container -> {
259 try {
260 return (MemorySegment) slicer.invokeExact(container);
261 } catch (Throwable e) {
262 throw new IllegalStateException(e);
263 }
264 };
265 }
266
267 private static void assertEquals(Object actual, Object expected) {
268 if (actual.getClass() != expected.getClass()) {
269 throw new AssertionError("Type mismatch: " + actual.getClass() + " != " + expected.getClass());
270 }
271 if (!actual.equals(expected)) {
272 throw new AssertionError("Not equal: " + actual + " != " + expected);
273 }
274 }
275
276 /**
277 * Make an upcall stub that saves its arguments into the given 'ref' array
278 *
279 * @param fd function descriptor for the upcall stub
280 * @param capturedArgs box to save arguments in
|
69 MH_SAVER = MethodHandles.lookup().findStatic(NativeTestHelper.class, "saver",
70 MethodType.methodType(Object.class, Object[].class, List.class, AtomicReference.class, SegmentAllocator.class, int.class));
71 } catch (ReflectiveOperationException e) {
72 throw new ExceptionInInitializerError(e);
73 }
74 }
75
76 public static boolean isIntegral(MemoryLayout layout) {
77 return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier());
78 }
79
80 static boolean isIntegral(Class<?> clazz) {
81 return clazz == byte.class || clazz == char.class || clazz == short.class
82 || clazz == int.class || clazz == long.class;
83 }
84
85 public static boolean isPointer(MemoryLayout layout) {
86 return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class;
87 }
88
89 public static final Linker LINKER = Linker.nativeLinker();
90
91 // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms.
92
93 /**
94 * The layout for the {@code bool} C type
95 */
96 public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) LINKER.canonicalLayouts().get("bool");
97 /**
98 * The layout for the {@code char} C type
99 */
100 public static final ValueLayout.OfByte C_CHAR = (ValueLayout.OfByte) LINKER.canonicalLayouts().get("char");
101 /**
102 * The layout for the {@code short} C type
103 */
104 public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) LINKER.canonicalLayouts().get("short");
105 /**
106 * The layout for the {@code int} C type
107 */
108 public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) LINKER.canonicalLayouts().get("int");
109
110 /**
111 * The layout for the {@code long long} C type.
112 */
113 public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) LINKER.canonicalLayouts().get("long long");
114 /**
115 * The layout for the {@code float} C type
116 */
117 public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) LINKER.canonicalLayouts().get("float");
118 /**
119 * The layout for the {@code double} C type
120 */
121 public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) LINKER.canonicalLayouts().get("double");
122 /**
123 * The {@code T*} native type.
124 */
125 public static final AddressLayout C_POINTER = ((AddressLayout) LINKER.canonicalLayouts().get("void*"))
126 .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, C_CHAR));
127 /**
128 * The layout for the {@code size_t} C type
129 */
130 public static final ValueLayout C_SIZE_T = (ValueLayout) LINKER.canonicalLayouts().get("size_t");
131
132 // Common layout shared by some tests
133 // struct S_PDI { void* p0; double p1; int p2; };
134 public static final MemoryLayout S_PDI_LAYOUT = switch ((int) ValueLayout.ADDRESS.byteSize()) {
135 case 8 -> MemoryLayout.structLayout(
136 C_POINTER.withName("p0"),
137 C_DOUBLE.withName("p1"),
138 C_INT.withName("p2"),
139 MemoryLayout.paddingLayout(4));
140 case 4 -> MemoryLayout.structLayout(
141 C_POINTER.withName("p0"),
142 C_DOUBLE.withName("p1"),
143 C_INT.withName("p2"));
144 default -> throw new UnsupportedOperationException("Unsupported address size");
145 };
146
147 private static final MethodHandle FREE = LINKER.downcallHandle(
148 LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER));
149
150 private static final MethodHandle MALLOC = LINKER.downcallHandle(
151 LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(C_POINTER, C_LONG_LONG));
152
153 public static void freeMemory(MemorySegment address) {
154 try {
155 FREE.invokeExact(address);
156 } catch (Throwable ex) {
157 throw new IllegalStateException(ex);
158 }
159 }
160
161 public static MemorySegment allocateMemory(long size) {
162 try {
163 return (MemorySegment) MALLOC.invokeExact(size);
164 } catch (Throwable ex) {
165 throw new IllegalStateException(ex);
250 double value = random.nextDouble();
251 return new TestValue(value, actual -> assertEquals(actual, value));
252 }
253
254 throw new IllegalStateException("Unexpected layout: " + layout);
255 }
256
257 private static Consumer<Object> initField(RandomGenerator random, MemorySegment container, MemoryLayout containerLayout,
258 MemoryLayout fieldLayout, MemoryLayout.PathElement fieldPath,
259 SegmentAllocator allocator) {
260 TestValue fieldValue = genTestValue(random, fieldLayout, allocator);
261 Consumer<Object> fieldCheck = fieldValue.check();
262 if (fieldLayout instanceof GroupLayout || fieldLayout instanceof SequenceLayout) {
263 UnaryOperator<MemorySegment> slicer = slicer(containerLayout, fieldPath);
264 MemorySegment slice = slicer.apply(container);
265 slice.copyFrom((MemorySegment) fieldValue.value());
266 return actual -> fieldCheck.accept(slicer.apply((MemorySegment) actual));
267 } else {
268 VarHandle accessor = containerLayout.varHandle(fieldPath);
269 //set value
270 accessor.set(container, 0L, fieldValue.value());
271 return actual -> fieldCheck.accept(accessor.get((MemorySegment) actual, 0L));
272 }
273 }
274
275 private static UnaryOperator<MemorySegment> slicer(MemoryLayout containerLayout, MemoryLayout.PathElement fieldPath) {
276 MethodHandle slicer = containerLayout.sliceHandle(fieldPath);
277 return container -> {
278 try {
279 return (MemorySegment) slicer.invokeExact(container, 0L);
280 } catch (Throwable e) {
281 throw new IllegalStateException(e);
282 }
283 };
284 }
285
286 private static void assertEquals(Object actual, Object expected) {
287 if (actual.getClass() != expected.getClass()) {
288 throw new AssertionError("Type mismatch: " + actual.getClass() + " != " + expected.getClass());
289 }
290 if (!actual.equals(expected)) {
291 throw new AssertionError("Not equal: " + actual + " != " + expected);
292 }
293 }
294
295 /**
296 * Make an upcall stub that saves its arguments into the given 'ref' array
297 *
298 * @param fd function descriptor for the upcall stub
299 * @param capturedArgs box to save arguments in
|