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 }