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