1 /*
  2  * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  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 
 24 /*
 25  * @test
 26  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess
 27  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess
 28  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess
 29  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess
 30  */
 31 
 32 import java.lang.foreign.*;
 33 import java.lang.foreign.MemoryLayout.PathElement;
 34 
 35 import java.lang.invoke.VarHandle;
 36 import java.nio.ByteOrder;
 37 import java.util.function.Function;
 38 
 39 import org.testng.annotations.*;
 40 import static org.testng.Assert.*;
 41 
 42 public class TestMemoryAccess {
 43 
 44     @Test(dataProvider = "elements")
 45     public void testAccess(Function<MemorySegment, MemorySegment> viewFactory, ValueLayout elemLayout, Checker checker) {
 46         ValueLayout layout = elemLayout.withName("elem");
 47         testAccessInternal(viewFactory, layout, layout.varHandle(), checker);
 48     }
 49 
 50     @Test(dataProvider = "elements")
 51     public void testPaddedAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Checker checker) {
 52         GroupLayout layout = MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem"));
 53         testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.groupElement("elem")), checker);
 54     }
 55 
 56     @Test(dataProvider = "elements")
 57     public void testPaddedAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Checker checker) {
 58         SequenceLayout layout = MemoryLayout.sequenceLayout(2, elemLayout);
 59         testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.sequenceElement(1)), checker);
 60     }
 61 
 62     @Test(dataProvider = "arrayElements")
 63     public void testArrayAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) {
 64         SequenceLayout seq = MemoryLayout.sequenceLayout(10, elemLayout.withName("elem"));
 65         testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement()), checker);
 66     }
 67 
 68     @Test(dataProvider = "arrayElements")
 69     public void testPaddedArrayAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) {
 70         SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem")));
 71         testArrayAccessInternal(viewFactory, seq, seq.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("elem")), checker);
 72     }
 73 
 74     @Test(dataProvider = "arrayElements")
 75     public void testPaddedArrayAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) {
 76         SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout));
 77         testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(1)), checker);
 78     }
 79 
 80     private void testAccessInternal(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout layout, VarHandle handle, Checker checker) {
 81         MemorySegment outer_segment;
 82         try (Arena arena = Arena.ofConfined()) {
 83             MemorySegment segment = viewFactory.apply(arena.allocate(layout));
 84             boolean isRO = segment.isReadOnly();
 85             try {
 86                 checker.check(handle, segment);
 87                 if (isRO) {
 88                     throw new AssertionError(); //not ok, memory should be immutable
 89                 }
 90             } catch (UnsupportedOperationException ex) {
 91                 if (!isRO) {
 92                     throw new AssertionError(); //we should not have failed!
 93                 }
 94                 return;
 95             }
 96             try {
 97                 checker.check(handle, segment.asSlice(layout.byteSize()));
 98                 throw new AssertionError(); //not ok, out of bounds
 99             } catch (IndexOutOfBoundsException ex) {
100                 //ok, should fail (out of bounds)
101             }
102             outer_segment = segment; //leak!
103         }
104         try {
105             checker.check(handle, outer_segment);
106             throw new AssertionError(); //not ok, session is closed
107         } catch (IllegalStateException ex) {
108             //ok, should fail (session is closed)
109         }
110     }
111 
112     private void testArrayAccessInternal(Function<MemorySegment, MemorySegment> viewFactory, SequenceLayout seq, VarHandle handle, ArrayChecker checker) {
113         MemorySegment outer_segment;
114         try (Arena arena = Arena.ofConfined()) {
115             MemorySegment segment = viewFactory.apply(arena.allocate(seq));
116             boolean isRO = segment.isReadOnly();
117             try {
118                 for (int i = 0; i < seq.elementCount(); i++) {
119                     checker.check(handle, segment, i);
120                 }
121                 if (isRO) {
122                     throw new AssertionError(); //not ok, memory should be immutable
123                 }
124             } catch (UnsupportedOperationException ex) {
125                 if (!isRO) {
126                     throw new AssertionError(); //we should not have failed!
127                 }
128                 return;
129             }
130             try {
131                 checker.check(handle, segment, seq.elementCount());
132                 throw new AssertionError(); //not ok, out of bounds
133             } catch (IndexOutOfBoundsException ex) {
134                 //ok, should fail (out of bounds)
135             }
136             outer_segment = segment; //leak!
137         }
138         try {
139             checker.check(handle, outer_segment, 0);
140             throw new AssertionError(); //not ok, session is closed
141         } catch (IllegalStateException ex) {
142             //ok, should fail (session is closed)
143         }
144     }
145 
146     @Test(dataProvider = "matrixElements")
147     public void testMatrixAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) {
148         SequenceLayout seq = MemoryLayout.sequenceLayout(20,
149                 MemoryLayout.sequenceLayout(10, elemLayout.withName("elem")));
150         testMatrixAccessInternal(viewFactory, seq, seq.varHandle(
151                 PathElement.sequenceElement(), PathElement.sequenceElement()), checker);
152     }
153 
154     @Test(dataProvider = "matrixElements")
155     public void testPaddedMatrixAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) {
156         SequenceLayout seq = MemoryLayout.sequenceLayout(20,
157                 MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem"))));
158         testMatrixAccessInternal(viewFactory, seq,
159                 seq.varHandle(
160                         PathElement.sequenceElement(), PathElement.sequenceElement(), PathElement.groupElement("elem")),
161                 checker);
162     }
163 
164     @Test(dataProvider = "matrixElements")
165     public void testPaddedMatrixAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) {
166         SequenceLayout seq = MemoryLayout.sequenceLayout(20,
167                 MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout)));
168         testMatrixAccessInternal(viewFactory, seq,
169                 seq.varHandle(
170                         PathElement.sequenceElement(), PathElement.sequenceElement(), PathElement.sequenceElement(1)),
171                 checker);
172     }
173 
174     private void testMatrixAccessInternal(Function<MemorySegment, MemorySegment> viewFactory, SequenceLayout seq, VarHandle handle, MatrixChecker checker) {
175         MemorySegment outer_segment;
176         try (Arena arena = Arena.ofConfined()) {
177             MemorySegment segment = viewFactory.apply(arena.allocate(seq));
178             boolean isRO = segment.isReadOnly();
179             try {
180                 for (int i = 0; i < seq.elementCount(); i++) {
181                     for (int j = 0; j < ((SequenceLayout) seq.elementLayout()).elementCount(); j++) {
182                         checker.check(handle, segment, i, j);
183                     }
184                 }
185                 if (isRO) {
186                     throw new AssertionError(); //not ok, memory should be immutable
187                 }
188             } catch (UnsupportedOperationException ex) {
189                 if (!isRO) {
190                     throw new AssertionError(); //we should not have failed!
191                 }
192                 return;
193             }
194             try {
195                 checker.check(handle, segment, seq.elementCount(),
196                         ((SequenceLayout)seq.elementLayout()).elementCount());
197                 throw new AssertionError(); //not ok, out of bounds
198             } catch (IndexOutOfBoundsException ex) {
199                 //ok, should fail (out of bounds)
200             }
201             outer_segment = segment; //leak!
202         }
203         try {
204             checker.check(handle, outer_segment, 0, 0);
205             throw new AssertionError(); //not ok, session is closed
206         } catch (IllegalStateException ex) {
207             //ok, should fail (session is closed)
208         }
209     }
210 
211     static Function<MemorySegment, MemorySegment> ID = Function.identity();
212     static Function<MemorySegment, MemorySegment> IMMUTABLE = MemorySegment::asReadOnly;
213 
214     @DataProvider(name = "elements")
215     public Object[][] createData() {
216         return new Object[][] {
217                 //BE, RW
218                 { ID, ValueLayout.JAVA_BYTE, Checker.BYTE },
219                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), Checker.SHORT },
220                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), Checker.CHAR },
221                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), Checker.INT },
222                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), Checker.LONG },
223                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), Checker.FLOAT },
224                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), Checker.DOUBLE },
225                 //BE, RO
226                 { IMMUTABLE, ValueLayout.JAVA_BYTE, Checker.BYTE },
227                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), Checker.SHORT },
228                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), Checker.CHAR },
229                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), Checker.INT },
230                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), Checker.LONG },
231                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), Checker.FLOAT },
232                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), Checker.DOUBLE },
233                 //LE, RW
234                 { ID, ValueLayout.JAVA_BYTE, Checker.BYTE },
235                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.SHORT },
236                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.CHAR },
237                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.INT },
238                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.LONG },
239                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.FLOAT },
240                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.DOUBLE },
241                 //LE, RO
242                 { IMMUTABLE, ValueLayout.JAVA_BYTE, Checker.BYTE },
243                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.SHORT },
244                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.CHAR },
245                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.INT },
246                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.LONG },
247                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.FLOAT },
248                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.DOUBLE },
249         };
250     }
251 
252     interface Checker {
253         void check(VarHandle handle, MemorySegment segment);
254 
255         Checker BYTE = (handle, segment) -> {
256             handle.set(segment, 0L, (byte)42);
257             assertEquals(42, (byte)handle.get(segment, 0L));
258         };
259 
260         Checker SHORT = (handle, segment) -> {
261             handle.set(segment, 0L, (short)42);
262             assertEquals(42, (short)handle.get(segment, 0L));
263         };
264 
265         Checker CHAR = (handle, segment) -> {
266             handle.set(segment, 0L, (char)42);
267             assertEquals(42, (char)handle.get(segment, 0L));
268         };
269 
270         Checker INT = (handle, segment) -> {
271             handle.set(segment, 0L, 42);
272             assertEquals(42, (int)handle.get(segment, 0L));
273         };
274 
275         Checker LONG = (handle, segment) -> {
276             handle.set(segment, 0L, (long)42);
277             assertEquals(42, (long)handle.get(segment, 0L));
278         };
279 
280         Checker FLOAT = (handle, segment) -> {
281             handle.set(segment, 0L, (float)42);
282             assertEquals((float)42, (float)handle.get(segment, 0L));
283         };
284 
285         Checker DOUBLE = (handle, segment) -> {
286             handle.set(segment, 0L, (double)42);
287             assertEquals((double)42, (double)handle.get(segment, 0L));
288         };
289     }
290 
291     @DataProvider(name = "arrayElements")
292     public Object[][] createArrayData() {
293         return new Object[][] {
294                 //BE, RW
295                 { ID, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE },
296                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.SHORT },
297                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.CHAR },
298                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.INT },
299                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.LONG },
300                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.FLOAT },
301                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.DOUBLE },
302                 //BE, RO
303                 { IMMUTABLE, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE },
304                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.SHORT },
305                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.CHAR },
306                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.INT },
307                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.LONG },
308                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.FLOAT },
309                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.DOUBLE },
310                 //LE, RW
311                 { ID, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE },
312                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.SHORT },
313                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.CHAR },
314                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.INT },
315                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.LONG },
316                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.FLOAT },
317                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.DOUBLE },
318                 //LE, RO
319                 { IMMUTABLE, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE },
320                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.SHORT },
321                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.CHAR },
322                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.INT },
323                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.LONG },
324                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.FLOAT },
325                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.DOUBLE },
326         };
327     }
328 
329     interface ArrayChecker {
330         void check(VarHandle handle, MemorySegment segment, long index);
331 
332         ArrayChecker BYTE = (handle, segment, i) -> {
333             handle.set(segment, 0L, i, (byte)i);
334             assertEquals(i, (byte)handle.get(segment, 0L, i));
335         };
336 
337         ArrayChecker SHORT = (handle, segment, i) -> {
338             handle.set(segment, 0L, i, (short)i);
339             assertEquals(i, (short)handle.get(segment, 0L, i));
340         };
341 
342         ArrayChecker CHAR = (handle, segment, i) -> {
343             handle.set(segment, 0L, i, (char)i);
344             assertEquals(i, (char)handle.get(segment, 0L, i));
345         };
346 
347         ArrayChecker INT = (handle, segment, i) -> {
348             handle.set(segment, 0L, i, (int)i);
349             assertEquals(i, (int)handle.get(segment, 0L, i));
350         };
351 
352         ArrayChecker LONG = (handle, segment, i) -> {
353             handle.set(segment, 0L, i, (long)i);
354             assertEquals(i, (long)handle.get(segment, 0L, i));
355         };
356 
357         ArrayChecker FLOAT = (handle, segment, i) -> {
358             handle.set(segment, 0L, i, (float)i);
359             assertEquals((float)i, (float)handle.get(segment, 0L, i));
360         };
361 
362         ArrayChecker DOUBLE = (handle, segment, i) -> {
363             handle.set(segment, 0L, i, (double)i);
364             assertEquals((double)i, (double)handle.get(segment, 0L, i));
365         };
366     }
367 
368     @DataProvider(name = "matrixElements")
369     public Object[][] createMatrixData() {
370         return new Object[][] {
371                 //BE, RW
372                 { ID, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE },
373                 { ID, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN },
374                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.SHORT },
375                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.CHAR },
376                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.INT },
377                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.LONG },
378                 { ID, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.ADDR },
379                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.FLOAT },
380                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.DOUBLE },
381                 //BE, RO
382                 { IMMUTABLE, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE },
383                 { IMMUTABLE, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN },
384                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.SHORT },
385                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.CHAR },
386                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.INT },
387                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.LONG },
388                 { IMMUTABLE, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.ADDR },
389                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.FLOAT },
390                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.DOUBLE },
391                 //LE, RW
392                 { ID, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE },
393                 { ID, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN },
394                 { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.SHORT },
395                 { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.CHAR },
396                 { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.INT },
397                 { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.LONG },
398                 { ID, ValueLayout.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.ADDR },
399                 { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.FLOAT },
400                 { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.DOUBLE },
401                 //LE, RO
402                 { IMMUTABLE, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE },
403                 { IMMUTABLE, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN },
404                 { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.SHORT },
405                 { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.CHAR },
406                 { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.INT },
407                 { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.LONG },
408                 { IMMUTABLE, ValueLayout.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.ADDR },
409                 { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.FLOAT },
410                 { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.DOUBLE },
411         };
412     }
413 
414     interface MatrixChecker {
415         void check(VarHandle handle, MemorySegment segment, long row, long col);
416 
417         MatrixChecker BYTE = (handle, segment, r, c) -> {
418             handle.set(segment, 0L, r, c, (byte)(r + c));
419             assertEquals(r + c, (byte)handle.get(segment, 0L, r, c));
420         };
421 
422         MatrixChecker BOOLEAN = (handle, segment, r, c) -> {
423             handle.set(segment, 0L, r, c, (r + c) != 0);
424             assertEquals((r + c) != 0, (boolean)handle.get(segment, 0L, r, c));
425         };
426 
427         MatrixChecker SHORT = (handle, segment, r, c) -> {
428             handle.set(segment, 0L, r, c, (short)(r + c));
429             assertEquals(r + c, (short)handle.get(segment, 0L, r, c));
430         };
431 
432         MatrixChecker CHAR = (handle, segment, r, c) -> {
433             handle.set(segment, 0L, r, c, (char)(r + c));
434             assertEquals(r + c, (char)handle.get(segment, 0L, r, c));
435         };
436 
437         MatrixChecker INT = (handle, segment, r, c) -> {
438             handle.set(segment, 0L, r, c, (int)(r + c));
439             assertEquals(r + c, (int)handle.get(segment, 0L, r, c));
440         };
441 
442         MatrixChecker LONG = (handle, segment, r, c) -> {
443             handle.set(segment, 0L, r, c, r + c);
444             assertEquals(r + c, (long)handle.get(segment, 0L, r, c));
445         };
446 
447         MatrixChecker ADDR = (handle, segment, r, c) -> {
448             handle.set(segment, 0L, r, c, MemorySegment.ofAddress(r + c));
449             assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, 0L, r, c));
450         };
451 
452         MatrixChecker FLOAT = (handle, segment, r, c) -> {
453             handle.set(segment, 0L, r, c, (float)(r + c));
454             assertEquals((float)(r + c), (float)handle.get(segment, 0L, r, c));
455         };
456 
457         MatrixChecker DOUBLE = (handle, segment, r, c) -> {
458             handle.set(segment, 0L, r, c, (double)(r + c));
459             assertEquals((double)(r + c), (double)handle.get(segment, 0L, r, c));
460         };
461     }
462 }