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