1 /*
   2  * Copyright (c) 2015, 2016, 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.misc.Unsafe;
  28 import jdk.internal.vm.annotation.ForceInline;
  29 
  30 import java.nio.ByteBuffer;
  31 import java.nio.ReadOnlyBufferException;
  32 import java.util.Objects;
  33 
  34 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  35 
  36 #warn
  37 
  38 final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
  39 
  40     static final int ALIGN = $BoxType$.BYTES - 1;
  41 
  42 #if[floatingPoint]
  43     @ForceInline
  44     static $rawType$ convEndian(boolean big, $type$ v) {
  45         $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
  46         return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
  47     }
  48 
  49     @ForceInline
  50     static $type$ convEndian(boolean big, $rawType$ rv) {
  51         rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
  52         return $Type$.$rawType$BitsTo$Type$(rv);
  53     }
  54 #else[floatingPoint]
  55     @ForceInline
  56     static $type$ convEndian(boolean big, $type$ n) {
  57         return big == BE ? n : $BoxType$.reverseBytes(n);
  58     }
  59 #end[floatingPoint]
  60 
  61 
  62     private static abstract class ByteArrayViewVarHandle extends VarHandle {
  63         final boolean be;
  64 
  65         ByteArrayViewVarHandle(VarForm form, boolean be) {
  66             super(form);
  67             this.be = be;
  68         }
  69     }
  70 
  71     static final class ArrayHandle extends ByteArrayViewVarHandle {
  72 
  73         ArrayHandle(boolean be) {
  74             super(ArrayHandle.FORM, be);
  75         }
  76 
  77         @Override
  78         final MethodType accessModeTypeUncached(AccessMode accessMode) {
  79             return accessMode.at.accessModeType(byte[].class, $type$.class, int.class);
  80         }
  81 
  82         @ForceInline
  83         static int index(byte[] ba, int index) {
  84             return Objects.checkIndex(index, ba.length - ALIGN, null);
  85         }
  86 
  87         @ForceInline
  88         static long address(byte[] ba, int index) {
  89             long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
  90             if ((address & ALIGN) != 0)
  91                 throw newIllegalStateExceptionForMisalignedAccess(index);
  92             return address;
  93         }
  94 
  95         @ForceInline
  96         static $type$ get(ArrayHandle handle, Object oba, int index) {
  97             byte[] ba = (byte[]) oba;
  98 #if[floatingPoint]
  99             $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
 100                     ba,
 101                     ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 102                     handle.be);
 103             return $Type$.$rawType$BitsTo$Type$(rawValue);
 104 #else[floatingPoint]
 105             return UNSAFE.get$Type$Unaligned(
 106                     ba,
 107                     ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 108                     handle.be);
 109 #end[floatingPoint]
 110         }
 111 
 112         @ForceInline
 113         static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
 114             byte[] ba = (byte[]) oba;
 115 #if[floatingPoint]
 116             UNSAFE.put$RawType$Unaligned(
 117                     ba,
 118                     ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 119                     $Type$.$type$ToRaw$RawType$Bits(value),
 120                     handle.be);
 121 #else[floatingPoint]
 122             UNSAFE.put$RawType$Unaligned(
 123                     ba,
 124                     ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
 125                     value,
 126                     handle.be);
 127 #end[floatingPoint]
 128         }
 129 
 130         @ForceInline
 131         static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
 132             byte[] ba = (byte[]) oba;
 133             return convEndian(handle.be,
 134                               UNSAFE.get$RawType$Volatile(
 135                                       ba,
 136                                       address(ba, index(ba, index))));
 137         }
 138 
 139         @ForceInline
 140         static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
 141             byte[] ba = (byte[]) oba;
 142             UNSAFE.put$RawType$Volatile(
 143                     ba,
 144                     address(ba, index(ba, index)),
 145                     convEndian(handle.be, value));
 146         }
 147 
 148         @ForceInline
 149         static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
 150             byte[] ba = (byte[]) oba;
 151             return convEndian(handle.be,
 152                               UNSAFE.get$RawType$Acquire(
 153                                       ba,
 154                                       address(ba, index(ba, index))));
 155         }
 156 
 157         @ForceInline
 158         static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
 159             byte[] ba = (byte[]) oba;
 160             UNSAFE.put$RawType$Release(
 161                     ba,
 162                     address(ba, index(ba, index)),
 163                     convEndian(handle.be, value));
 164         }
 165 
 166         @ForceInline
 167         static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
 168             byte[] ba = (byte[]) oba;
 169             return convEndian(handle.be,
 170                               UNSAFE.get$RawType$Opaque(
 171                                       ba,
 172                                       address(ba, index(ba, index))));
 173         }
 174 
 175         @ForceInline
 176         static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
 177             byte[] ba = (byte[]) oba;
 178             UNSAFE.put$RawType$Opaque(
 179                     ba,
 180                     address(ba, index(ba, index)),
 181                     convEndian(handle.be, value));
 182         }
 183 #if[CAS]
 184 
 185         @ForceInline
 186         static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 187             byte[] ba = (byte[]) oba;
 188             return UNSAFE.compareAndSwap$RawType$(
 189                     ba,
 190                     address(ba, index(ba, index)),
 191                     convEndian(handle.be, expected), convEndian(handle.be, value));
 192         }
 193 
 194         @ForceInline
 195         static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 196             byte[] ba = (byte[]) oba;
 197             return convEndian(handle.be,
 198                               UNSAFE.compareAndExchange$RawType$Volatile(
 199                                       ba,
 200                                       address(ba, index(ba, index)),
 201                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 202         }
 203 
 204         @ForceInline
 205         static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 206             byte[] ba = (byte[]) oba;
 207             return convEndian(handle.be,
 208                               UNSAFE.compareAndExchange$RawType$Acquire(
 209                                       ba,
 210                                       address(ba, index(ba, index)),
 211                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 212         }
 213 
 214         @ForceInline
 215         static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 216             byte[] ba = (byte[]) oba;
 217             return convEndian(handle.be,
 218                               UNSAFE.compareAndExchange$RawType$Release(
 219                                       ba,
 220                                       address(ba, index(ba, index)),
 221                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 222         }
 223 
 224         @ForceInline
 225         static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 226             byte[] ba = (byte[]) oba;
 227             return UNSAFE.weakCompareAndSwap$RawType$(
 228                     ba,
 229                     address(ba, index(ba, index)),
 230                     convEndian(handle.be, expected), convEndian(handle.be, value));
 231         }
 232 
 233         @ForceInline
 234         static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 235             byte[] ba = (byte[]) oba;
 236             // TODO defer to strong form until new Unsafe method is added
 237             return UNSAFE.compareAndSwap$RawType$(
 238                     ba,
 239                     address(ba, index(ba, index)),
 240                     convEndian(handle.be, expected), convEndian(handle.be, value));
 241         }
 242 
 243         @ForceInline
 244         static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 245             byte[] ba = (byte[]) oba;
 246             return UNSAFE.weakCompareAndSwap$RawType$Acquire(
 247                     ba,
 248                     address(ba, index(ba, index)),
 249                     convEndian(handle.be, expected), convEndian(handle.be, value));
 250         }
 251 
 252         @ForceInline
 253         static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
 254             byte[] ba = (byte[]) oba;
 255             return UNSAFE.weakCompareAndSwap$RawType$Release(
 256                     ba,
 257                     address(ba, index(ba, index)),
 258                     convEndian(handle.be, expected), convEndian(handle.be, value));
 259         }
 260 
 261         @ForceInline
 262         static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
 263             byte[] ba = (byte[]) oba;
 264             return convEndian(handle.be,
 265                               UNSAFE.getAndSet$RawType$(
 266                                       ba,
 267                                       address(ba, index(ba, index)),
 268                                       convEndian(handle.be, value)));
 269         }
 270 #end[CAS]
 271 #if[AtomicAdd]
 272 
 273         @ForceInline
 274         static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
 275             byte[] ba = (byte[]) oba;
 276             return convEndian(handle.be,
 277                               UNSAFE.getAndAdd$RawType$(
 278                                       ba,
 279                                       address(ba, index(ba, index)),
 280                                       convEndian(handle.be, value)));
 281         }
 282 
 283         @ForceInline
 284         static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
 285             byte[] ba = (byte[]) oba;
 286             return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
 287                     ba,
 288                     address(ba, index(ba, index)),
 289                     convEndian(handle.be, value))) + value;
 290         }
 291 #end[AtomicAdd]
 292 
 293         static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class);
 294     }
 295 
 296 
 297     static final class ByteBufferHandle extends ByteArrayViewVarHandle {
 298 
 299         ByteBufferHandle(boolean be) {
 300             super(ByteBufferHandle.FORM, be);
 301         }
 302 
 303         @Override
 304         final MethodType accessModeTypeUncached(AccessMode accessMode) {
 305             return accessMode.at.accessModeType(ByteBuffer.class, $type$.class, int.class);
 306         }
 307 
 308         @ForceInline
 309         static int index(ByteBuffer bb, int index) {
 310             return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
 311         }
 312 
 313         @ForceInline
 314         static int indexRO(ByteBuffer bb, int index) {
 315             if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
 316                 throw new ReadOnlyBufferException();
 317             return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
 318         }
 319 
 320         @ForceInline
 321         static long address(ByteBuffer bb, int index) {
 322             long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
 323             if ((address & ALIGN) != 0)
 324                 throw newIllegalStateExceptionForMisalignedAccess(index);
 325             return address;
 326         }
 327 
 328         @ForceInline
 329         static $type$ get(ByteBufferHandle handle, Object obb, int index) {
 330             ByteBuffer bb = (ByteBuffer) obb;
 331 #if[floatingPoint]
 332             $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
 333                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 334                     ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
 335                     handle.be);
 336             return $Type$.$rawType$BitsTo$Type$(rawValue);
 337 #else[floatingPoint]
 338             return UNSAFE.get$Type$Unaligned(
 339                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 340                     ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
 341                     handle.be);
 342 #end[floatingPoint]
 343         }
 344 
 345         @ForceInline
 346         static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 347             ByteBuffer bb = (ByteBuffer) obb;
 348 #if[floatingPoint]
 349             UNSAFE.put$RawType$Unaligned(
 350                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 351                     ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
 352                     $Type$.$type$ToRaw$RawType$Bits(value),
 353                     handle.be);
 354 #else[floatingPoint]
 355             UNSAFE.put$Type$Unaligned(
 356                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 357                     ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
 358                     value,
 359                     handle.be);
 360 #end[floatingPoint]
 361         }
 362 
 363         @ForceInline
 364         static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
 365             ByteBuffer bb = (ByteBuffer) obb;
 366             return convEndian(handle.be,
 367                               UNSAFE.get$RawType$Volatile(
 368                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 369                                       address(bb, index(bb, index))));
 370         }
 371 
 372         @ForceInline
 373         static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 374             ByteBuffer bb = (ByteBuffer) obb;
 375             UNSAFE.put$RawType$Volatile(
 376                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 377                     address(bb, indexRO(bb, index)),
 378                     convEndian(handle.be, value));
 379         }
 380 
 381         @ForceInline
 382         static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
 383             ByteBuffer bb = (ByteBuffer) obb;
 384             return convEndian(handle.be,
 385                               UNSAFE.get$RawType$Acquire(
 386                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 387                                       address(bb, index(bb, index))));
 388         }
 389 
 390         @ForceInline
 391         static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 392             ByteBuffer bb = (ByteBuffer) obb;
 393             UNSAFE.put$RawType$Release(
 394                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 395                     address(bb, indexRO(bb, index)),
 396                     convEndian(handle.be, value));
 397         }
 398 
 399         @ForceInline
 400         static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
 401             ByteBuffer bb = (ByteBuffer) obb;
 402             return convEndian(handle.be,
 403                               UNSAFE.get$RawType$Opaque(
 404                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 405                                       address(bb, index(bb, index))));
 406         }
 407 
 408         @ForceInline
 409         static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 410             ByteBuffer bb = (ByteBuffer) obb;
 411             UNSAFE.put$RawType$Opaque(
 412                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 413                     address(bb, indexRO(bb, index)),
 414                     convEndian(handle.be, value));
 415         }
 416 #if[CAS]
 417 
 418         @ForceInline
 419         static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 420             ByteBuffer bb = (ByteBuffer) obb;
 421             return UNSAFE.compareAndSwap$RawType$(
 422                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 423                     address(bb, indexRO(bb, index)),
 424                     convEndian(handle.be, expected), convEndian(handle.be, value));
 425         }
 426 
 427         @ForceInline
 428         static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 429             ByteBuffer bb = (ByteBuffer) obb;
 430             return convEndian(handle.be,
 431                               UNSAFE.compareAndExchange$RawType$Volatile(
 432                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 433                                       address(bb, indexRO(bb, index)),
 434                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 435         }
 436 
 437         @ForceInline
 438         static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 439             ByteBuffer bb = (ByteBuffer) obb;
 440             return convEndian(handle.be,
 441                               UNSAFE.compareAndExchange$RawType$Acquire(
 442                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 443                                       address(bb, indexRO(bb, index)),
 444                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 445         }
 446 
 447         @ForceInline
 448         static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 449             ByteBuffer bb = (ByteBuffer) obb;
 450             return convEndian(handle.be,
 451                               UNSAFE.compareAndExchange$RawType$Release(
 452                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 453                                       address(bb, indexRO(bb, index)),
 454                                       convEndian(handle.be, expected), convEndian(handle.be, value)));
 455         }
 456 
 457         @ForceInline
 458         static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 459             ByteBuffer bb = (ByteBuffer) obb;
 460             return UNSAFE.weakCompareAndSwap$RawType$(
 461                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 462                     address(bb, indexRO(bb, index)),
 463                     convEndian(handle.be, expected), convEndian(handle.be, value));
 464         }
 465 
 466         @ForceInline
 467         static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 468             ByteBuffer bb = (ByteBuffer) obb;
 469             // TODO defer to strong form until new Unsafe method is added
 470             return UNSAFE.compareAndSwap$RawType$(
 471                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 472                     address(bb, indexRO(bb, index)),
 473                     convEndian(handle.be, expected), convEndian(handle.be, value));
 474         }
 475 
 476         @ForceInline
 477         static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 478             ByteBuffer bb = (ByteBuffer) obb;
 479             return UNSAFE.weakCompareAndSwap$RawType$Acquire(
 480                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 481                     address(bb, indexRO(bb, index)),
 482                     convEndian(handle.be, expected), convEndian(handle.be, value));
 483         }
 484 
 485         @ForceInline
 486         static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
 487             ByteBuffer bb = (ByteBuffer) obb;
 488             return UNSAFE.weakCompareAndSwap$RawType$Release(
 489                     UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 490                     address(bb, indexRO(bb, index)),
 491                     convEndian(handle.be, expected), convEndian(handle.be, value));
 492         }
 493 
 494         @ForceInline
 495         static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 496             ByteBuffer bb = (ByteBuffer) obb;
 497             return convEndian(handle.be,
 498                               UNSAFE.getAndSet$RawType$(
 499                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 500                                       address(bb, indexRO(bb, index)),
 501                                       convEndian(handle.be, value)));
 502         }
 503 #end[CAS]
 504 #if[AtomicAdd]
 505 
 506         @ForceInline
 507         static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 508             ByteBuffer bb = (ByteBuffer) obb;
 509             return convEndian(handle.be,
 510                               UNSAFE.getAndAdd$RawType$(
 511                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 512                                       address(bb, indexRO(bb, index)),
 513                                       convEndian(handle.be, value)));
 514         }
 515 
 516         @ForceInline
 517         static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
 518             ByteBuffer bb = (ByteBuffer) obb;
 519             return convEndian(handle.be,
 520                               UNSAFE.getAndAdd$RawType$(
 521                                       UNSAFE.getObject(bb, BYTE_BUFFER_HB),
 522                                       address(bb, indexRO(bb, index)),
 523                                       convEndian(handle.be, value))) + value;
 524         }
 525 #end[AtomicAdd]
 526 
 527         static final VarForm FORM = new VarForm(ByteBufferHandle.class, ByteBuffer.class, $type$.class, int.class);
 528     }
 529 }