1 /*
   2  * Copyright (c) 2018, 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 package org.graalvm.compiler.replacements.jdk9;
  26 
  27 import jdk.vm.ci.aarch64.AArch64;
  28 import jdk.vm.ci.amd64.AMD64;
  29 import jdk.vm.ci.code.TargetDescription;
  30 import org.graalvm.compiler.api.test.Graal;
  31 import org.graalvm.compiler.core.phases.HighTier;
  32 import org.graalvm.compiler.options.OptionValues;
  33 import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
  34 import org.graalvm.compiler.runtime.RuntimeProvider;
  35 import org.graalvm.compiler.test.AddExports;
  36 import org.junit.Test;
  37 
  38 import java.lang.reflect.Field;
  39 
  40 @AddExports("java.base/jdk.internal.misc")
  41 public class UnsafeReplacementsTest extends MethodSubstitutionTest {
  42 
  43     static class Container {
  44         public volatile boolean booleanField;
  45         public volatile byte byteField = 17;
  46         public volatile char charField = 1025;
  47         public volatile short shortField = 2232;
  48         public volatile int intField = 0xcafebabe;
  49         public volatile long longField = 0xdedababafafaL;
  50         public volatile float floatField = 0.125f;
  51         public volatile double doubleField = 0.125;
  52         public volatile Object objectField = dummyValue;
  53     }
  54 
  55     static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
  56     static Container dummyValue = new Container();
  57     static Container newDummyValue = new Container();
  58     static long booleanOffset;
  59     static long byteOffset;
  60     static long charOffset;
  61     static long shortOffset;
  62     static long intOffset;
  63     static long longOffset;
  64     static long floatOffset;
  65     static long doubleOffset;
  66     static long objectOffset;
  67 
  68     static {
  69         try {
  70             booleanOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("booleanField"));
  71             byteOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("byteField"));
  72             charOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("charField"));
  73             shortOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("shortField"));
  74             intOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("intField"));
  75             longOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("longField"));
  76             floatOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("floatField"));
  77             doubleOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("doubleField"));
  78             objectOffset = unsafe.objectFieldOffset(Container.class.getDeclaredField("objectField"));
  79         } catch (NoSuchFieldException e) {
  80             throw new RuntimeException(e);
  81         }
  82     }
  83 
  84     public static boolean unsafeCompareAndSetBoolean() {
  85         Container container = new Container();
  86         return unsafe.compareAndSetBoolean(container, booleanOffset, false, true);
  87     }
  88 
  89     public static boolean unsafeCompareAndSetByte() {
  90         Container container = new Container();
  91         return unsafe.compareAndSetByte(container, byteOffset, (byte) 17, (byte) 121);
  92     }
  93 
  94     public static boolean unsafeCompareAndSetChar() {
  95         Container container = new Container();
  96         return unsafe.compareAndSetChar(container, charOffset, (char) 1025, (char) 1777);
  97     }
  98 
  99     public static boolean unsafeCompareAndSetShort() {
 100         Container container = new Container();
 101         return unsafe.compareAndSetShort(container, shortOffset, (short) 2232, (short) 12111);
 102     }
 103 
 104     public static boolean unsafeCompareAndSetInt() {
 105         Container container = new Container();
 106         return unsafe.compareAndSetInt(container, intOffset, 0xcafebabe, 0xbabefafa);
 107     }
 108 
 109     public static boolean unsafeCompareAndSetLong() {
 110         Container container = new Container();
 111         return unsafe.compareAndSetLong(container, longOffset, 0xdedababafafaL, 0xfafacecafafadedaL);
 112     }
 113 
 114     public static boolean unsafeCompareAndSetFloat() {
 115         Container container = new Container();
 116         return unsafe.compareAndSetFloat(container, floatOffset, 0.125f, 0.25f);
 117     }
 118 
 119     public static boolean unsafeCompareAndSetDouble() {
 120         Container container = new Container();
 121         return unsafe.compareAndSetDouble(container, doubleOffset, 0.125, 0.25);
 122     }
 123 
 124     public static boolean unsafeCompareAndSetReference() {
 125         Container container = new Container();
 126         return unsafe.compareAndSetReference(container, objectOffset, dummyValue, newDummyValue);
 127     }
 128 
 129     public static boolean unsafeCompareAndExchangeBoolean() {
 130         Container container = new Container();
 131         return unsafe.compareAndExchangeBoolean(container, booleanOffset, false, true);
 132     }
 133 
 134     public static byte unsafeCompareAndExchangeByte() {
 135         Container container = new Container();
 136         return unsafe.compareAndExchangeByte(container, byteOffset, (byte) 17, (byte) 31);
 137     }
 138 
 139     public static char unsafeCompareAndExchangeChar() {
 140         Container container = new Container();
 141         return unsafe.compareAndExchangeChar(container, charOffset, (char) 1025, (char) 4502);
 142     }
 143 
 144     public static short unsafeCompareAndExchangeShort() {
 145         Container container = new Container();
 146         return unsafe.compareAndExchangeShort(container, shortOffset, (short) 2232, (short) 8121);
 147     }
 148 
 149     public static int unsafeCompareAndExchangeInt() {
 150         Container container = new Container();
 151         return unsafe.compareAndExchangeInt(container, intOffset, 0xcafebabe, 0xbabefafa);
 152     }
 153 
 154     public static long unsafeCompareAndExchangeLong() {
 155         Container container = new Container();
 156         return unsafe.compareAndExchangeLong(container, longOffset, 0xdedababafafaL, 0xfafacecafafadedaL);
 157     }
 158 
 159     public static float unsafeCompareAndExchangeFloat() {
 160         Container container = new Container();
 161         return unsafe.compareAndExchangeFloat(container, floatOffset, 0.125f, 0.25f);
 162     }
 163 
 164     public static double unsafeCompareAndExchangeDouble() {
 165         Container container = new Container();
 166         return unsafe.compareAndExchangeDouble(container, doubleOffset, 0.125, 0.25);
 167     }
 168 
 169     public static Object unsafeCompareAndExchangeReference() {
 170         Container container = new Container();
 171         return unsafe.compareAndExchangeReference(container, objectOffset, dummyValue, newDummyValue);
 172     }
 173 
 174     @Test
 175     public void testCompareAndSet() {
 176         TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget();
 177         if (target.arch instanceof AMD64) {
 178             testGraph("unsafeCompareAndSetBoolean");
 179             testGraph("unsafeCompareAndSetByte");
 180             testGraph("unsafeCompareAndSetChar");
 181             testGraph("unsafeCompareAndSetShort");
 182             testGraph("unsafeCompareAndSetInt");
 183             testGraph("unsafeCompareAndSetLong");
 184             testGraph("unsafeCompareAndSetFloat");
 185             testGraph("unsafeCompareAndSetDouble");
 186             testGraph("unsafeCompareAndSetReference");
 187             testGraph("unsafeCompareAndExchangeBoolean");
 188             testGraph("unsafeCompareAndExchangeByte");
 189             testGraph("unsafeCompareAndExchangeChar");
 190             testGraph("unsafeCompareAndExchangeShort");
 191             testGraph("unsafeCompareAndExchangeInt");
 192             testGraph("unsafeCompareAndExchangeLong");
 193             testGraph("unsafeCompareAndExchangeFloat");
 194             testGraph("unsafeCompareAndExchangeDouble");
 195             testGraph("unsafeCompareAndExchangeReference");
 196         }
 197         test("unsafeCompareAndSetBoolean");
 198         test("unsafeCompareAndSetByte");
 199         test("unsafeCompareAndSetChar");
 200         test("unsafeCompareAndSetShort");
 201         test("unsafeCompareAndSetInt");
 202         test("unsafeCompareAndSetLong");
 203         test("unsafeCompareAndSetFloat");
 204         test("unsafeCompareAndSetDouble");
 205         test("unsafeCompareAndSetReference");
 206         test("unsafeCompareAndExchangeBoolean");
 207         test("unsafeCompareAndExchangeByte");
 208         test("unsafeCompareAndExchangeChar");
 209         test("unsafeCompareAndExchangeShort");
 210         test("unsafeCompareAndExchangeInt");
 211         test("unsafeCompareAndExchangeLong");
 212         test("unsafeCompareAndExchangeFloat");
 213         test("unsafeCompareAndExchangeDouble");
 214         test("unsafeCompareAndExchangeReference");
 215     }
 216 
 217     public static int unsafeGetAndAddByte() {
 218         Container container = new Container();
 219         return unsafe.getAndAddByte(container, byteOffset, (byte) 2);
 220     }
 221 
 222     public static int unsafeGetAndAddChar() {
 223         Container container = new Container();
 224         return unsafe.getAndAddChar(container, charOffset, (char) 250);
 225     }
 226 
 227     public static int unsafeGetAndAddShort() {
 228         Container container = new Container();
 229         return unsafe.getAndAddShort(container, shortOffset, (short) 1250);
 230     }
 231 
 232     public static int unsafeGetAndAddInt() {
 233         Container container = new Container();
 234         return unsafe.getAndAddInt(container, intOffset, 104501);
 235     }
 236 
 237     public static long unsafeGetAndAddLong() {
 238         Container container = new Container();
 239         return unsafe.getAndAddLong(container, longOffset, 0x123456abcdL);
 240     }
 241 
 242     @Test
 243     public void testGetAndAdd() {
 244         TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget();
 245         if (target.arch instanceof AMD64) {
 246             testGraph("unsafeGetAndAddByte");
 247             testGraph("unsafeGetAndAddChar");
 248             testGraph("unsafeGetAndAddShort");
 249         }
 250         if (target.arch instanceof AMD64 || target.arch instanceof AArch64) {
 251             testGraph("unsafeGetAndAddInt");
 252             testGraph("unsafeGetAndAddLong");
 253         }
 254         test("unsafeGetAndAddByte");
 255         test("unsafeGetAndAddChar");
 256         test("unsafeGetAndAddShort");
 257         test("unsafeGetAndAddInt");
 258         test("unsafeGetAndAddLong");
 259     }
 260 
 261     public static boolean unsafeGetAndSetBoolean() {
 262         Container container = new Container();
 263         return unsafe.getAndSetBoolean(container, booleanOffset, true);
 264     }
 265 
 266     public static byte unsafeGetAndSetByte() {
 267         Container container = new Container();
 268         return unsafe.getAndSetByte(container, byteOffset, (byte) 129);
 269     }
 270 
 271     public static char unsafeGetAndSetChar() {
 272         Container container = new Container();
 273         return unsafe.getAndSetChar(container, charOffset, (char) 21111);
 274     }
 275 
 276     public static short unsafeGetAndSetShort() {
 277         Container container = new Container();
 278         return unsafe.getAndSetShort(container, shortOffset, (short) 21111);
 279     }
 280 
 281     public static int unsafeGetAndSetInt() {
 282         Container container = new Container();
 283         return unsafe.getAndSetInt(container, intOffset, 0x1234af);
 284     }
 285 
 286     public static long unsafeGetAndSetLong() {
 287         Container container = new Container();
 288         return unsafe.getAndSetLong(container, longOffset, 0x12345678abL);
 289     }
 290 
 291     public static Object unsafeGetAndSetReference() {
 292         Container container = new Container();
 293         container.objectField = null;
 294         Container other = new Container();
 295         return unsafe.getAndSetReference(container, objectOffset, other);
 296     }
 297 
 298     @Test
 299     public void testGetAndSet() {
 300         TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget();
 301         if (target.arch instanceof AMD64) {
 302             testGraph("unsafeGetAndSetBoolean");
 303             testGraph("unsafeGetAndSetByte");
 304             testGraph("unsafeGetAndSetChar");
 305             testGraph("unsafeGetAndSetShort");
 306         }
 307         if (target.arch instanceof AMD64 || target.arch instanceof AArch64) {
 308             testGraph("unsafeGetAndSetInt");
 309             testGraph("unsafeGetAndSetLong");
 310             testGraph("unsafeGetAndSetReference");
 311         }
 312         test("unsafeGetAndSetBoolean");
 313         test("unsafeGetAndSetByte");
 314         test("unsafeGetAndSetChar");
 315         test("unsafeGetAndSetShort");
 316         test("unsafeGetAndSetInt");
 317         test("unsafeGetAndSetLong");
 318         test("unsafeGetAndSetReference");
 319     }
 320 
 321     public static void fieldInstance() {
 322         JdkInternalMiscUnsafeAccessTestBoolean.testFieldInstance();
 323     }
 324 
 325     @Test
 326     public void testFieldInstance() {
 327         test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "fieldInstance");
 328     }
 329 
 330     public static void array() {
 331         JdkInternalMiscUnsafeAccessTestBoolean.testArray();
 332     }
 333 
 334     @Test
 335     public void testArray() {
 336         test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "array");
 337     }
 338 
 339     public static void fieldStatic() {
 340         JdkInternalMiscUnsafeAccessTestBoolean.testFieldStatic();
 341     }
 342 
 343     @Test
 344     public void testFieldStatic() {
 345         test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "fieldStatic");
 346     }
 347 
 348     public static void assertEquals(Object seen, Object expected, String message) {
 349         if (seen != expected) {
 350             throw new AssertionError(message + " - seen: " + seen + ", expected: " + expected);
 351         }
 352     }
 353 
 354     public static class JdkInternalMiscUnsafeAccessTestBoolean {
 355         static final int ITERATIONS = 100000;
 356 
 357         static final int WEAK_ATTEMPTS = 10;
 358 
 359         static final long V_OFFSET;
 360 
 361         static final Object STATIC_V_BASE;
 362 
 363         static final long STATIC_V_OFFSET;
 364 
 365         static final int ARRAY_OFFSET;
 366 
 367         static final int ARRAY_SHIFT;
 368 
 369         static {
 370             try {
 371                 Field staticVField = UnsafeReplacementsTest.JdkInternalMiscUnsafeAccessTestBoolean.class.getDeclaredField("staticV");
 372                 STATIC_V_BASE = unsafe.staticFieldBase(staticVField);
 373                 STATIC_V_OFFSET = unsafe.staticFieldOffset(staticVField);
 374             } catch (Exception e) {
 375                 throw new RuntimeException(e);
 376             }
 377 
 378             try {
 379                 Field vField = UnsafeReplacementsTest.JdkInternalMiscUnsafeAccessTestBoolean.class.getDeclaredField("v");
 380                 V_OFFSET = unsafe.objectFieldOffset(vField);
 381             } catch (Exception e) {
 382                 throw new RuntimeException(e);
 383             }
 384 
 385             ARRAY_OFFSET = unsafe.arrayBaseOffset(boolean[].class);
 386             int ascale = unsafe.arrayIndexScale(boolean[].class);
 387             ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(ascale);
 388         }
 389 
 390         static boolean staticV;
 391 
 392         boolean v;
 393 
 394         @BytecodeParserForceInline
 395         public static void testFieldInstance() {
 396             JdkInternalMiscUnsafeAccessTestBoolean t = new JdkInternalMiscUnsafeAccessTestBoolean();
 397             for (int c = 0; c < ITERATIONS; c++) {
 398                 testAccess(t, V_OFFSET);
 399             }
 400         }
 401 
 402         public static void testFieldStatic() {
 403             for (int c = 0; c < ITERATIONS; c++) {
 404                 testAccess(STATIC_V_BASE, STATIC_V_OFFSET);
 405             }
 406         }
 407 
 408         public static void testArray() {
 409             boolean[] array = new boolean[10];
 410             for (int c = 0; c < ITERATIONS; c++) {
 411                 for (int i = 0; i < array.length; i++) {
 412                     testAccess(array, (((long) i) << ARRAY_SHIFT) + ARRAY_OFFSET);
 413                 }
 414             }
 415         }
 416 
 417         // Checkstyle: stop
 418         @BytecodeParserForceInline
 419         public static void testAccess(Object base, long offset) {
 420             // Advanced compare
 421             {
 422                 boolean r = unsafe.compareAndExchangeBoolean(base, offset, false, true);
 423                 assertEquals(r, false, "success compareAndExchange boolean");
 424                 boolean x = unsafe.getBoolean(base, offset);
 425                 assertEquals(x, true, "success compareAndExchange boolean value");
 426             }
 427 
 428             {
 429                 boolean r = unsafe.compareAndExchangeBoolean(base, offset, false, false);
 430                 assertEquals(r, true, "failing compareAndExchange boolean");
 431                 boolean x = unsafe.getBoolean(base, offset);
 432                 assertEquals(x, true, "failing compareAndExchange boolean value");
 433             }
 434 
 435             {
 436                 boolean r = unsafe.compareAndExchangeBooleanAcquire(base, offset, true, false);
 437                 assertEquals(r, true, "success compareAndExchangeAcquire boolean");
 438                 boolean x = unsafe.getBoolean(base, offset);
 439                 assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
 440             }
 441 
 442             {
 443                 boolean r = unsafe.compareAndExchangeBooleanAcquire(base, offset, true, false);
 444                 assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
 445                 boolean x = unsafe.getBoolean(base, offset);
 446                 assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
 447             }
 448 
 449             {
 450                 boolean r = unsafe.compareAndExchangeBooleanRelease(base, offset, false, true);
 451                 assertEquals(r, false, "success compareAndExchangeRelease boolean");
 452                 boolean x = unsafe.getBoolean(base, offset);
 453                 assertEquals(x, true, "success compareAndExchangeRelease boolean value");
 454             }
 455 
 456             {
 457                 boolean r = unsafe.compareAndExchangeBooleanRelease(base, offset, false, false);
 458                 assertEquals(r, true, "failing compareAndExchangeRelease boolean");
 459                 boolean x = unsafe.getBoolean(base, offset);
 460                 assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
 461             }
 462 
 463             {
 464                 boolean success = false;
 465                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 466                     success = unsafe.weakCompareAndSetBooleanPlain(base, offset, true, false);
 467                 }
 468                 assertEquals(success, true, "weakCompareAndSetPlain boolean");
 469                 boolean x = unsafe.getBoolean(base, offset);
 470                 assertEquals(x, false, "weakCompareAndSetPlain boolean value");
 471             }
 472 
 473             {
 474                 boolean success = false;
 475                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 476                     success = unsafe.weakCompareAndSetBooleanAcquire(base, offset, false, true);
 477                 }
 478                 assertEquals(success, true, "weakCompareAndSetAcquire boolean");
 479                 boolean x = unsafe.getBoolean(base, offset);
 480                 assertEquals(x, true, "weakCompareAndSetAcquire boolean");
 481             }
 482 
 483             {
 484                 boolean success = false;
 485                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 486                     success = unsafe.weakCompareAndSetBooleanRelease(base, offset, true, false);
 487                 }
 488                 assertEquals(success, true, "weakCompareAndSetRelease boolean");
 489                 boolean x = unsafe.getBoolean(base, offset);
 490                 assertEquals(x, false, "weakCompareAndSetRelease boolean");
 491             }
 492 
 493             {
 494                 boolean success = false;
 495                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 496                     success = unsafe.weakCompareAndSetBoolean(base, offset, false, true);
 497                 }
 498                 assertEquals(success, true, "weakCompareAndSet boolean");
 499                 boolean x = unsafe.getBoolean(base, offset);
 500                 assertEquals(x, true, "weakCompareAndSet boolean");
 501             }
 502 
 503             unsafe.putBoolean(base, offset, false);
 504 
 505             // Compare set and get
 506             {
 507                 boolean o = unsafe.getAndSetBoolean(base, offset, true);
 508                 assertEquals(o, false, "getAndSet boolean");
 509                 boolean x = unsafe.getBoolean(base, offset);
 510                 assertEquals(x, true, "getAndSet boolean value");
 511             }
 512 
 513         }
 514         // Checkstyle: resume
 515     }
 516 
 517     public static boolean unsafeGetPutBoolean() {
 518         Container container = new Container();
 519         unsafe.putBoolean(container, booleanOffset, true);
 520         return unsafe.getBoolean(container, booleanOffset);
 521     }
 522 
 523     public static byte unsafeGetPutByte() {
 524         Container container = new Container();
 525         unsafe.putByte(container, byteOffset, (byte) 0x12);
 526         return unsafe.getByte(container, byteOffset);
 527     }
 528 
 529     public static short unsafeGetPutShort() {
 530         Container container = new Container();
 531         unsafe.putShort(container, shortOffset, (short) 0x1234);
 532         return unsafe.getShort(container, shortOffset);
 533     }
 534 
 535     public static char unsafeGetPutChar() {
 536         Container container = new Container();
 537         unsafe.putChar(container, charOffset, 'x');
 538         return unsafe.getChar(container, charOffset);
 539     }
 540 
 541     public static int unsafeGetPutInt() {
 542         Container container = new Container();
 543         unsafe.putInt(container, intOffset, 0x01234567);
 544         return unsafe.getInt(container, intOffset);
 545     }
 546 
 547     public static long unsafeGetPutLong() {
 548         Container container = new Container();
 549         unsafe.putLong(container, longOffset, 0x01234567890ABCDEFL);
 550         return unsafe.getLong(container, longOffset);
 551     }
 552 
 553     public static float unsafeGetPutFloat() {
 554         Container container = new Container();
 555         unsafe.putFloat(container, floatOffset, 1.234F);
 556         return unsafe.getFloat(container, floatOffset);
 557     }
 558 
 559     public static double unsafeGetPutDouble() {
 560         Container container = new Container();
 561         unsafe.putDouble(container, doubleOffset, 1.23456789);
 562         return unsafe.getDouble(container, doubleOffset);
 563     }
 564 
 565     public static Object unsafeGetPutReference() {
 566         Container container = new Container();
 567         unsafe.putReference(container, objectOffset, "Hello there");
 568         return unsafe.getReference(container, objectOffset);
 569     }
 570 
 571     public static boolean unsafeGetPutBooleanOpaque() {
 572         Container container = new Container();
 573         unsafe.putBooleanOpaque(container, booleanOffset, true);
 574         return unsafe.getBooleanOpaque(container, booleanOffset);
 575     }
 576 
 577     public static byte unsafeGetPutByteOpaque() {
 578         Container container = new Container();
 579         unsafe.putByteOpaque(container, byteOffset, (byte) 0x12);
 580         return unsafe.getByteOpaque(container, byteOffset);
 581     }
 582 
 583     public static short unsafeGetPutShortOpaque() {
 584         Container container = new Container();
 585         unsafe.putShortOpaque(container, shortOffset, (short) 0x1234);
 586         return unsafe.getShortOpaque(container, shortOffset);
 587     }
 588 
 589     public static char unsafeGetPutCharOpaque() {
 590         Container container = new Container();
 591         unsafe.putCharOpaque(container, charOffset, 'x');
 592         return unsafe.getCharOpaque(container, charOffset);
 593     }
 594 
 595     public static int unsafeGetPutIntOpaque() {
 596         Container container = new Container();
 597         unsafe.putIntOpaque(container, intOffset, 0x01234567);
 598         return unsafe.getIntOpaque(container, intOffset);
 599     }
 600 
 601     public static long unsafeGetPutLongOpaque() {
 602         Container container = new Container();
 603         unsafe.putLongOpaque(container, longOffset, 0x01234567890ABCDEFL);
 604         return unsafe.getLongOpaque(container, longOffset);
 605     }
 606 
 607     public static float unsafeGetPutFloatOpaque() {
 608         Container container = new Container();
 609         unsafe.putFloatOpaque(container, floatOffset, 1.234F);
 610         return unsafe.getFloatOpaque(container, floatOffset);
 611     }
 612 
 613     public static double unsafeGetPutDoubleOpaque() {
 614         Container container = new Container();
 615         unsafe.putDoubleOpaque(container, doubleOffset, 1.23456789);
 616         return unsafe.getDoubleOpaque(container, doubleOffset);
 617     }
 618 
 619     public static Object unsafeGetPutReferenceOpaque() {
 620         Container container = new Container();
 621         unsafe.putReferenceOpaque(container, objectOffset, "Hello there");
 622         return unsafe.getReferenceOpaque(container, objectOffset);
 623     }
 624 
 625     public static boolean unsafeGetPutBooleanRA() {
 626         Container container = new Container();
 627         unsafe.putBooleanRelease(container, booleanOffset, true);
 628         return unsafe.getBooleanAcquire(container, booleanOffset);
 629     }
 630 
 631     public static byte unsafeGetPutByteRA() {
 632         Container container = new Container();
 633         unsafe.putByteRelease(container, byteOffset, (byte) 0x12);
 634         return unsafe.getByteAcquire(container, byteOffset);
 635     }
 636 
 637     public static short unsafeGetPutShortRA() {
 638         Container container = new Container();
 639         unsafe.putShortRelease(container, shortOffset, (short) 0x1234);
 640         return unsafe.getShortAcquire(container, shortOffset);
 641     }
 642 
 643     public static char unsafeGetPutCharRA() {
 644         Container container = new Container();
 645         unsafe.putCharRelease(container, charOffset, 'x');
 646         return unsafe.getCharAcquire(container, charOffset);
 647     }
 648 
 649     public static int unsafeGetPutIntRA() {
 650         Container container = new Container();
 651         unsafe.putIntRelease(container, intOffset, 0x01234567);
 652         return unsafe.getIntAcquire(container, intOffset);
 653     }
 654 
 655     public static long unsafeGetPutLongRA() {
 656         Container container = new Container();
 657         unsafe.putLongRelease(container, longOffset, 0x01234567890ABCDEFL);
 658         return unsafe.getLongAcquire(container, longOffset);
 659     }
 660 
 661     public static float unsafeGetPutFloatRA() {
 662         Container container = new Container();
 663         unsafe.putFloatRelease(container, floatOffset, 1.234F);
 664         return unsafe.getFloatAcquire(container, floatOffset);
 665     }
 666 
 667     public static double unsafeGetPutDoubleRA() {
 668         Container container = new Container();
 669         unsafe.putDoubleRelease(container, doubleOffset, 1.23456789);
 670         return unsafe.getDoubleAcquire(container, doubleOffset);
 671     }
 672 
 673     public static Object unsafeGetPutReferenceRA() {
 674         Container container = new Container();
 675         unsafe.putReferenceRelease(container, objectOffset, "Hello there");
 676         return unsafe.getReferenceAcquire(container, objectOffset);
 677     }
 678 
 679     public static boolean unsafeGetPutBooleanVolatile() {
 680         Container container = new Container();
 681         unsafe.putBooleanVolatile(container, booleanOffset, true);
 682         return unsafe.getBooleanVolatile(container, booleanOffset);
 683     }
 684 
 685     public static byte unsafeGetPutByteVolatile() {
 686         Container container = new Container();
 687         unsafe.putByteVolatile(container, byteOffset, (byte) 0x12);
 688         return unsafe.getByteVolatile(container, byteOffset);
 689     }
 690 
 691     public static short unsafeGetPutShortVolatile() {
 692         Container container = new Container();
 693         unsafe.putShortVolatile(container, shortOffset, (short) 0x1234);
 694         return unsafe.getShortVolatile(container, shortOffset);
 695     }
 696 
 697     public static char unsafeGetPutCharVolatile() {
 698         Container container = new Container();
 699         unsafe.putCharVolatile(container, charOffset, 'x');
 700         return unsafe.getCharVolatile(container, charOffset);
 701     }
 702 
 703     public static int unsafeGetPutIntVolatile() {
 704         Container container = new Container();
 705         unsafe.putIntVolatile(container, intOffset, 0x01234567);
 706         return unsafe.getIntVolatile(container, intOffset);
 707     }
 708 
 709     public static long unsafeGetPutLongVolatile() {
 710         Container container = new Container();
 711         unsafe.putLongVolatile(container, longOffset, 0x01234567890ABCDEFL);
 712         return unsafe.getLongVolatile(container, longOffset);
 713     }
 714 
 715     public static float unsafeGetPutFloatVolatile() {
 716         Container container = new Container();
 717         unsafe.putFloatVolatile(container, floatOffset, 1.234F);
 718         return unsafe.getFloatVolatile(container, floatOffset);
 719     }
 720 
 721     public static double unsafeGetPutDoubleVolatile() {
 722         Container container = new Container();
 723         unsafe.putDoubleVolatile(container, doubleOffset, 1.23456789);
 724         return unsafe.getDoubleVolatile(container, doubleOffset);
 725     }
 726 
 727     public static Object unsafeGetPutReferenceVolatile() {
 728         Container container = new Container();
 729         unsafe.putReferenceVolatile(container, objectOffset, "Hello there");
 730         return unsafe.getReferenceVolatile(container, objectOffset);
 731     }
 732 
 733     @Test
 734     public void testUnsafeGetPutPlain() {
 735         testGraph("unsafeGetPutBoolean");
 736         testGraph("unsafeGetPutByte");
 737         testGraph("unsafeGetPutShort");
 738         testGraph("unsafeGetPutChar");
 739         testGraph("unsafeGetPutInt");
 740         testGraph("unsafeGetPutLong");
 741         testGraph("unsafeGetPutFloat");
 742         testGraph("unsafeGetPutDouble");
 743         testGraph("unsafeGetPutObject");
 744 
 745         test("unsafeGetPutBoolean");
 746         test("unsafeGetPutByte");
 747         test("unsafeGetPutShort");
 748         test("unsafeGetPutChar");
 749         test("unsafeGetPutInt");
 750         test("unsafeGetPutLong");
 751         test("unsafeGetPutFloat");
 752         test("unsafeGetPutDouble");
 753         test("unsafeGetPutObject");
 754     }
 755 
 756     @Test
 757     public void testUnsafeGetPutOpaque() {
 758         testGraph("unsafeGetPutBooleanOpaque");
 759         testGraph("unsafeGetPutByteOpaque");
 760         testGraph("unsafeGetPutShortOpaque");
 761         testGraph("unsafeGetPutCharOpaque");
 762         testGraph("unsafeGetPutIntOpaque");
 763         testGraph("unsafeGetPutLongOpaque");
 764         testGraph("unsafeGetPutFloatOpaque");
 765         testGraph("unsafeGetPutDoubleOpaque");
 766         testGraph("unsafeGetPutObjectOpaque");
 767 
 768         test("unsafeGetPutBooleanOpaque");
 769         test("unsafeGetPutByteOpaque");
 770         test("unsafeGetPutShortOpaque");
 771         test("unsafeGetPutCharOpaque");
 772         test("unsafeGetPutIntOpaque");
 773         test("unsafeGetPutLongOpaque");
 774         test("unsafeGetPutFloatOpaque");
 775         test("unsafeGetPutDoubleOpaque");
 776         test("unsafeGetPutObjectOpaque");
 777     }
 778 
 779     @Test
 780     public void testUnsafeGetPutReleaseAcquire() {
 781         testGraph("unsafeGetPutBooleanRA");
 782         testGraph("unsafeGetPutByteRA");
 783         testGraph("unsafeGetPutShortRA");
 784         testGraph("unsafeGetPutCharRA");
 785         testGraph("unsafeGetPutIntRA");
 786         testGraph("unsafeGetPutLongRA");
 787         testGraph("unsafeGetPutFloatRA");
 788         testGraph("unsafeGetPutDoubleRA");
 789         testGraph("unsafeGetPutReferenceRA");
 790 
 791         test("unsafeGetPutBooleanRA");
 792         test("unsafeGetPutByteRA");
 793         test("unsafeGetPutShortRA");
 794         test("unsafeGetPutCharRA");
 795         test("unsafeGetPutIntRA");
 796         test("unsafeGetPutLongRA");
 797         test("unsafeGetPutFloatRA");
 798         test("unsafeGetPutDoubleRA");
 799         test("unsafeGetPutReferenceRA");
 800     }
 801 
 802     @Test
 803     public void testUnsafeGetPutVolatile() {
 804         testGraph("unsafeGetPutBooleanVolatile");
 805         testGraph("unsafeGetPutByteVolatile");
 806         testGraph("unsafeGetPutShortVolatile");
 807         testGraph("unsafeGetPutCharVolatile");
 808         testGraph("unsafeGetPutIntVolatile");
 809         testGraph("unsafeGetPutLongVolatile");
 810         testGraph("unsafeGetPutFloatVolatile");
 811         testGraph("unsafeGetPutDoubleVolatile");
 812         testGraph("unsafeGetPutReferenceVolatile");
 813 
 814         test("unsafeGetPutBooleanVolatile");
 815         test("unsafeGetPutByteVolatile");
 816         test("unsafeGetPutShortVolatile");
 817         test("unsafeGetPutCharVolatile");
 818         test("unsafeGetPutIntVolatile");
 819         test("unsafeGetPutLongVolatile");
 820         test("unsafeGetPutFloatVolatile");
 821         test("unsafeGetPutDoubleVolatile");
 822         test("unsafeGetPutReferenceVolatile");
 823     }
 824 }