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