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