1 /*
   2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8143628
  27  * @summary Test unsafe access for $type$
  28  *
  29 #if[JdkInternalMisc]
  30  * @modules $module$/$package$:+open
  31 #else[JdkInternalMisc]
  32  * @modules $module$/$package$
  33 #end[JdkInternalMisc]
  34  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.$Qualifier$UnsafeAccessTest$Type$
  35  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.$Qualifier$UnsafeAccessTest$Type$
  36  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.$Qualifier$UnsafeAccessTest$Type$
  37  * @run testng/othervm -Diters=20000                         compiler.unsafe.$Qualifier$UnsafeAccessTest$Type$
  38  */
  39 
  40 package compiler.unsafe;
  41 
  42 import org.testng.annotations.Test;
  43 
  44 import java.lang.reflect.Field;
  45 
  46 import static org.testng.Assert.*;
  47 
  48 public class $Qualifier$UnsafeAccessTest$Type$ {
  49     static final int ITERS = Integer.getInteger("iters", 1);
  50     static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10);
  51 
  52     static final $package$.Unsafe UNSAFE;
  53 
  54     static final long V_OFFSET;
  55 
  56     static final Object STATIC_V_BASE;
  57 
  58     static final long STATIC_V_OFFSET;
  59 
  60     static int ARRAY_OFFSET;
  61 
  62     static int ARRAY_SHIFT;
  63 
  64     static {
  65         try {
  66             Field f = $package$.Unsafe.class.getDeclaredField("theUnsafe");
  67             f.setAccessible(true);
  68             UNSAFE = ($package$.Unsafe) f.get(null);
  69         } catch (Exception e) {
  70             throw new RuntimeException("Unable to get Unsafe instance.", e);
  71         }
  72 
  73         try {
  74             Field staticVField = $Qualifier$UnsafeAccessTest$Type$.class.getDeclaredField("static_v");
  75             STATIC_V_BASE = UNSAFE.staticFieldBase(staticVField);
  76             STATIC_V_OFFSET = UNSAFE.staticFieldOffset(staticVField);
  77         } catch (Exception e) {
  78             throw new RuntimeException(e);
  79         }
  80 
  81         try {
  82             Field vField = $Qualifier$UnsafeAccessTest$Type$.class.getDeclaredField("v");
  83             V_OFFSET = UNSAFE.objectFieldOffset(vField);
  84         } catch (Exception e) {
  85             throw new RuntimeException(e);
  86         }
  87 
  88         ARRAY_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
  89         int ascale = UNSAFE.arrayIndexScale($type$[].class);
  90         ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(ascale);
  91     }
  92 
  93     static $type$ static_v;
  94 
  95     $type$ v;
  96 
  97     @Test
  98     public void testFieldInstance() {
  99         $Qualifier$UnsafeAccessTest$Type$ t = new $Qualifier$UnsafeAccessTest$Type$();
 100         for (int c = 0; c < ITERS; c++) {
 101             testAccess(t, V_OFFSET);
 102         }
 103     }
 104 
 105     @Test
 106     public void testFieldStatic() {
 107         for (int c = 0; c < ITERS; c++) {
 108             testAccess(STATIC_V_BASE, STATIC_V_OFFSET);
 109         }
 110     }
 111 
 112     @Test
 113     public void testArray() {
 114         $type$[] array = new $type$[10];
 115         for (int c = 0; c < ITERS; c++) {
 116             for (int i = 0; i < array.length; i++) {
 117                 testAccess(array, (((long) i) << ARRAY_SHIFT) + ARRAY_OFFSET);
 118             }
 119         }
 120     }
 121 
 122 #if[!Object]
 123 #if[!boolean]
 124     @Test
 125     public void testArrayOffHeap() {
 126         int size = 10;
 127         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
 128         try {
 129             for (int c = 0; c < ITERS; c++) {
 130                 for (int i = 0; i < size; i++) {
 131                     testAccess(null, (((long) i) << ARRAY_SHIFT) + address);
 132                 }
 133             }
 134         } finally {
 135             UNSAFE.freeMemory(address);
 136         }
 137     }
 138 
 139     @Test
 140     public void testArrayOffHeapDirect() {
 141         int size = 10;
 142         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
 143         try {
 144             for (int c = 0; c < ITERS; c++) {
 145                 for (int i = 0; i < size; i++) {
 146                     testAccess((((long) i) << ARRAY_SHIFT) + address);
 147                 }
 148             }
 149         } finally {
 150             UNSAFE.freeMemory(address);
 151         }
 152     }
 153 #end[!boolean]
 154 #end[!Object]
 155 
 156     static void testAccess(Object base, long offset) {
 157         // Plain
 158         {
 159             UNSAFE.put$MethodAffix$(base, offset, $value1$);
 160             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 161             assertEquals(x, $value1$, "set $type$ value");
 162         }
 163 
 164         // Volatile
 165         {
 166             UNSAFE.put$MethodAffix$Volatile(base, offset, $value2$);
 167             $type$ x = UNSAFE.get$MethodAffix$Volatile(base, offset);
 168             assertEquals(x, $value2$, "putVolatile $type$ value");
 169         }
 170 
 171 #if[!JdkInternalMisc]
 172 #if[Ordered]
 173         // Lazy
 174         {
 175             UNSAFE.putOrdered$MethodAffix$(base, offset, $value1$);
 176             $type$ x = UNSAFE.get$MethodAffix$Volatile(base, offset);
 177             assertEquals(x, $value1$, "putRelease $type$ value");
 178         }
 179 #end[Ordered]
 180 #end[!JdkInternalMisc]
 181 
 182 #if[JdkInternalMisc]
 183         // Lazy
 184         {
 185             UNSAFE.put$MethodAffix$Release(base, offset, $value1$);
 186             $type$ x = UNSAFE.get$MethodAffix$Acquire(base, offset);
 187             assertEquals(x, $value1$, "putRelease $type$ value");
 188         }
 189 
 190         // Opaque
 191         {
 192             UNSAFE.put$MethodAffix$Opaque(base, offset, $value2$);
 193             $type$ x = UNSAFE.get$MethodAffix$Opaque(base, offset);
 194             assertEquals(x, $value2$, "putOpaque $type$ value");
 195         }
 196 #end[JdkInternalMisc]
 197 
 198 #if[JdkInternalMisc]
 199 #if[Unaligned]
 200         // Unaligned
 201         {
 202             UNSAFE.put$MethodAffix$Unaligned(base, offset, $value2$);
 203             $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset);
 204             assertEquals(x, $value2$, "putUnaligned $type$ value");
 205         }
 206 
 207         {
 208             UNSAFE.put$MethodAffix$Unaligned(base, offset, $value1$, true);
 209             $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset, true);
 210             assertEquals(x, $value1$, "putUnaligned big endian $type$ value");
 211         }
 212 
 213         {
 214             UNSAFE.put$MethodAffix$Unaligned(base, offset, $value2$, false);
 215             $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset, false);
 216             assertEquals(x, $value2$, "putUnaligned little endian $type$ value");
 217         }
 218 #end[Unaligned]
 219 #end[JdkInternalMisc]
 220 
 221 #if[CAS]
 222         UNSAFE.put$MethodAffix$(base, offset, $value1$);
 223 
 224         // Compare
 225         {
 226 #if[JdkInternalMisc]
 227             boolean r = UNSAFE.compareAndSet$MethodAffix$(base, offset, $value1$, $value2$);
 228             assertEquals(r, true, "success compareAndSet $type$");
 229 #else[JdkInternalMisc]
 230             boolean r = UNSAFE.compareAndSwap$MethodAffix$(base, offset, $value1$, $value2$);
 231             assertEquals(r, true, "success compareAndSwap $type$");
 232 #end[JdkInternalMisc]
 233             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 234 #if[JdkInternalMisc]
 235             assertEquals(x, $value2$, "success compareAndSet $type$ value");
 236 #else[JdkInternalMisc]
 237             assertEquals(x, $value2$, "success compareAndSwap $type$ value");
 238 #end[JdkInternalMisc]
 239         }
 240 
 241         {
 242 #if[JdkInternalMisc]
 243             boolean r = UNSAFE.compareAndSet$MethodAffix$(base, offset, $value1$, $value3$);
 244             assertEquals(r, false, "failing compareAndSet $type$");
 245 #else[JdkInternalMisc]
 246             boolean r = UNSAFE.compareAndSwap$MethodAffix$(base, offset, $value1$, $value3$);
 247             assertEquals(r, false, "failing compareAndSwap $type$");
 248 #end[JdkInternalMisc]
 249             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 250 #if[JdkInternalMisc]
 251             assertEquals(x, $value2$, "failing compareAndSet $type$ value");
 252 #else[JdkInternalMisc]
 253             assertEquals(x, $value2$, "failing compareAndSwap $type$ value");
 254 #end[JdkInternalMisc]
 255         }
 256 
 257 #if[JdkInternalMisc]
 258         // Advanced compare
 259         {
 260             $type$ r = UNSAFE.compareAndExchange$MethodAffix$(base, offset, $value2$, $value1$);
 261             assertEquals(r, $value2$, "success compareAndExchange $type$");
 262             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 263             assertEquals(x, $value1$, "success compareAndExchange $type$ value");
 264         }
 265 
 266         {
 267             $type$ r = UNSAFE.compareAndExchange$MethodAffix$(base, offset, $value2$, $value3$);
 268             assertEquals(r, $value1$, "failing compareAndExchange $type$");
 269             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 270             assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
 271         }
 272 
 273         {
 274             $type$ r = UNSAFE.compareAndExchange$MethodAffix$Acquire(base, offset, $value1$, $value2$);
 275             assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
 276             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 277             assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
 278         }
 279 
 280         {
 281             $type$ r = UNSAFE.compareAndExchange$MethodAffix$Acquire(base, offset, $value1$, $value3$);
 282             assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
 283             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 284             assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
 285         }
 286 
 287         {
 288             $type$ r = UNSAFE.compareAndExchange$MethodAffix$Release(base, offset, $value2$, $value1$);
 289             assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
 290             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 291             assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
 292         }
 293 
 294         {
 295             $type$ r = UNSAFE.compareAndExchange$MethodAffix$Release(base, offset, $value2$, $value3$);
 296             assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
 297             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 298             assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
 299         }
 300 
 301         {
 302             boolean success = false;
 303             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 304                 success = UNSAFE.weakCompareAndSet$MethodAffix$Plain(base, offset, $value1$, $value2$);
 305             }
 306             assertEquals(success, true, "weakCompareAndSetPlain $type$");
 307             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 308             assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
 309         }
 310 
 311         {
 312             boolean success = false;
 313             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 314                 success = UNSAFE.weakCompareAndSet$MethodAffix$Acquire(base, offset, $value2$, $value1$);
 315             }
 316             assertEquals(success, true, "weakCompareAndSetAcquire $type$");
 317             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 318             assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
 319         }
 320 
 321         {
 322             boolean success = false;
 323             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 324                 success = UNSAFE.weakCompareAndSet$MethodAffix$Release(base, offset, $value1$, $value2$);
 325             }
 326             assertEquals(success, true, "weakCompareAndSetRelease $type$");
 327             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 328             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
 329         }
 330 
 331         {
 332             boolean success = false;
 333             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 334                 success = UNSAFE.weakCompareAndSet$MethodAffix$(base, offset, $value2$, $value1$);
 335             }
 336             assertEquals(success, true, "weakCompareAndSet $type$");
 337             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 338             assertEquals(x, $value1$, "weakCompareAndSet $type$");
 339         }
 340 
 341 #end[JdkInternalMisc]
 342         UNSAFE.put$MethodAffix$(base, offset, $value2$);
 343 
 344         // Compare set and get
 345         {
 346             $type$ o = UNSAFE.getAndSet$MethodAffix$(base, offset, $value1$);
 347             assertEquals(o, $value2$, "getAndSet $type$");
 348             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 349             assertEquals(x, $value1$, "getAndSet $type$ value");
 350         }
 351 #end[CAS]
 352 
 353 #if[AtomicAdd]
 354         UNSAFE.put$MethodAffix$(base, offset, $value1$);
 355 
 356         // get and add, add and get
 357         {
 358             $type$ o = UNSAFE.getAndAdd$MethodAffix$(base, offset, $value2$);
 359             assertEquals(o, $value1$, "getAndAdd $type$");
 360             $type$ x = UNSAFE.get$MethodAffix$(base, offset);
 361             assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$");
 362         }
 363 #end[AtomicAdd]
 364     }
 365 
 366 #if[!Object]
 367 #if[!boolean]
 368     static void testAccess(long address) {
 369         // Plain
 370         {
 371             UNSAFE.put$MethodAffix$(address, $value1$);
 372             $type$ x = UNSAFE.get$MethodAffix$(address);
 373             assertEquals(x, $value1$, "set $type$ value");
 374         }
 375     }
 376 #end[!boolean]
 377 #end[!Object]
 378 }