1 /*
   2  * Copyright (c) 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.lang.invoke;
  26 
  27 import jdk.internal.access.foreign.MemoryAddressProxy;
  28 import jdk.internal.vm.annotation.ForceInline;
  29 
  30 import java.util.Objects;
  31 
  32 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  33 
  34 #warn
  35 
  36 final class VarHandleMemoryAddressAs$Type$s {
  37 
  38     static final boolean BE = UNSAFE.isBigEndian();
  39 
  40 #if[floatingPoint]
  41     @ForceInline
  42     static $rawType$ convEndian(boolean big, $type$ v) {
  43         $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
  44         return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
  45     }
  46 
  47     @ForceInline
  48     static $type$ convEndian(boolean big, $rawType$ rv) {
  49         rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
  50         return $Type$.$rawType$BitsTo$Type$(rv);
  51     }
  52 #else[floatingPoint]
  53 #if[byte]
  54     @ForceInline
  55     static $type$ convEndian(boolean big, $type$ n) {
  56         return n;
  57     }
  58 #else[byte]
  59     @ForceInline
  60     static $type$ convEndian(boolean big, $type$ n) {
  61         return big == BE ? n : $BoxType$.reverseBytes(n);
  62     }
  63 #end[byte]
  64 #end[floatingPoint]
  65 
  66     @ForceInline
  67     static MemoryAddressProxy checkAddress(Object obb, long offset, long length, boolean ro) {
  68         MemoryAddressProxy oo = (MemoryAddressProxy)Objects.requireNonNull(obb);
  69         oo.checkAccess(offset, length, ro);
  70         return oo;
  71     }
  72     
  73     @ForceInline
  74     static long offset(MemoryAddressProxy bb, long offset, long alignment) {
  75         long address = bb.unsafeGetOffset() + offset;
  76         if ((address & alignment) != 0) {
  77             throw VarHandleMemoryAddressBase.newIllegalStateExceptionForMisalignedAccess(address);
  78         }
  79         return address;
  80     }
  81     
  82     @ForceInline
  83     static $type$ get0(VarHandleMemoryAddressBase handle, Object obb, long base) {
  84         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
  85 #if[floatingPoint]
  86         $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
  87                 bb.unsafeGetBase(),
  88                 offset(bb, base, handle.alignment),
  89                 handle.be);
  90         return $Type$.$rawType$BitsTo$Type$(rawValue);
  91 #else[floatingPoint]
  92 #if[byte]
  93         return UNSAFE.get$Type$(
  94                 bb.unsafeGetBase(),
  95                 offset(bb, base, handle.alignment));
  96 #else[byte]
  97         return UNSAFE.get$Type$Unaligned(
  98                 bb.unsafeGetBase(),
  99                 offset(bb, base, handle.alignment),
 100                 handle.be);
 101 #end[byte]
 102 #end[floatingPoint]
 103     }
 104 
 105     @ForceInline
 106     static void set0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 107         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 108 #if[floatingPoint]
 109         UNSAFE.put$RawType$Unaligned(
 110                 bb.unsafeGetBase(),
 111                 offset(bb, base, handle.alignment),
 112                 $Type$.$type$ToRaw$RawType$Bits(value),
 113                 handle.be);
 114 #else[floatingPoint]
 115 #if[byte]
 116         UNSAFE.put$Type$(
 117                 bb.unsafeGetBase(),
 118                 offset(bb, base, handle.alignment),
 119                 value);
 120 #else[byte]
 121         UNSAFE.put$Type$Unaligned(
 122                 bb.unsafeGetBase(),
 123                 offset(bb, base, handle.alignment),
 124                 value,
 125                 handle.be);
 126 #end[byte]
 127 #end[floatingPoint]
 128     }
 129 
 130     @ForceInline
 131     static $type$ getVolatile0(VarHandleMemoryAddressBase handle, Object obb, long base) {
 132         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
 133         return convEndian(handle.be,
 134                           UNSAFE.get$RawType$Volatile(
 135                                   bb.unsafeGetBase(),
 136                                   offset(bb, base, handle.alignment)));
 137     }
 138 
 139     @ForceInline
 140     static void setVolatile0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 141         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 142         UNSAFE.put$RawType$Volatile(
 143                 bb.unsafeGetBase(),
 144                 offset(bb, base, handle.alignment),
 145                 convEndian(handle.be, value));
 146     }
 147 
 148     @ForceInline
 149     static $type$ getAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base) {
 150         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
 151         return convEndian(handle.be,
 152                           UNSAFE.get$RawType$Acquire(
 153                                   bb.unsafeGetBase(),
 154                                   offset(bb, base, handle.alignment)));
 155     }
 156 
 157     @ForceInline
 158     static void setRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 159         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 160         UNSAFE.put$RawType$Release(
 161                 bb.unsafeGetBase(),
 162                 offset(bb, base, handle.alignment),
 163                 convEndian(handle.be, value));
 164     }
 165 
 166     @ForceInline
 167     static $type$ getOpaque0(VarHandleMemoryAddressBase handle, Object obb, long base) {
 168         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
 169         return convEndian(handle.be,
 170                           UNSAFE.get$RawType$Opaque(
 171                                   bb.unsafeGetBase(),
 172                                   offset(bb, base, handle.alignment)));
 173     }
 174 
 175     @ForceInline
 176     static void setOpaque0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 177         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 178         UNSAFE.put$RawType$Opaque(
 179                 bb.unsafeGetBase(),
 180                 offset(bb, base, handle.alignment),
 181                 convEndian(handle.be, value));
 182     }
 183 #if[CAS]
 184 
 185     @ForceInline
 186     static boolean compareAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 187         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 188         return UNSAFE.compareAndSet$RawType$(
 189                 bb.unsafeGetBase(),
 190                 offset(bb, base, handle.alignment),
 191                 convEndian(handle.be, expected), convEndian(handle.be, value));
 192     }
 193 
 194     @ForceInline
 195     static $type$ compareAndExchange0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 196         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 197         return convEndian(handle.be,
 198                           UNSAFE.compareAndExchange$RawType$(
 199                                   bb.unsafeGetBase(),
 200                                   offset(bb, base, handle.alignment),
 201                                   convEndian(handle.be, expected), convEndian(handle.be, value)));
 202     }
 203 
 204     @ForceInline
 205     static $type$ compareAndExchangeAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 206         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 207         return convEndian(handle.be,
 208                           UNSAFE.compareAndExchange$RawType$Acquire(
 209                                   bb.unsafeGetBase(),
 210                                   offset(bb, base, handle.alignment),
 211                                   convEndian(handle.be, expected), convEndian(handle.be, value)));
 212     }
 213 
 214     @ForceInline
 215     static $type$ compareAndExchangeRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 216         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 217         return convEndian(handle.be,
 218                           UNSAFE.compareAndExchange$RawType$Release(
 219                                   bb.unsafeGetBase(),
 220                                   offset(bb, base, handle.alignment),
 221                                   convEndian(handle.be, expected), convEndian(handle.be, value)));
 222     }
 223 
 224     @ForceInline
 225     static boolean weakCompareAndSetPlain0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 226         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 227         return UNSAFE.weakCompareAndSet$RawType$Plain(
 228                 bb.unsafeGetBase(),
 229                 offset(bb, base, handle.alignment),
 230                 convEndian(handle.be, expected), convEndian(handle.be, value));
 231     }
 232 
 233     @ForceInline
 234     static boolean weakCompareAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 235         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 236         return UNSAFE.weakCompareAndSet$RawType$(
 237                 bb.unsafeGetBase(),
 238                 offset(bb, base, handle.alignment),
 239                 convEndian(handle.be, expected), convEndian(handle.be, value));
 240     }
 241 
 242     @ForceInline
 243     static boolean weakCompareAndSetAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 244         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 245         return UNSAFE.weakCompareAndSet$RawType$Acquire(
 246                 bb.unsafeGetBase(),
 247                 offset(bb, base, handle.alignment),
 248                 convEndian(handle.be, expected), convEndian(handle.be, value));
 249     }
 250 
 251     @ForceInline
 252     static boolean weakCompareAndSetRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ expected, $type$ value) {
 253         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 254         return UNSAFE.weakCompareAndSet$RawType$Release(
 255                 bb.unsafeGetBase(),
 256                 offset(bb, base, handle.alignment),
 257                 convEndian(handle.be, expected), convEndian(handle.be, value));
 258     }
 259 
 260     @ForceInline
 261     static $type$ getAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 262         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 263         return convEndian(handle.be,
 264                           UNSAFE.getAndSet$RawType$(
 265                                   bb.unsafeGetBase(),
 266                                   offset(bb, base, handle.alignment),
 267                                   convEndian(handle.be, value)));
 268     }
 269 
 270     @ForceInline
 271     static $type$ getAndSetAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 272         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 273         return convEndian(handle.be,
 274                           UNSAFE.getAndSet$RawType$Acquire(
 275                                   bb.unsafeGetBase(),
 276                                   offset(bb, base, handle.alignment),
 277                                   convEndian(handle.be, value)));
 278     }
 279 
 280     @ForceInline
 281     static $type$ getAndSetRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 282         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 283         return convEndian(handle.be,
 284                           UNSAFE.getAndSet$RawType$Release(
 285                                   bb.unsafeGetBase(),
 286                                   offset(bb, base, handle.alignment),
 287                                   convEndian(handle.be, value)));
 288     }
 289 #end[CAS]
 290 #if[AtomicAdd]
 291 
 292     @ForceInline
 293     static $type$ getAndAdd0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ delta) {
 294         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 295         if (handle.be == BE) {
 296             return UNSAFE.getAndAdd$RawType$(
 297                     bb.unsafeGetBase(),
 298                     offset(bb, base, handle.alignment),
 299                     delta);
 300         } else {
 301             return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignment), delta);
 302         }
 303     }
 304 
 305     @ForceInline
 306     static $type$ getAndAddAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ delta) {
 307         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 308         if (handle.be == BE) {
 309             return UNSAFE.getAndAdd$RawType$Acquire(
 310                     bb.unsafeGetBase(),
 311                     offset(bb, base, handle.alignment),
 312                     delta);
 313         } else {
 314             return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignment), delta);
 315         }
 316     }
 317 
 318     @ForceInline
 319     static $type$ getAndAddRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ delta) {
 320         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 321         if (handle.be == BE) {
 322             return UNSAFE.getAndAdd$RawType$Release(
 323                     bb.unsafeGetBase(),
 324                     offset(bb, base, handle.alignment),
 325                     delta);
 326         } else {
 327             return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignment), delta);
 328         }
 329     }
 330 
 331     @ForceInline
 332     static $type$ getAndAddConvEndianWithCAS(MemoryAddressProxy bb, long offset, $type$ delta) {
 333         $type$ nativeExpectedValue, expectedValue;
 334         Object base = bb.unsafeGetBase();
 335         do {
 336             nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
 337             expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
 338         } while (!UNSAFE.weakCompareAndSet$RawType$(base, offset,
 339                 nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
 340         return expectedValue;
 341     }
 342 #end[AtomicAdd]
 343 #if[Bitwise]
 344 
 345     @ForceInline
 346     static $type$ getAndBitwiseOr0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 347         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 348         if (handle.be == BE) {
 349             return UNSAFE.getAndBitwiseOr$RawType$(
 350                     bb.unsafeGetBase(),
 351                     offset(bb, base, handle.alignment),
 352                     value);
 353         } else {
 354             return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 355         }
 356     }
 357 
 358     @ForceInline
 359     static $type$ getAndBitwiseOrRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 360         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 361         if (handle.be == BE) {
 362             return UNSAFE.getAndBitwiseOr$RawType$Release(
 363                     bb.unsafeGetBase(),
 364                     offset(bb, base, handle.alignment),
 365                     value);
 366         } else {
 367             return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 368         }
 369     }
 370 
 371     @ForceInline
 372     static $type$ getAndBitwiseOrAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 373         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 374         if (handle.be == BE) {
 375             return UNSAFE.getAndBitwiseOr$RawType$Acquire(
 376                     bb.unsafeGetBase(),
 377                     offset(bb, base, handle.alignment),
 378                     value);
 379         } else {
 380             return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 381         }
 382     }
 383 
 384     @ForceInline
 385     static $type$ getAndBitwiseOrConvEndianWithCAS(MemoryAddressProxy bb, long offset, $type$ value) {
 386         $type$ nativeExpectedValue, expectedValue;
 387         Object base = bb.unsafeGetBase();
 388         do {
 389             nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
 390             expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
 391         } while (!UNSAFE.weakCompareAndSet$RawType$(base, offset,
 392                 nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value)));
 393         return expectedValue;
 394     }
 395 
 396     @ForceInline
 397     static $type$ getAndBitwiseAnd0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 398         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 399         if (handle.be == BE) {
 400             return UNSAFE.getAndBitwiseAnd$RawType$(
 401                     bb.unsafeGetBase(),
 402                     offset(bb, base, handle.alignment),
 403                     value);
 404         } else {
 405             return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 406         }
 407     }
 408 
 409     @ForceInline
 410     static $type$ getAndBitwiseAndRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 411         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 412         if (handle.be == BE) {
 413             return UNSAFE.getAndBitwiseAnd$RawType$Release(
 414                     bb.unsafeGetBase(),
 415                     offset(bb, base, handle.alignment),
 416                     value);
 417         } else {
 418             return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 419         }
 420     }
 421 
 422     @ForceInline
 423     static $type$ getAndBitwiseAndAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 424         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 425         if (handle.be == BE) {
 426             return UNSAFE.getAndBitwiseAnd$RawType$Acquire(
 427                     bb.unsafeGetBase(),
 428                     offset(bb, base, handle.alignment),
 429                     value);
 430         } else {
 431             return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 432         }
 433     }
 434 
 435     @ForceInline
 436     static $type$ getAndBitwiseAndConvEndianWithCAS(MemoryAddressProxy bb, long offset, $type$ value) {
 437         $type$ nativeExpectedValue, expectedValue;
 438         Object base = bb.unsafeGetBase();
 439         do {
 440             nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
 441             expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
 442         } while (!UNSAFE.weakCompareAndSet$RawType$(base, offset,
 443                 nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value)));
 444         return expectedValue;
 445     }
 446 
 447 
 448     @ForceInline
 449     static $type$ getAndBitwiseXor0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 450         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 451         if (handle.be == BE) {
 452             return UNSAFE.getAndBitwiseXor$RawType$(
 453                     bb.unsafeGetBase(),
 454                     offset(bb, base, handle.alignment),
 455                     value);
 456         } else {
 457             return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 458         }
 459     }
 460 
 461     @ForceInline
 462     static $type$ getAndBitwiseXorRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 463         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 464         if (handle.be == BE) {
 465             return UNSAFE.getAndBitwiseXor$RawType$Release(
 466                     bb.unsafeGetBase(),
 467                     offset(bb, base, handle.alignment),
 468                     value);
 469         } else {
 470             return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 471         }
 472     }
 473 
 474     @ForceInline
 475     static $type$ getAndBitwiseXorAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, $type$ value) {
 476         MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
 477         if (handle.be == BE) {
 478             return UNSAFE.getAndBitwiseXor$RawType$Acquire(
 479                     bb.unsafeGetBase(),
 480                     offset(bb, base, handle.alignment),
 481                     value);
 482         } else {
 483             return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignment), value);
 484         }
 485     }
 486 
 487     @ForceInline
 488     static $type$ getAndBitwiseXorConvEndianWithCAS(MemoryAddressProxy bb, long offset, $type$ value) {
 489         $type$ nativeExpectedValue, expectedValue;
 490         Object base = bb.unsafeGetBase();
 491         do {
 492             nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset);
 493             expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
 494         } while (!UNSAFE.weakCompareAndSet$RawType$(base, offset,
 495                 nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value)));
 496         return expectedValue;
 497     }
 498 #end[Bitwise]
 499 }