1 /*
   2  * Copyright (c) 2015, 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  * @modules $module$/$package$
  29  * @run testng/othervm -Diters=100   -Xint                   $Qualifier$UnsafeAccessTest$Type$
  30  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 $Qualifier$UnsafeAccessTest$Type$
  31  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  $Qualifier$UnsafeAccessTest$Type$
  32  * @run testng/othervm -Diters=20000                         $Qualifier$UnsafeAccessTest$Type$
  33  */
  34 
  35 import org.testng.annotations.Test;
  36 
  37 import java.lang.reflect.Field;
  38 
  39 import static org.testng.Assert.*;
  40 
  41 public class $Qualifier$UnsafeAccessTest$Type$ {
  42     static final int ITERS = Integer.getInteger("iters", 1);
  43     static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10);
  44 
  45     static final $package$.Unsafe UNSAFE;
  46 
  47     static final long V_OFFSET;
  48 
  49     static final Object STATIC_V_BASE;
  50 
  51     static final long STATIC_V_OFFSET;
  52 
  53     static int ARRAY_OFFSET;
  54 
  55     static int ARRAY_SHIFT;
  56 
  57     static {
  58         try {
  59             Field f = $package$.Unsafe.class.getDeclaredField("theUnsafe");
  60             f.setAccessible(true);
  61             UNSAFE = ($package$.Unsafe) f.get(null);
  62         } catch (Exception e) {
  63             throw new RuntimeException("Unable to get Unsafe instance.", e);
  64         }
  65 
  66         try {
  67             Field staticVField = $Qualifier$UnsafeAccessTest$Type$.class.getDeclaredField("static_v");
  68             STATIC_V_BASE = UNSAFE.staticFieldBase(staticVField);
  69             STATIC_V_OFFSET = UNSAFE.staticFieldOffset(staticVField);
  70         } catch (Exception e) {
  71             throw new RuntimeException(e);
  72         }
  73 
  74         try {
  75             Field vField = $Qualifier$UnsafeAccessTest$Type$.class.getDeclaredField("v");
  76             V_OFFSET = UNSAFE.objectFieldOffset(vField);
  77         } catch (Exception e) {
  78             throw new RuntimeException(e);
  79         }
  80 
  81         ARRAY_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
  82         int ascale = UNSAFE.arrayIndexScale($type$[].class);
  83         ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(ascale);
  84     }
  85 
  86     static $type$ static_v;
  87 
  88     $type$ v;
  89 
  90     @Test
  91     public void testFieldInstance() {
  92         $Qualifier$UnsafeAccessTest$Type$ t = new $Qualifier$UnsafeAccessTest$Type$();
  93         for (int c = 0; c < ITERS; c++) {
  94             testAccess(t, V_OFFSET);
  95         }
  96     }
  97 
  98     @Test
  99     public void testFieldStatic() {
 100         for (int c = 0; c < ITERS; c++) {
 101             testAccess(STATIC_V_BASE, STATIC_V_OFFSET);
 102         }
 103     }
 104 
 105     @Test
 106     public void testArray() {
 107         $type$[] array = new $type$[10];
 108         for (int c = 0; c < ITERS; c++) {
 109             for (int i = 0; i < array.length; i++) {
 110                 testAccess(array, (((long) i) << ARRAY_SHIFT) + ARRAY_OFFSET);
 111             }
 112         }
 113     }
 114 
 115 #if[!Object]
 116 #if[!boolean]
 117     @Test
 118     public void testArrayOffHeap() {
 119         int size = 10;
 120         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
 121         try {
 122             for (int c = 0; c < ITERS; c++) {
 123                 for (int i = 0; i < size; i++) {
 124                     testAccess(null, (((long) i) << ARRAY_SHIFT) + address);
 125                 }
 126             }
 127         } finally {
 128             UNSAFE.freeMemory(address);
 129         }
 130     }
 131 
 132     @Test
 133     public void testArrayOffHeapDirect() {
 134         int size = 10;
 135         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
 136         try {
 137             for (int c = 0; c < ITERS; c++) {
 138                 for (int i = 0; i < size; i++) {
 139                     testAccess((((long) i) << ARRAY_SHIFT) + address);
 140                 }
 141             }
 142         } finally {
 143             UNSAFE.freeMemory(address);
 144         }
 145     }
 146 #end[!boolean]
 147 #end[!Object]
 148 
 149     static void testAccess(Object base, long offset) {
 150         // Plain
 151         {
 152             UNSAFE.put$Type$(base, offset, $value1$);
 153             $type$ x = UNSAFE.get$Type$(base, offset);
 154             assertEquals(x, $value1$, "set $type$ value");
 155         }
 156 
 157         // Volatile
 158         {
 159             UNSAFE.put$Type$Volatile(base, offset, $value2$);
 160             $type$ x = UNSAFE.get$Type$Volatile(base, offset);
 161             assertEquals(x, $value2$, "putVolatile $type$ value");
 162         }
 163 
 164 #if[!JdkInternalMisc]
 165 #if[Ordered]
 166         // Lazy
 167         {
 168             UNSAFE.putOrdered$Type$(base, offset, $value1$);
 169             $type$ x = UNSAFE.get$Type$Volatile(base, offset);
 170             assertEquals(x, $value1$, "putRelease $type$ value");
 171         }
 172 #end[Ordered]
 173 #end[!JdkInternalMisc]
 174 
 175 #if[JdkInternalMisc]
 176         // Lazy
 177         {
 178             UNSAFE.put$Type$Release(base, offset, $value1$);
 179             $type$ x = UNSAFE.get$Type$Acquire(base, offset);
 180             assertEquals(x, $value1$, "putRelease $type$ value");
 181         }
 182 
 183         // Opaque
 184         {
 185             UNSAFE.put$Type$Opaque(base, offset, $value2$);
 186             $type$ x = UNSAFE.get$Type$Opaque(base, offset);
 187             assertEquals(x, $value2$, "putOpaque $type$ value");
 188         }
 189 #end[JdkInternalMisc]
 190 
 191 #if[JdkInternalMisc]
 192 #if[Unaligned]
 193         // Unaligned
 194         {
 195             UNSAFE.put$Type$Unaligned(base, offset, $value2$);
 196             $type$ x = UNSAFE.get$Type$Unaligned(base, offset);
 197             assertEquals(x, $value2$, "putUnaligned $type$ value");
 198         }
 199 
 200         {
 201             UNSAFE.put$Type$Unaligned(base, offset, $value1$, true);
 202             $type$ x = UNSAFE.get$Type$Unaligned(base, offset, true);
 203             assertEquals(x, $value1$, "putUnaligned big endian $type$ value");
 204         }
 205 
 206         {
 207             UNSAFE.put$Type$Unaligned(base, offset, $value2$, false);
 208             $type$ x = UNSAFE.get$Type$Unaligned(base, offset, false);
 209             assertEquals(x, $value2$, "putUnaligned little endian $type$ value");
 210         }
 211 #end[Unaligned]
 212 #end[JdkInternalMisc]
 213 
 214 #if[CAS]
 215         UNSAFE.put$Type$(base, offset, $value1$);
 216 
 217         // Compare
 218         {
 219             boolean r = UNSAFE.compareAndSwap$Type$(base, offset, $value1$, $value2$);
 220             assertEquals(r, true, "success compareAndSwap $type$");
 221             $type$ x = UNSAFE.get$Type$(base, offset);
 222             assertEquals(x, $value2$, "success compareAndSwap $type$ value");
 223         }
 224 
 225         {
 226             boolean r = UNSAFE.compareAndSwap$Type$(base, offset, $value1$, $value3$);
 227             assertEquals(r, false, "failing compareAndSwap $type$");
 228             $type$ x = UNSAFE.get$Type$(base, offset);
 229             assertEquals(x, $value2$, "failing compareAndSwap $type$ value");
 230         }
 231 
 232 #if[JdkInternalMisc]
 233         // Advanced compare
 234         {
 235             $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value1$);
 236             assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
 237             $type$ x = UNSAFE.get$Type$(base, offset);
 238             assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
 239         }
 240 
 241         {
 242             $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value3$);
 243             assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
 244             $type$ x = UNSAFE.get$Type$(base, offset);
 245             assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
 246         }
 247 
 248         {
 249             $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value2$);
 250             assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
 251             $type$ x = UNSAFE.get$Type$(base, offset);
 252             assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
 253         }
 254 
 255         {
 256             $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value3$);
 257             assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
 258             $type$ x = UNSAFE.get$Type$(base, offset);
 259             assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
 260         }
 261 
 262         {
 263             $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value1$);
 264             assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
 265             $type$ x = UNSAFE.get$Type$(base, offset);
 266             assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
 267         }
 268 
 269         {
 270             $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value3$);
 271             assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
 272             $type$ x = UNSAFE.get$Type$(base, offset);
 273             assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
 274         }
 275 
 276         {
 277             boolean success = false;
 278             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 279                 success = UNSAFE.weakCompareAndSwap$Type$(base, offset, $value1$, $value2$);
 280             }
 281             assertEquals(success, true, "weakCompareAndSwap $type$");
 282             $type$ x = UNSAFE.get$Type$(base, offset);
 283             assertEquals(x, $value2$, "weakCompareAndSwap $type$ value");
 284         }
 285 
 286         {
 287             boolean success = false;
 288             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 289                 success = UNSAFE.weakCompareAndSwap$Type$Acquire(base, offset, $value2$, $value1$);
 290             }
 291             assertEquals(success, true, "weakCompareAndSwapAcquire $type$");
 292             $type$ x = UNSAFE.get$Type$(base, offset);
 293             assertEquals(x, $value1$, "weakCompareAndSwapAcquire $type$");
 294         }
 295 
 296         {
 297             boolean success = false;
 298             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 299                 success = UNSAFE.weakCompareAndSwap$Type$Release(base, offset, $value1$, $value2$);
 300             }
 301             assertEquals(success, true, "weakCompareAndSwapRelease $type$");
 302             $type$ x = UNSAFE.get$Type$(base, offset);
 303             assertEquals(x, $value2$, "weakCompareAndSwapRelease $type$");
 304         }
 305 
 306         {
 307             boolean success = false;
 308             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 309                 success = UNSAFE.weakCompareAndSwap$Type$Volatile(base, offset, $value2$, $value1$);
 310             }
 311             assertEquals(success, true, "weakCompareAndSwapVolatile $type$");
 312             $type$ x = UNSAFE.get$Type$(base, offset);
 313             assertEquals(x, $value1$, "weakCompareAndSwapVolatile $type$");
 314         }
 315 
 316 #end[JdkInternalMisc]
 317         UNSAFE.put$Type$(base, offset, $value2$);
 318 
 319         // Compare set and get
 320         {
 321             $type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$);
 322             assertEquals(o, $value2$, "getAndSet $type$");
 323             $type$ x = UNSAFE.get$Type$(base, offset);
 324             assertEquals(x, $value1$, "getAndSet $type$ value");
 325         }
 326 #end[CAS]
 327 
 328 #if[AtomicAdd]
 329         UNSAFE.put$Type$(base, offset, $value1$);
 330 
 331         // get and add, add and get
 332         {
 333             $type$ o = UNSAFE.getAndAdd$Type$(base, offset, $value2$);
 334             assertEquals(o, $value1$, "getAndAdd $type$");
 335             $type$ x = UNSAFE.get$Type$(base, offset);
 336             assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$");
 337         }
 338 #end[AtomicAdd]
 339     }
 340 
 341 #if[!Object]
 342 #if[!boolean]
 343     static void testAccess(long address) {
 344         // Plain
 345         {
 346             UNSAFE.put$Type$(address, $value1$);
 347             $type$ x = UNSAFE.get$Type$(address);
 348             assertEquals(x, $value1$, "set $type$ value");
 349         }
 350     }
 351 #end[!boolean]
 352 #end[!Object]
 353 }
 354