1 /*
   2  * Copyright (c) 2000, 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 
  26 #warn This file is preprocessed before being compiled
  27 
  28 package java.nio;
  29 
  30 import java.io.FileDescriptor;
  31 import jdk.internal.misc.Unsafe;
  32 import jdk.internal.misc.VM;
  33 import jdk.internal.ref.Cleaner;
  34 import sun.nio.ch.DirectBuffer;
  35 
  36 
  37 class Direct$Type$Buffer$RW$$BO$
  38 #if[rw]
  39     extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
  40 #else[rw]
  41     extends Direct$Type$Buffer$BO$
  42 #end[rw]
  43     implements DirectBuffer
  44 {
  45 
  46 #if[rw]
  47 
  48     // Cached unsafe-access object
  49     protected static final Unsafe unsafe = Bits.unsafe();
  50 
  51     // Cached array base offset
  52     private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
  53 
  54     // Cached unaligned-access capability
  55     protected static final boolean unaligned = Bits.unaligned();
  56 
  57     // Base address, used in all indexing calculations
  58     // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
  59     //    protected long address;
  60 
  61     // An object attached to this buffer. If this buffer is a view of another
  62     // buffer then we use this field to keep a reference to that buffer to
  63     // ensure that its memory isn't freed before we are done with it.
  64     private final Object att;
  65 
  66     public Object attachment() {
  67         return att;
  68     }
  69 
  70 #if[byte]
  71 
  72     private static class Deallocator
  73         implements Runnable
  74     {
  75 
  76         private static Unsafe unsafe = Unsafe.getUnsafe();
  77 
  78         private long address;
  79         private long size;
  80         private int capacity;
  81 
  82         private Deallocator(long address, long size, int capacity) {
  83             assert (address != 0);
  84             this.address = address;
  85             this.size = size;
  86             this.capacity = capacity;
  87         }
  88 
  89         public void run() {
  90             if (address == 0) {
  91                 // Paranoia
  92                 return;
  93             }
  94             unsafe.freeMemory(address);
  95             address = 0;
  96             Bits.unreserveMemory(size, capacity);
  97         }
  98 
  99     }
 100 
 101     private final Cleaner cleaner;
 102 
 103     public Cleaner cleaner() { return cleaner; }
 104 
 105 #else[byte]
 106 
 107     public Cleaner cleaner() { return null; }
 108 
 109 #end[byte]
 110 
 111 #end[rw]
 112 
 113 #if[byte]
 114 
 115     // Primary constructor
 116     //
 117     Direct$Type$Buffer$RW$(int cap) {                   // package-private
 118 #if[rw]
 119         super(-1, 0, cap, cap);
 120         boolean pa = VM.isDirectMemoryPageAligned();
 121         int ps = Bits.pageSize();
 122         long size = Math.max(1L, (long)cap + (pa ? ps : 0));
 123         Bits.reserveMemory(size, cap);
 124 
 125         long base = 0;
 126         try {
 127             base = unsafe.allocateMemory(size);
 128         } catch (OutOfMemoryError x) {
 129             Bits.unreserveMemory(size, cap);
 130             throw x;
 131         }
 132         unsafe.setMemory(base, size, (byte) 0);
 133         if (pa && (base % ps != 0)) {
 134             // Round up to page boundary
 135             address = base + ps - (base & (ps - 1));
 136         } else {
 137             address = base;
 138         }
 139         cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
 140         att = null;
 141 #else[rw]
 142         super(cap);
 143 #end[rw]
 144     }
 145 
 146 #if[rw]
 147 
 148     // Invoked to construct a direct ByteBuffer referring to the block of
 149     // memory. A given arbitrary object may also be attached to the buffer.
 150     //
 151     Direct$Type$Buffer(long addr, int cap, Object ob) {
 152         super(-1, 0, cap, cap);
 153         address = addr;
 154         cleaner = null;
 155         att = ob;
 156     }
 157 
 158 
 159     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
 160     //
 161     private Direct$Type$Buffer(long addr, int cap) {
 162         super(-1, 0, cap, cap);
 163         address = addr;
 164         cleaner = null;
 165         att = null;
 166     }
 167 
 168 #end[rw]
 169 
 170     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
 171     //
 172     protected Direct$Type$Buffer$RW$(int cap, long addr,
 173                                      FileDescriptor fd,
 174                                      Runnable unmapper)
 175     {
 176 #if[rw]
 177         super(-1, 0, cap, cap, fd);
 178         address = addr;
 179         cleaner = Cleaner.create(this, unmapper);
 180         att = null;
 181 #else[rw]
 182         super(cap, addr, fd, unmapper);
 183 #end[rw]
 184     }
 185 
 186 #end[byte]
 187 
 188     // For duplicates and slices
 189     //
 190     Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
 191                                int mark, int pos, int lim, int cap,
 192                                int off)
 193     {
 194 #if[rw]
 195         super(mark, pos, lim, cap);
 196         address = db.address() + off;
 197 #if[byte]
 198         cleaner = null;
 199 #end[byte]
 200         att = db;
 201 #else[rw]
 202         super(db, mark, pos, lim, cap, off);
 203 #end[rw]
 204     }
 205 
 206     public $Type$Buffer slice() {
 207         int pos = this.position();
 208         int lim = this.limit();
 209         assert (pos <= lim);
 210         int rem = (pos <= lim ? lim - pos : 0);
 211         int off = (pos << $LG_BYTES_PER_VALUE$);
 212         assert (off >= 0);
 213         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
 214     }
 215 
 216     public $Type$Buffer duplicate() {
 217         return new Direct$Type$Buffer$RW$$BO$(this,
 218                                               this.markValue(),
 219                                               this.position(),
 220                                               this.limit(),
 221                                               this.capacity(),
 222                                               0);
 223     }
 224 
 225     public $Type$Buffer asReadOnlyBuffer() {
 226 #if[rw]
 227         return new Direct$Type$BufferR$BO$(this,
 228                                            this.markValue(),
 229                                            this.position(),
 230                                            this.limit(),
 231                                            this.capacity(),
 232                                            0);
 233 #else[rw]
 234         return duplicate();
 235 #end[rw]
 236     }
 237 
 238 #if[rw]
 239 
 240     public long address() {
 241         return address;
 242     }
 243 
 244     private long ix(int i) {
 245         return address + ((long)i << $LG_BYTES_PER_VALUE$);
 246     }
 247 
 248     public $type$ get() {
 249         return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
 250     }
 251 
 252     public $type$ get(int i) {
 253         return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
 254     }
 255 
 256 #if[streamableType]
 257     $type$ getUnchecked(int i) {
 258         return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i))));
 259     }
 260 #end[streamableType]
 261 
 262     public $Type$Buffer get($type$[] dst, int offset, int length) {
 263 #if[rw]
 264         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
 265             checkBounds(offset, length, dst.length);
 266             int pos = position();
 267             int lim = limit();
 268             assert (pos <= lim);
 269             int rem = (pos <= lim ? lim - pos : 0);
 270             if (length > rem)
 271                 throw new BufferUnderflowException();
 272 
 273             long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
 274 #if[!byte]
 275             if (order() != ByteOrder.nativeOrder())
 276                 unsafe.copySwapMemory(null,
 277                                       ix(pos),
 278                                       dst,
 279                                       dstOffset,
 280                                       (long)length << $LG_BYTES_PER_VALUE$,
 281                                       (long)1 << $LG_BYTES_PER_VALUE$);
 282             else
 283 #end[!byte]
 284                 unsafe.copyMemory(null,
 285                                   ix(pos),
 286                                   dst,
 287                                   dstOffset,
 288                                   (long)length << $LG_BYTES_PER_VALUE$);
 289             position(pos + length);
 290         } else {
 291             super.get(dst, offset, length);
 292         }
 293         return this;
 294 #else[rw]
 295         throw new ReadOnlyBufferException();
 296 #end[rw]
 297     }
 298 
 299 #end[rw]
 300 
 301     public $Type$Buffer put($type$ x) {
 302 #if[rw]
 303         unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
 304         return this;
 305 #else[rw]
 306         throw new ReadOnlyBufferException();
 307 #end[rw]
 308     }
 309 
 310     public $Type$Buffer put(int i, $type$ x) {
 311 #if[rw]
 312         unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
 313         return this;
 314 #else[rw]
 315         throw new ReadOnlyBufferException();
 316 #end[rw]
 317     }
 318 
 319     public $Type$Buffer put($Type$Buffer src) {
 320 #if[rw]
 321         if (src instanceof Direct$Type$Buffer$BO$) {
 322             if (src == this)
 323                 throw createSameBufferException();
 324             Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
 325 
 326             int spos = sb.position();
 327             int slim = sb.limit();
 328             assert (spos <= slim);
 329             int srem = (spos <= slim ? slim - spos : 0);
 330 
 331             int pos = position();
 332             int lim = limit();
 333             assert (pos <= lim);
 334             int rem = (pos <= lim ? lim - pos : 0);
 335 
 336             if (srem > rem)
 337                 throw new BufferOverflowException();
 338             unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
 339             sb.position(spos + srem);
 340             position(pos + srem);
 341         } else if (src.hb != null) {
 342 
 343             int spos = src.position();
 344             int slim = src.limit();
 345             assert (spos <= slim);
 346             int srem = (spos <= slim ? slim - spos : 0);
 347 
 348             put(src.hb, src.offset + spos, srem);
 349             src.position(spos + srem);
 350 
 351         } else {
 352             super.put(src);
 353         }
 354         return this;
 355 #else[rw]
 356         throw new ReadOnlyBufferException();
 357 #end[rw]
 358     }
 359 
 360     public $Type$Buffer put($type$[] src, int offset, int length) {
 361 #if[rw]
 362         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
 363             checkBounds(offset, length, src.length);
 364             int pos = position();
 365             int lim = limit();
 366             assert (pos <= lim);
 367             int rem = (pos <= lim ? lim - pos : 0);
 368             if (length > rem)
 369                 throw new BufferOverflowException();
 370 
 371             long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
 372 #if[!byte]
 373             if (order() != ByteOrder.nativeOrder())
 374                 unsafe.copySwapMemory(src,
 375                                       srcOffset,
 376                                       null,
 377                                       ix(pos),
 378                                       (long)length << $LG_BYTES_PER_VALUE$,
 379                                       (long)1 << $LG_BYTES_PER_VALUE$);
 380             else
 381 #end[!byte]
 382                 unsafe.copyMemory(src,
 383                                   srcOffset,
 384                                   null,
 385                                   ix(pos),
 386                                   (long)length << $LG_BYTES_PER_VALUE$);
 387             position(pos + length);
 388         } else {
 389             super.put(src, offset, length);
 390         }
 391         return this;
 392 #else[rw]
 393         throw new ReadOnlyBufferException();
 394 #end[rw]
 395     }
 396 
 397     public $Type$Buffer compact() {
 398 #if[rw]
 399         int pos = position();
 400         int lim = limit();
 401         assert (pos <= lim);
 402         int rem = (pos <= lim ? lim - pos : 0);
 403 
 404         unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
 405         position(rem);
 406         limit(capacity());
 407         discardMark();
 408         return this;
 409 #else[rw]
 410         throw new ReadOnlyBufferException();
 411 #end[rw]
 412     }
 413 
 414     public boolean isDirect() {
 415         return true;
 416     }
 417 
 418     public boolean isReadOnly() {
 419         return {#if[rw]?false:true};
 420     }
 421 
 422 
 423 #if[char]
 424 
 425     public String toString(int start, int end) {
 426         if ((end > limit()) || (start > end))
 427             throw new IndexOutOfBoundsException();
 428         try {
 429             int len = end - start;
 430             char[] ca = new char[len];
 431             CharBuffer cb = CharBuffer.wrap(ca);
 432             CharBuffer db = this.duplicate();
 433             db.position(start);
 434             db.limit(end);
 435             cb.put(db);
 436             return new String(ca);
 437         } catch (StringIndexOutOfBoundsException x) {
 438             throw new IndexOutOfBoundsException();
 439         }
 440     }
 441 
 442 
 443     // --- Methods to support CharSequence ---
 444 
 445     public CharBuffer subSequence(int start, int end) {
 446         int pos = position();
 447         int lim = limit();
 448         assert (pos <= lim);
 449         pos = (pos <= lim ? pos : lim);
 450         int len = lim - pos;
 451 
 452         if ((start < 0) || (end > len) || (start > end))
 453             throw new IndexOutOfBoundsException();
 454         return new DirectCharBuffer$RW$$BO$(this,
 455                                             -1,
 456                                             pos + start,
 457                                             pos + end,
 458                                             capacity(),
 459                                             offset);
 460     }
 461 
 462 #end[char]
 463 
 464 
 465 
 466 #if[!byte]
 467 
 468     public ByteOrder order() {
 469 #if[boS]
 470         return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
 471                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
 472 #end[boS]
 473 #if[boU]
 474         return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
 475                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
 476 #end[boU]
 477     }
 478 
 479 #end[!byte]
 480 
 481 
 482 
 483 #if[byte]
 484 
 485     byte _get(int i) {                          // package-private
 486         return unsafe.getByte(address + i);
 487     }
 488 
 489     void _put(int i, byte b) {                  // package-private
 490 #if[rw]
 491         unsafe.putByte(address + i, b);
 492 #else[rw]
 493         throw new ReadOnlyBufferException();
 494 #end[rw]
 495     }
 496 
 497     // #BIN
 498     //
 499     // Binary-data access methods  for short, char, int, long, float,
 500     // and double will be inserted here
 501 
 502 #end[byte]
 503 
 504 }