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