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 VarHandleTestByteArrayAs$Type$ 27 * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAs$Type$ 28 * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAs$Type$ 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 VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { 46 static final int SIZE = $BoxType$.BYTES; 47 48 static final $type$ VALUE_1 = $value1$; 49 50 static final $type$ VALUE_2 = $value2$; 51 52 static final $type$ VALUE_3 = $value3$; 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($type$[].class, 62 endianess == MemoryMode.BIG_ENDIAN), 63 endianess, MemoryMode.READ_WRITE); 64 vhss.add(aeh); 65 66 VarHandleSource bbh = new VarHandleSource( 67 MethodHandles.byteBufferViewVarHandle($type$[].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 #if[CAS] 90 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); 91 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)); 92 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); 93 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); 94 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); 95 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); 96 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); 97 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); 98 #else[CAS] 99 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); 100 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)); 101 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); 102 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); 103 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); 104 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); 105 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); 106 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); 107 #end[CAS] 108 109 #if[AtomicAdd] 110 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); 111 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET)); 112 #else[AtomicAdd] 113 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); 114 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET)); 115 #end[AtomicAdd] 116 } 117 118 @Test(dataProvider = "typesProvider") 119 public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) { 120 assertEquals(vh.varType(), $type$.class); 121 122 assertEquals(vh.coordinateTypes(), pts); 123 124 testTypes(vh); 125 } 126 127 128 @DataProvider 129 public Object[][] accessTestCaseProvider() throws Exception { 130 List<AccessTestCase<?>> cases = new ArrayList<>(); 131 132 for (ByteArrayViewSource<?> bav : bavss) { 133 for (VarHandleSource vh : vhss) { 134 if (vh.matches(bav)) { 135 if (bav instanceof ByteArraySource) { 136 ByteArraySource bas = (ByteArraySource) bav; 137 138 cases.add(new VarHandleSourceAccessTestCase( 139 "read write", bav, vh, h -> testArrayReadWrite(bas, h), 140 true)); 141 cases.add(new VarHandleSourceAccessTestCase( 142 "unsupported", bav, vh, h -> testArrayUnsupported(bas, h), 143 false)); 144 cases.add(new VarHandleSourceAccessTestCase( 145 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h), 146 false)); 147 cases.add(new VarHandleSourceAccessTestCase( 148 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h), 149 false)); 150 } 151 else { 152 ByteBufferSource bbs = (ByteBufferSource) bav; 153 154 if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) { 155 cases.add(new VarHandleSourceAccessTestCase( 156 "read write", bav, vh, h -> testArrayReadWrite(bbs, h), 157 true)); 158 } 159 else { 160 cases.add(new VarHandleSourceAccessTestCase( 161 "read only", bav, vh, h -> testArrayReadOnly(bbs, h), 162 true)); 163 } 164 165 cases.add(new VarHandleSourceAccessTestCase( 166 "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h), 167 false)); 168 cases.add(new VarHandleSourceAccessTestCase( 169 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h), 170 false)); 171 cases.add(new VarHandleSourceAccessTestCase( 172 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h), 173 false)); 174 } 175 } 176 } 177 } 178 179 // Work around issue with jtreg summary reporting which truncates 180 // the String result of Object.toString to 30 characters, hence 181 // the first dummy argument 182 return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); 183 } 184 185 @Test(dataProvider = "accessTestCaseProvider") 186 public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable { 187 T t = atc.get(); 188 int iters = atc.requiresLoop() ? ITERS : 1; 189 for (int c = 0; c < iters; c++) { 190 atc.testAccess(t); 191 } 192 } 193 194 195 static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) { 196 VarHandle vh = vhs.s; 197 byte[] array = bs.s; 198 int ci = 1; 199 200 #if[!CAS] 201 checkUOE(() -> { 202 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 203 }); 204 205 checkUOE(() -> { 206 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 207 }); 208 209 checkUOE(() -> { 210 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 211 }); 212 213 checkUOE(() -> { 214 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 215 }); 216 217 checkUOE(() -> { 218 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 219 }); 220 221 checkUOE(() -> { 222 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 223 }); 224 225 checkUOE(() -> { 226 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 227 }); 228 229 checkUOE(() -> { 230 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 231 }); 232 #end[CAS] 233 234 #if[!AtomicAdd] 235 checkUOE(() -> { 236 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 237 }); 238 239 checkUOE(() -> { 240 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 241 }); 242 #end[AtomicAdd] 243 } 244 245 static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) { 246 VarHandle vh = vhs.s; 247 ByteBuffer array = bs.s; 248 int ci = 0; 249 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 250 251 if (readOnly) { 252 checkROBE(() -> { 253 vh.set(array, ci, VALUE_1); 254 }); 255 } 256 257 if (readOnly) { 258 checkROBE(() -> { 259 vh.setVolatile(array, ci, VALUE_1); 260 }); 261 262 checkROBE(() -> { 263 vh.setRelease(array, ci, VALUE_1); 264 }); 265 266 checkROBE(() -> { 267 vh.setOpaque(array, ci, VALUE_1); 268 }); 269 #if[CAS] 270 271 checkROBE(() -> { 272 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 273 }); 274 275 checkROBE(() -> { 276 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 277 }); 278 279 checkROBE(() -> { 280 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 281 }); 282 283 checkROBE(() -> { 284 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 285 }); 286 287 checkROBE(() -> { 288 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 289 }); 290 291 checkROBE(() -> { 292 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 293 }); 294 295 checkROBE(() -> { 296 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 297 }); 298 299 checkROBE(() -> { 300 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 301 }); 302 checkUOE(() -> { 303 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 304 }); 305 #else[CAS] 306 checkUOE(() -> { 307 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 308 }); 309 310 checkUOE(() -> { 311 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 312 }); 313 314 checkUOE(() -> { 315 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 316 }); 317 318 checkUOE(() -> { 319 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 320 }); 321 322 checkUOE(() -> { 323 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 324 }); 325 326 checkUOE(() -> { 327 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 328 }); 329 330 checkUOE(() -> { 331 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 332 }); 333 #end[CAS] 334 335 #if[AtomicAdd] 336 checkROBE(() -> { 337 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 338 }); 339 340 checkROBE(() -> { 341 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 342 }); 343 #else[AtomicAdd] 344 checkUOE(() -> { 345 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 346 }); 347 348 checkUOE(() -> { 349 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 350 }); 351 #end[AtomicAdd] 352 } 353 else { 354 #if[!CAS] 355 checkUOE(() -> { 356 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 357 }); 358 359 checkUOE(() -> { 360 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 361 }); 362 363 checkUOE(() -> { 364 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 365 }); 366 367 checkUOE(() -> { 368 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 369 }); 370 371 checkUOE(() -> { 372 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 373 }); 374 375 checkUOE(() -> { 376 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 377 }); 378 379 checkUOE(() -> { 380 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 381 }); 382 383 checkUOE(() -> { 384 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 385 }); 386 #end[CAS] 387 #if[!AtomicAdd] 388 checkUOE(() -> { 389 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 390 }); 391 392 checkUOE(() -> { 393 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 394 }); 395 #end[AtomicAdd] 396 } 397 } 398 399 400 static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable { 401 VarHandle vh = vhs.s; 402 byte[] array = bs.s; 403 404 int length = array.length - SIZE + 1; 405 for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { 406 final int ci = i; 407 408 checkIOOBE(() -> { 409 $type$ x = ($type$) vh.get(array, ci); 410 }); 411 412 checkIOOBE(() -> { 413 vh.set(array, ci, VALUE_1); 414 }); 415 416 checkIOOBE(() -> { 417 $type$ x = ($type$) vh.getVolatile(array, ci); 418 }); 419 420 checkIOOBE(() -> { 421 $type$ x = ($type$) vh.getAcquire(array, ci); 422 }); 423 424 checkIOOBE(() -> { 425 $type$ x = ($type$) vh.getOpaque(array, ci); 426 }); 427 428 checkIOOBE(() -> { 429 vh.setVolatile(array, ci, VALUE_1); 430 }); 431 432 checkIOOBE(() -> { 433 vh.setRelease(array, ci, VALUE_1); 434 }); 435 436 checkIOOBE(() -> { 437 vh.setOpaque(array, ci, VALUE_1); 438 }); 439 #if[CAS] 440 441 checkIOOBE(() -> { 442 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 443 }); 444 445 checkIOOBE(() -> { 446 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 447 }); 448 449 checkIOOBE(() -> { 450 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 451 }); 452 453 checkIOOBE(() -> { 454 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 455 }); 456 457 checkIOOBE(() -> { 458 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 459 }); 460 461 checkIOOBE(() -> { 462 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 463 }); 464 465 checkIOOBE(() -> { 466 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 467 }); 468 469 checkIOOBE(() -> { 470 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 471 }); 472 #end[CAS] 473 474 #if[AtomicAdd] 475 checkIOOBE(() -> { 476 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 477 }); 478 479 checkIOOBE(() -> { 480 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 481 }); 482 #end[AtomicAdd] 483 484 } 485 } 486 487 static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { 488 VarHandle vh = vhs.s; 489 ByteBuffer array = bs.s; 490 491 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 492 493 int length = array.limit() - SIZE + 1; 494 for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) { 495 final int ci = i; 496 497 checkIOOBE(() -> { 498 $type$ x = ($type$) vh.get(array, ci); 499 }); 500 501 if (!readOnly) { 502 checkIOOBE(() -> { 503 vh.set(array, ci, VALUE_1); 504 }); 505 } 506 507 checkIOOBE(() -> { 508 $type$ x = ($type$) vh.getVolatile(array, ci); 509 }); 510 511 checkIOOBE(() -> { 512 $type$ x = ($type$) vh.getAcquire(array, ci); 513 }); 514 515 checkIOOBE(() -> { 516 $type$ x = ($type$) vh.getOpaque(array, ci); 517 }); 518 519 if (!readOnly) { 520 checkIOOBE(() -> { 521 vh.setVolatile(array, ci, VALUE_1); 522 }); 523 524 checkIOOBE(() -> { 525 vh.setRelease(array, ci, VALUE_1); 526 }); 527 528 checkIOOBE(() -> { 529 vh.setOpaque(array, ci, VALUE_1); 530 }); 531 532 #if[CAS] 533 checkIOOBE(() -> { 534 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 535 }); 536 537 checkIOOBE(() -> { 538 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 539 }); 540 541 checkIOOBE(() -> { 542 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 543 }); 544 545 checkIOOBE(() -> { 546 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 547 }); 548 549 checkIOOBE(() -> { 550 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 551 }); 552 553 checkIOOBE(() -> { 554 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 555 }); 556 557 checkIOOBE(() -> { 558 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 559 }); 560 561 checkIOOBE(() -> { 562 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 563 }); 564 #end[CAS] 565 566 #if[AtomicAdd] 567 checkIOOBE(() -> { 568 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 569 }); 570 571 checkIOOBE(() -> { 572 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 573 }); 574 #end[AtomicAdd] 575 } 576 } 577 } 578 579 static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable { 580 VarHandle vh = vhs.s; 581 byte[] array = bs.s; 582 583 int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); 584 585 int length = array.length - SIZE + 1; 586 for (int i = 0; i < length; i++) { 587 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 588 final int ci = i; 589 590 if (!iAligned) { 591 checkISE(() -> { 592 $type$ x = ($type$) vh.getVolatile(array, ci); 593 }); 594 595 checkISE(() -> { 596 $type$ x = ($type$) vh.getAcquire(array, ci); 597 }); 598 599 checkISE(() -> { 600 $type$ x = ($type$) vh.getOpaque(array, ci); 601 }); 602 603 checkISE(() -> { 604 vh.setVolatile(array, ci, VALUE_1); 605 }); 606 607 checkISE(() -> { 608 vh.setRelease(array, ci, VALUE_1); 609 }); 610 611 checkISE(() -> { 612 vh.setOpaque(array, ci, VALUE_1); 613 }); 614 #if[CAS] 615 616 checkISE(() -> { 617 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 618 }); 619 620 checkISE(() -> { 621 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 622 }); 623 624 checkISE(() -> { 625 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 626 }); 627 628 checkISE(() -> { 629 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 630 }); 631 632 checkISE(() -> { 633 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 634 }); 635 636 checkISE(() -> { 637 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 638 }); 639 640 checkISE(() -> { 641 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 642 }); 643 644 checkISE(() -> { 645 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 646 }); 647 #end[CAS] 648 649 #if[AtomicAdd] 650 checkISE(() -> { 651 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 652 }); 653 654 checkISE(() -> { 655 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 656 }); 657 #end[AtomicAdd] 658 659 } 660 } 661 } 662 663 static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable { 664 VarHandle vh = vhs.s; 665 ByteBuffer array = bs.s; 666 667 boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes); 668 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 669 670 int length = array.limit() - SIZE + 1; 671 for (int i = 0; i < length; i++) { 672 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 673 final int ci = i; 674 675 if (!iAligned) { 676 checkISE(() -> { 677 $type$ x = ($type$) vh.getVolatile(array, ci); 678 }); 679 680 checkISE(() -> { 681 $type$ x = ($type$) vh.getAcquire(array, ci); 682 }); 683 684 checkISE(() -> { 685 $type$ x = ($type$) vh.getOpaque(array, ci); 686 }); 687 688 if (!readOnly) { 689 checkISE(() -> { 690 vh.setVolatile(array, ci, VALUE_1); 691 }); 692 693 checkISE(() -> { 694 vh.setRelease(array, ci, VALUE_1); 695 }); 696 697 checkISE(() -> { 698 vh.setOpaque(array, ci, VALUE_1); 699 }); 700 701 #if[CAS] 702 checkISE(() -> { 703 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2); 704 }); 705 706 checkISE(() -> { 707 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1); 708 }); 709 710 checkISE(() -> { 711 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1); 712 }); 713 714 checkISE(() -> { 715 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1); 716 }); 717 718 checkISE(() -> { 719 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); 720 }); 721 722 checkISE(() -> { 723 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); 724 }); 725 726 checkISE(() -> { 727 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2); 728 }); 729 730 checkISE(() -> { 731 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1); 732 }); 733 #end[CAS] 734 735 #if[AtomicAdd] 736 checkISE(() -> { 737 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1); 738 }); 739 740 checkISE(() -> { 741 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1); 742 }); 743 #end[AtomicAdd] 744 } 745 } 746 } 747 } 748 749 static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { 750 VarHandle vh = vhs.s; 751 byte[] array = bs.s; 752 753 int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE); 754 755 bs.fill((byte) 0xff); 756 int length = array.length - SIZE + 1; 757 for (int i = 0; i < length; i++) { 758 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 759 760 // Plain 761 { 762 vh.set(array, i, VALUE_1); 763 $type$ x = ($type$) vh.get(array, i); 764 assertEquals(x, VALUE_1, "get $type$ value"); 765 } 766 767 768 if (iAligned) { 769 // Volatile 770 { 771 vh.setVolatile(array, i, VALUE_2); 772 $type$ x = ($type$) vh.getVolatile(array, i); 773 assertEquals(x, VALUE_2, "setVolatile $type$ value"); 774 } 775 776 // Lazy 777 { 778 vh.setRelease(array, i, VALUE_1); 779 $type$ x = ($type$) vh.getAcquire(array, i); 780 assertEquals(x, VALUE_1, "setRelease $type$ value"); 781 } 782 783 // Opaque 784 { 785 vh.setOpaque(array, i, VALUE_2); 786 $type$ x = ($type$) vh.getOpaque(array, i); 787 assertEquals(x, VALUE_2, "setOpaque $type$ value"); 788 } 789 #if[CAS] 790 791 vh.set(array, i, VALUE_1); 792 793 // Compare 794 { 795 boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); 796 assertEquals(r, true, "success compareAndSet $type$"); 797 $type$ x = ($type$) vh.get(array, i); 798 assertEquals(x, VALUE_2, "success compareAndSet $type$ value"); 799 } 800 801 { 802 boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); 803 assertEquals(r, false, "failing compareAndSet $type$"); 804 $type$ x = ($type$) vh.get(array, i); 805 assertEquals(x, VALUE_2, "failing compareAndSet $type$ value"); 806 } 807 808 { 809 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1); 810 assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$"); 811 $type$ x = ($type$) vh.get(array, i); 812 assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value"); 813 } 814 815 { 816 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3); 817 assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$"); 818 $type$ x = ($type$) vh.get(array, i); 819 assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value"); 820 } 821 822 { 823 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); 824 assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$"); 825 $type$ x = ($type$) vh.get(array, i); 826 assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value"); 827 } 828 829 { 830 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); 831 assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$"); 832 $type$ x = ($type$) vh.get(array, i); 833 assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value"); 834 } 835 836 { 837 $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); 838 assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$"); 839 $type$ x = ($type$) vh.get(array, i); 840 assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value"); 841 } 842 843 { 844 $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); 845 assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$"); 846 $type$ x = ($type$) vh.get(array, i); 847 assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value"); 848 } 849 850 { 851 boolean success = false; 852 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 853 success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); 854 } 855 assertEquals(success, true, "weakCompareAndSet $type$"); 856 $type$ x = ($type$) vh.get(array, i); 857 assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); 858 } 859 860 { 861 boolean success = false; 862 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 863 success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); 864 } 865 assertEquals(success, true, "weakCompareAndSetAcquire $type$"); 866 $type$ x = ($type$) vh.get(array, i); 867 assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); 868 } 869 870 { 871 boolean success = false; 872 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 873 success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); 874 } 875 assertEquals(success, true, "weakCompareAndSetRelease $type$"); 876 $type$ x = ($type$) vh.get(array, i); 877 assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); 878 } 879 880 // Compare set and get 881 { 882 $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1); 883 assertEquals(o, VALUE_2, "getAndSet $type$"); 884 $type$ x = ($type$) vh.get(array, i); 885 assertEquals(x, VALUE_1, "getAndSet $type$ value"); 886 } 887 #end[CAS] 888 889 #if[AtomicAdd] 890 vh.set(array, i, VALUE_1); 891 892 // get and add, add and get 893 { 894 $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3); 895 assertEquals(o, VALUE_1, "getAndAdd $type$"); 896 $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3); 897 assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value"); 898 } 899 #end[AtomicAdd] 900 } 901 } 902 } 903 904 905 static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { 906 VarHandle vh = vhs.s; 907 ByteBuffer array = bs.s; 908 909 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 910 911 bs.fill((byte) 0xff); 912 int length = array.limit() - SIZE + 1; 913 for (int i = 0; i < length; i++) { 914 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 915 916 // Plain 917 { 918 vh.set(array, i, VALUE_1); 919 $type$ x = ($type$) vh.get(array, i); 920 assertEquals(x, VALUE_1, "get $type$ value"); 921 } 922 923 if (iAligned) { 924 // Volatile 925 { 926 vh.setVolatile(array, i, VALUE_2); 927 $type$ x = ($type$) vh.getVolatile(array, i); 928 assertEquals(x, VALUE_2, "setVolatile $type$ value"); 929 } 930 931 // Lazy 932 { 933 vh.setRelease(array, i, VALUE_1); 934 $type$ x = ($type$) vh.getAcquire(array, i); 935 assertEquals(x, VALUE_1, "setRelease $type$ value"); 936 } 937 938 // Opaque 939 { 940 vh.setOpaque(array, i, VALUE_2); 941 $type$ x = ($type$) vh.getOpaque(array, i); 942 assertEquals(x, VALUE_2, "setOpaque $type$ value"); 943 } 944 #if[CAS] 945 946 vh.set(array, i, VALUE_1); 947 948 // Compare 949 { 950 boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2); 951 assertEquals(r, true, "success compareAndSet $type$"); 952 $type$ x = ($type$) vh.get(array, i); 953 assertEquals(x, VALUE_2, "success compareAndSet $type$ value"); 954 } 955 956 { 957 boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3); 958 assertEquals(r, false, "failing compareAndSet $type$"); 959 $type$ x = ($type$) vh.get(array, i); 960 assertEquals(x, VALUE_2, "failing compareAndSet $type$ value"); 961 } 962 963 { 964 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1); 965 assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$"); 966 $type$ x = ($type$) vh.get(array, i); 967 assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value"); 968 } 969 970 { 971 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3); 972 assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$"); 973 $type$ x = ($type$) vh.get(array, i); 974 assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value"); 975 } 976 977 { 978 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2); 979 assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$"); 980 $type$ x = ($type$) vh.get(array, i); 981 assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value"); 982 } 983 984 { 985 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3); 986 assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$"); 987 $type$ x = ($type$) vh.get(array, i); 988 assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value"); 989 } 990 991 { 992 $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1); 993 assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$"); 994 $type$ x = ($type$) vh.get(array, i); 995 assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value"); 996 } 997 998 { 999 $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3); 1000 assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$"); 1001 $type$ x = ($type$) vh.get(array, i); 1002 assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value"); 1003 } 1004 1005 { 1006 boolean success = false; 1007 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 1008 success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); 1009 } 1010 assertEquals(success, true, "weakCompareAndSet $type$"); 1011 $type$ x = ($type$) vh.get(array, i); 1012 assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); 1013 } 1014 1015 { 1016 boolean success = false; 1017 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 1018 success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); 1019 } 1020 assertEquals(success, true, "weakCompareAndSetAcquire $type$"); 1021 $type$ x = ($type$) vh.get(array, i); 1022 assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); 1023 } 1024 1025 { 1026 boolean success = false; 1027 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { 1028 success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); 1029 } 1030 assertEquals(success, true, "weakCompareAndSetRelease $type$"); 1031 $type$ x = ($type$) vh.get(array, i); 1032 assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); 1033 } 1034 1035 // Compare set and get 1036 { 1037 $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1); 1038 assertEquals(o, VALUE_2, "getAndSet $type$"); 1039 $type$ x = ($type$) vh.get(array, i); 1040 assertEquals(x, VALUE_1, "getAndSet $type$ value"); 1041 } 1042 #end[CAS] 1043 1044 #if[AtomicAdd] 1045 vh.set(array, i, VALUE_1); 1046 1047 // get and add, add and get 1048 { 1049 $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3); 1050 assertEquals(o, VALUE_1, "getAndAdd $type$"); 1051 $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3); 1052 assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value"); 1053 } 1054 #end[AtomicAdd] 1055 } 1056 } 1057 } 1058 1059 static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) { 1060 VarHandle vh = vhs.s; 1061 ByteBuffer array = bs.s; 1062 1063 int misalignmentAtZero = array.alignmentOffset(0, SIZE); 1064 1065 ByteBuffer bb = ByteBuffer.allocate(SIZE); 1066 bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 1067 bs.fill(bb.put$Type$(0, VALUE_2).array()); 1068 1069 int length = array.limit() - SIZE + 1; 1070 for (int i = 0; i < length; i++) { 1071 boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0; 1072 1073 $type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) 1074 ? rotateLeft(VALUE_2, (i % SIZE) << 3) 1075 : rotateRight(VALUE_2, (i % SIZE) << 3); 1076 // Plain 1077 { 1078 $type$ x = ($type$) vh.get(array, i); 1079 assertEquals(x, v, "get $type$ value"); 1080 } 1081 1082 if (iAligned) { 1083 // Volatile 1084 { 1085 $type$ x = ($type$) vh.getVolatile(array, i); 1086 assertEquals(x, v, "getVolatile $type$ value"); 1087 } 1088 1089 // Lazy 1090 { 1091 $type$ x = ($type$) vh.getAcquire(array, i); 1092 assertEquals(x, v, "getRelease $type$ value"); 1093 } 1094 1095 // Opaque 1096 { 1097 $type$ x = ($type$) vh.getOpaque(array, i); 1098 assertEquals(x, v, "getOpaque $type$ value"); 1099 } 1100 } 1101 } 1102 } 1103 1104 } 1105