1 /* 2 * Copyright (c) 2015, 2016, 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 -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort 27 * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsShort 28 * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsShort 29 */ 30 31 import org.testng.annotations.DataProvider; 32 import org.testng.annotations.Test; 33 34 import java.lang.invoke.MethodHandles; 35 import java.lang.invoke.VarHandle; 36 import java.nio.ByteBuffer; 37 import java.nio.ByteOrder; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.EnumSet; 41 import java.util.List; 42 43 import static org.testng.Assert.*; 44 45 public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { 46 static final int SIZE = Short.BYTES; 47 48 static final short VALUE_1 = (short)0x0102; 49 50 static final short VALUE_2 = (short)0x1112; 51 52 static final short VALUE_3 = (short)0x2122; 53 54 55 @Override 56 public void setupVarHandleSources() { 57 // Combinations of VarHandle byte[] or ByteBuffer 58 vhss = new ArrayList<>(); 59 for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { 60 VarHandleSource aeh = new VarHandleSource( 61 MethodHandles.byteArrayViewVarHandle(short[].class, 62 endianess == MemoryMode.BIG_ENDIAN), 63 endianess, MemoryMode.READ_WRITE); 64 vhss.add(aeh); 65 66 VarHandleSource bbh = new VarHandleSource( 67 MethodHandles.byteBufferViewVarHandle(short[].class, 68 endianess == MemoryMode.BIG_ENDIAN), 69 endianess, MemoryMode.READ_WRITE); 70 vhss.add(bbh); 71 } 72 } 73 74 75 @Test(dataProvider = "varHandlesProvider") 76 public void testIsAccessModeSupported(VarHandleSource vhs) { 77 VarHandle vh = vhs.s; 78 79 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); 80 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); 81 82 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); 83 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); 84 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); 85 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); 86 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); 87 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); 88 89 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); 90 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)); 91 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); 92 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); 93 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); 94 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); 95 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); 96 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); 97 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); 98 99 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); 100 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET)); 101 } 102 103 @Test(dataProvider = "typesProvider") 104 public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) { 105 assertEquals(vh.varType(), short.class); 106 107 assertEquals(vh.coordinateTypes(), pts); 108 109 testTypes(vh); 110 } 111 112 113 @DataProvider 114 public Object[][] accessTestCaseProvider() throws Exception { 115 List<AccessTestCase<?>> cases = new ArrayList<>(); 116 117 for (ByteArrayViewSource<?> bav : bavss) { 118 for (VarHandleSource vh : vhss) { 119 if (vh.matches(bav)) { 120 if (bav instanceof ByteArraySource) { 121 ByteArraySource bas = (ByteArraySource) bav; 122 123 cases.add(new VarHandleSourceAccessTestCase( 124 "read write", bav, vh, h -> testArrayReadWrite(bas, h), 125 true)); 126 cases.add(new VarHandleSourceAccessTestCase( 127 "unsupported", bav, vh, h -> testArrayUnsupported(bas, h), 128 false)); 129 cases.add(new VarHandleSourceAccessTestCase( 130 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), 131 false)); 132 cases.add(new VarHandleSourceAccessTestCase( 133 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), 134 false)); 135 } 136 else { 137 ByteBufferSource bbs = (ByteBufferSource) bav; 138 139 if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) { 140 cases.add(new VarHandleSourceAccessTestCase( 141 "read write", bav, vh, h -> testArrayReadWrite(bbs, h), 142 true)); 143 } 144 else { 145 cases.add(new VarHandleSourceAccessTestCase( 146 "read only", bav, vh, h -> testArrayReadOnly(bbs, h), 147 true)); 148 } 149 150 cases.add(new VarHandleSourceAccessTestCase( 151 "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h), 152 false)); 153 cases.add(new VarHandleSourceAccessTestCase( 154 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), 155 false)); 156 cases.add(new VarHandleSourceAccessTestCase( 157 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), 158 false)); 159 } 160 } 161 } 162 } 163 164 // Work around issue with jtreg summary reporting which truncates 165 // the String result of Object.toString to 30 characters, hence 166 // the first dummy argument 167 return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); 168 } 169 170 @Test(dataProvider = "accessTestCaseProvider") 171 public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable { 172 T t = atc.get(); 173 int iters = atc.requiresLoop() ? ITERS : 1; 174 for (int c = 0; c < iters; c++) { 175 atc.testAccess(t); 176 } 177 } 178 179 180 static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { 181 VarHandle vh = vhs.s; 182 byte[] array = bs.s; 183 int ci = 1; 184 185 checkUOE(() -> { 186 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 187 }); 188 189 checkUOE(() -> { 190 short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 191 }); 192 193 checkUOE(() -> { 194 short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 195 }); 196 197 checkUOE(() -> { 198 short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 199 }); 200 201 checkUOE(() -> { 202 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 203 }); 204 205 checkUOE(() -> { 206 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 207 }); 208 209 checkUOE(() -> { 210 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 211 }); 212 213 checkUOE(() -> { 214 short o = (short) vh.getAndSet(array, ci, VALUE_1); 215 }); 216 217 checkUOE(() -> { 218 short o = (short) vh.getAndAdd(array, ci, VALUE_1); 219 }); 220 221 checkUOE(() -> { 222 short o = (short) vh.addAndGet(array, ci, VALUE_1); 223 }); 224 } 225 226 static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { 227 VarHandle vh = vhs.s; 228 ByteBuffer array = bs.s; 229 int ci = 0; 230 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 231 232 if (readOnly) { 233 checkROBE(() -> { 234 vh.set(array, ci, VALUE_1); 235 }); 236 } 237 238 if (readOnly) { 239 checkROBE(() -> { 240 vh.setVolatile(array, ci, VALUE_1); 241 }); 242 243 checkROBE(() -> { 244 vh.setRelease(array, ci, VALUE_1); 245 }); 246 247 checkROBE(() -> { 248 vh.setOpaque(array, ci, VALUE_1); 249 }); 250 checkUOE(() -> { 251 short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 252 }); 253 254 checkUOE(() -> { 255 short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 256 }); 257 258 checkUOE(() -> { 259 short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 260 }); 261 262 checkUOE(() -> { 263 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 264 }); 265 266 checkUOE(() -> { 267 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 268 }); 269 270 checkUOE(() -> { 271 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 272 }); 273 274 checkUOE(() -> { 275 short o = (short) vh.getAndSet(array, ci, VALUE_1); 276 }); 277 278 checkUOE(() -> { 279 short o = (short) vh.getAndAdd(array, ci, VALUE_1); 280 }); 281 282 checkUOE(() -> { 283 short o = (short) vh.addAndGet(array, ci, VALUE_1); 284 }); 285 } 286 else { 287 checkUOE(() -> { 288 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 289 }); 290 291 checkUOE(() -> { 292 short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 293 }); 294 295 checkUOE(() -> { 296 short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 297 }); 298 299 checkUOE(() -> { 300 short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 301 }); 302 303 checkUOE(() -> { 304 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 305 }); 306 307 checkUOE(() -> { 308 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 309 }); 310 311 checkUOE(() -> { 312 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 313 }); 314 315 checkUOE(() -> { 316 short o = (short) vh.getAndSet(array, ci, VALUE_1); 317 }); 318 checkUOE(() -> { 319 short o = (short) vh.getAndAdd(array, ci, VALUE_1); 320 }); 321 322 checkUOE(() -> { 323 short o = (short) vh.addAndGet(array, ci, VALUE_1); 324 }); 325 } 326 } 327 328 329 static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { 330 VarHandle vh = vhs.s; 331 byte[] array = bs.s; 332 333 int length = array.length - SIZE + 1; 334 for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { 335 final int ci = i; 336 337 checkIOOBE(() -> { 338 short x = (short) vh.get(array, ci); 339 }); 340 341 checkIOOBE(() -> { 342 vh.set(array, ci, VALUE_1); 343 }); 344 345 checkIOOBE(() -> { 346 short x = (short) vh.getVolatile(array, ci); 347 }); 348 349 checkIOOBE(() -> { 350 short x = (short) vh.getAcquire(array, ci); 351 }); 352 353 checkIOOBE(() -> { 354 short x = (short) vh.getOpaque(array, ci); 355 }); 356 357 checkIOOBE(() -> { 358 vh.setVolatile(array, ci, VALUE_1); 359 }); 360 361 checkIOOBE(() -> { 362 vh.setRelease(array, ci, VALUE_1); 363 }); 364 365 checkIOOBE(() -> { 366 vh.setOpaque(array, ci, VALUE_1); 367 }); 368 369 370 } 371 } 372 373 static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { 374 VarHandle vh = vhs.s; 375 ByteBuffer array = bs.s; 376 377 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 378 379 int length = array.limit() - SIZE + 1; 380 for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { 381 final int ci = i; 382 383 checkIOOBE(() -> { 384 short x = (short) vh.get(array, ci); 385 }); 386 387 if (!readOnly) { 388 checkIOOBE(() -> { 389 vh.set(array, ci, VALUE_1); 390 }); 391 } 392 393 checkIOOBE(() -> { 394 short x = (short) vh.getVolatile(array, ci); 395 }); 396 397 checkIOOBE(() -> { 398 short x = (short) vh.getAcquire(array, ci); 399 }); 400 401 checkIOOBE(() -> { 402 short x = (short) vh.getOpaque(array, ci); 403 }); 404 405 if (!readOnly) { 406 checkIOOBE(() -> { 407 vh.setVolatile(array, ci, VALUE_1); 408 }); 409 410 checkIOOBE(() -> { 411 vh.setRelease(array, ci, VALUE_1); 412 }); 413 414 checkIOOBE(() -> { 415 vh.setOpaque(array, ci, VALUE_1); 416 }); 417 418 419 } 420 } 421 } 422 423 static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { 424 VarHandle vh = vhs.s; 425 byte[] array = bs.s; 426 427 int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); 428 429 int length = array.length - SIZE + 1; 430 for (int i = 0; i < length; i++) { 431 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 432 final int ci = i; 433 434 if (!iAligned) { 435 checkISE(() -> { 436 short x = (short) vh.getVolatile(array, ci); 437 }); 438 439 checkISE(() -> { 440 short x = (short) vh.getAcquire(array, ci); 441 }); 442 443 checkISE(() -> { 444 short x = (short) vh.getOpaque(array, ci); 445 }); 446 447 checkISE(() -> { 448 vh.setVolatile(array, ci, VALUE_1); 449 }); 450 451 checkISE(() -> { 452 vh.setRelease(array, ci, VALUE_1); 453 }); 454 455 checkISE(() -> { 456 vh.setOpaque(array, ci, VALUE_1); 457 }); 458 459 460 } 461 } 462 } 463 464 static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { 465 VarHandle vh = vhs.s; 466 ByteBuffer array = bs.s; 467 468 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 469 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 470 471 int length = array.limit() - SIZE + 1; 472 for (int i = 0; i < length; i++) { 473 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 474 final int ci = i; 475 476 if (!iAligned) { 477 checkISE(() -> { 478 short x = (short) vh.getVolatile(array, ci); 479 }); 480 481 checkISE(() -> { 482 short x = (short) vh.getAcquire(array, ci); 483 }); 484 485 checkISE(() -> { 486 short x = (short) vh.getOpaque(array, ci); 487 }); 488 489 if (!readOnly) { 490 checkISE(() -> { 491 vh.setVolatile(array, ci, VALUE_1); 492 }); 493 494 checkISE(() -> { 495 vh.setRelease(array, ci, VALUE_1); 496 }); 497 498 checkISE(() -> { 499 vh.setOpaque(array, ci, VALUE_1); 500 }); 501 502 503 } 504 } 505 } 506 } 507 508 static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { 509 VarHandle vh = vhs.s; 510 byte[] array = bs.s; 511 512 int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); 513 514 bs.fill((byte) 0xff); 515 int length = array.length - SIZE + 1; 516 for (int i = 0; i < length; i++) { 517 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 518 519 // Plain 520 { 521 vh.set(array, i, VALUE_1); 522 short x = (short) vh.get(array, i); 523 assertEquals(x, VALUE_1, "get short value"); 524 } 525 526 527 if (iAligned) { 528 // Volatile 529 { 530 vh.setVolatile(array, i, VALUE_2); 531 short x = (short) vh.getVolatile(array, i); 532 assertEquals(x, VALUE_2, "setVolatile short value"); 533 } 534 535 // Lazy 536 { 537 vh.setRelease(array, i, VALUE_1); 538 short x = (short) vh.getAcquire(array, i); 539 assertEquals(x, VALUE_1, "setRelease short value"); 540 } 541 542 // Opaque 543 { 544 vh.setOpaque(array, i, VALUE_2); 545 short x = (short) vh.getOpaque(array, i); 546 assertEquals(x, VALUE_2, "setOpaque short value"); 547 } 548 549 } 550 } 551 } 552 553 554 static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { 555 VarHandle vh = vhs.s; 556 ByteBuffer array = bs.s; 557 558 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 559 560 bs.fill((byte) 0xff); 561 int length = array.limit() - SIZE + 1; 562 for (int i = 0; i < length; i++) { 563 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 564 565 // Plain 566 { 567 vh.set(array, i, VALUE_1); 568 short x = (short) vh.get(array, i); 569 assertEquals(x, VALUE_1, "get short value"); 570 } 571 572 if (iAligned) { 573 // Volatile 574 { 575 vh.setVolatile(array, i, VALUE_2); 576 short x = (short) vh.getVolatile(array, i); 577 assertEquals(x, VALUE_2, "setVolatile short value"); 578 } 579 580 // Lazy 581 { 582 vh.setRelease(array, i, VALUE_1); 583 short x = (short) vh.getAcquire(array, i); 584 assertEquals(x, VALUE_1, "setRelease short value"); 585 } 586 587 // Opaque 588 { 589 vh.setOpaque(array, i, VALUE_2); 590 short x = (short) vh.getOpaque(array, i); 591 assertEquals(x, VALUE_2, "setOpaque short value"); 592 } 593 594 } 595 } 596 } 597 598 static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { 599 VarHandle vh = vhs.s; 600 ByteBuffer array = bs.s; 601 602 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 603 604 ByteBuffer bb = ByteBuffer.allocate(SIZE); 605 bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 606 bs.fill(bb.putShort(0, VALUE_2).array()); 607 608 int length = array.limit() - SIZE + 1; 609 for (int i = 0; i < length; i++) { 610 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 611 612 short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) 613 ? rotateLeft(VALUE_2, (i % SIZE) << 3) 614 : rotateRight(VALUE_2, (i % SIZE) << 3); 615 // Plain 616 { 617 short x = (short) vh.get(array, i); 618 assertEquals(x, v, "get short value"); 619 } 620 621 if (iAligned) { 622 // Volatile 623 { 624 short x = (short) vh.getVolatile(array, i); 625 assertEquals(x, v, "getVolatile short value"); 626 } 627 628 // Lazy 629 { 630 short x = (short) vh.getAcquire(array, i); 631 assertEquals(x, v, "getRelease short value"); 632 } 633 634 // Opaque 635 { 636 short x = (short) vh.getOpaque(array, i); 637 assertEquals(x, v, "getOpaque short value"); 638 } 639 } 640 } 641 } 642 643 } 644