1 /*
   2  * Copyright (c) 2000, 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 
  26 #warn This file is preprocessed before being compiled
  27 
  28 package java.nio;
  29 
  30 import java.io.FileDescriptor;
  31 import java.lang.ref.Reference;
  32 import java.util.Objects;
  33 import jdk.internal.misc.VM;
  34 import jdk.internal.ref.Cleaner;
  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 array base offset
  50     private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
  51 
  52     // Cached unaligned-access capability
  53     protected static final boolean UNALIGNED = Bits.unaligned();
  54 
  55     // Base address, used in all indexing calculations
  56     // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
  57     //    protected long address;
  58 
  59     // An object attached to this buffer. If this buffer is a view of another
  60     // buffer then we use this field to keep a reference to that buffer to
  61     // ensure that its memory isn't freed before we are done with it.
  62     private final Object att;
  63 
  64     public Object attachment() {
  65         return att;
  66     }
  67 
  68 #if[byte]
  69 
  70     private static class Deallocator
  71         implements Runnable
  72     {
  73 
  74         private long address;
  75         private long size;
  76         private int capacity;
  77 
  78         private Deallocator(long address, long size, int capacity) {
  79             assert (address != 0);
  80             this.address = address;
  81             this.size = size;
  82             this.capacity = capacity;
  83         }
  84 
  85         public void run() {
  86             if (address == 0) {
  87                 // Paranoia
  88                 return;
  89             }
  90             UNSAFE.freeMemory(address);
  91             address = 0;
  92             Bits.unreserveMemory(size, capacity);
  93         }
  94 
  95     }
  96 
  97     private final Cleaner cleaner;
  98 
  99     public Cleaner cleaner() { return cleaner; }
 100 
 101 #else[byte]
 102 
 103     public Cleaner cleaner() { return null; }
 104 
 105 #end[byte]
 106 
 107 #end[rw]
 108 
 109 #if[byte]
 110 
 111     // Primary constructor
 112     //
 113     Direct$Type$Buffer$RW$(int cap) {                   // package-private
 114 #if[rw]
 115         super(-1, 0, cap, cap);
 116         boolean pa = VM.isDirectMemoryPageAligned();
 117         int ps = Bits.pageSize();
 118         long size = Math.max(1L, (long)cap + (pa ? ps : 0));
 119         Bits.reserveMemory(size, cap);
 120 
 121         long base = 0;
 122         try {
 123             base = UNSAFE.allocateMemory(size);
 124         } catch (OutOfMemoryError x) {
 125             Bits.unreserveMemory(size, cap);
 126             throw x;
 127         }
 128         UNSAFE.setMemory(base, size, (byte) 0);
 129         if (pa && (base % ps != 0)) {
 130             // Round up to page boundary
 131             address = base + ps - (base & (ps - 1));
 132         } else {
 133             address = base;
 134         }
 135         cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
 136         att = null;
 137 #else[rw]
 138         super(cap);
 139         this.isReadOnly = true;
 140 #end[rw]
 141     }
 142 
 143 #if[rw]
 144 
 145     // Invoked to construct a direct ByteBuffer referring to the block of
 146     // memory. A given arbitrary object may also be attached to the buffer.
 147     //
 148     Direct$Type$Buffer(long addr, int cap, Object ob) {
 149         super(-1, 0, cap, cap);
 150         address = addr;
 151         cleaner = null;
 152         att = ob;
 153     }
 154 
 155 
 156     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
 157     //
 158     private Direct$Type$Buffer(long addr, int cap) {
 159         super(-1, 0, cap, cap);
 160         address = addr;
 161         cleaner = null;
 162         att = null;
 163     }
 164 
 165 #end[rw]
 166 
 167     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
 168     //
 169     protected Direct$Type$Buffer$RW$(int cap, long addr,
 170                                      FileDescriptor fd,
 171                                      Runnable unmapper)
 172     {
 173 #if[rw]
 174         super(-1, 0, cap, cap, fd);
 175         address = addr;
 176         cleaner = Cleaner.create(this, unmapper);
 177         att = null;
 178 #else[rw]
 179         super(cap, addr, fd, unmapper);
 180         this.isReadOnly = true;
 181 #end[rw]
 182     }
 183 
 184 #end[byte]
 185 
 186     // For duplicates and slices
 187     //
 188     Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
 189                                int mark, int pos, int lim, int cap,
 190                                int off)
 191     {
 192 #if[rw]
 193         super(mark, pos, lim, cap);
 194         address = db.address() + off;
 195 #if[byte]
 196         cleaner = null;
 197 #end[byte]
 198         Object attachment = db.attachment();
 199         att = (attachment == null ? db : attachment);
 200 #else[rw]
 201         super(db, mark, pos, lim, cap, off);
 202         this.isReadOnly = true;
 203 #end[rw]
 204     }
 205 
 206     @Override
 207     Object base() {
 208         return null;
 209     }
 210 
 211     public $Type$Buffer slice() {
 212         int pos = this.position();
 213         int lim = this.limit();
 214         assert (pos <= lim);
 215         int rem = (pos <= lim ? lim - pos : 0);
 216         int off = (pos << $LG_BYTES_PER_VALUE$);
 217         assert (off >= 0);
 218         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
 219     }
 220 
 221 #if[byte]
 222     public $Type$Buffer slice(int pos, int lim) {
 223         assert (pos >= 0);
 224         assert (pos <= lim);
 225         int rem = lim - pos;
 226         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
 227     }
 228 #end[byte]
 229 
 230     public $Type$Buffer duplicate() {
 231         return new Direct$Type$Buffer$RW$$BO$(this,
 232                                               this.markValue(),
 233                                               this.position(),
 234                                               this.limit(),
 235                                               this.capacity(),
 236                                               0);
 237     }
 238 
 239     public $Type$Buffer asReadOnlyBuffer() {
 240 #if[rw]
 241         return new Direct$Type$BufferR$BO$(this,
 242                                            this.markValue(),
 243                                            this.position(),
 244                                            this.limit(),
 245                                            this.capacity(),
 246                                            0);
 247 #else[rw]
 248         return duplicate();
 249 #end[rw]
 250     }
 251 
 252 #if[rw]
 253 
 254     public long address() {
 255         return address;
 256     }
 257 
 258     private long ix(int i) {
 259         return address + ((long)i << $LG_BYTES_PER_VALUE$);
 260     }
 261 
 262     public $type$ get() {
 263         try {
 264             return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
 265         } finally {
 266             Reference.reachabilityFence(this);
 267         }
 268     }
 269 
 270     public $type$ get(int i) {
 271         try {
 272             return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
 273         } finally {
 274             Reference.reachabilityFence(this);
 275         }
 276     }
 277 
 278 #if[streamableType]
 279     $type$ getUnchecked(int i) {
 280         try {
 281             return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
 282         } finally {
 283             Reference.reachabilityFence(this);
 284         }
 285     }
 286 #end[streamableType]
 287 
 288     public $Type$Buffer get($type$[] dst, int offset, int length) {
 289 #if[rw]
 290         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
 291             checkBounds(offset, length, dst.length);
 292             int pos = position();
 293             int lim = limit();
 294             assert (pos <= lim);
 295             int rem = (pos <= lim ? lim - pos : 0);
 296             if (length > rem)
 297                 throw new BufferUnderflowException();
 298 
 299             long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
 300             try {
 301 #if[!byte]
 302                 if (order() != ByteOrder.nativeOrder())
 303                     UNSAFE.copySwapMemory(null,
 304                                           ix(pos),
 305                                           dst,
 306                                           dstOffset,
 307                                           (long)length << $LG_BYTES_PER_VALUE$,
 308                                           (long)1 << $LG_BYTES_PER_VALUE$);
 309                 else
 310 #end[!byte]
 311                     UNSAFE.copyMemory(null,
 312                                       ix(pos),
 313                                       dst,
 314                                       dstOffset,
 315                                       (long)length << $LG_BYTES_PER_VALUE$);
 316             } finally {
 317                 Reference.reachabilityFence(this);
 318             }
 319             position(pos + length);
 320         } else {
 321             super.get(dst, offset, length);
 322         }
 323         return this;
 324 #else[rw]
 325         throw new ReadOnlyBufferException();
 326 #end[rw]
 327     }
 328 
 329     public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
 330         //System.out.println("Direct absolute bulk get");
 331 #if[rw]
 332         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
 333             Objects.checkFromIndexSize(index, length, limit());
 334             Objects.checkFromIndexSize(offset, length, dst.length);
 335 
 336             long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
 337             try {
 338 #if[!byte]
 339                 if (order() != ByteOrder.nativeOrder())
 340                     UNSAFE.copySwapMemory(null,
 341                                           ix(index),
 342                                           dst,
 343                                           dstOffset,
 344                                           (long)length << $LG_BYTES_PER_VALUE$,
 345                                           (long)1 << $LG_BYTES_PER_VALUE$);
 346                 else
 347 #end[!byte]
 348                     UNSAFE.copyMemory(null,
 349                                       ix(index),
 350                                       dst,
 351                                       dstOffset,
 352                                       (long)length << $LG_BYTES_PER_VALUE$);
 353             } finally {
 354                 Reference.reachabilityFence(this);
 355             }
 356         } else {
 357             super.get(index, dst, offset, length);
 358         }
 359         return this;
 360 #else[rw]
 361         throw new ReadOnlyBufferException();
 362 #end[rw]
 363     }
 364 #end[rw]
 365 
 366     public $Type$Buffer put($type$ x) {
 367 #if[rw]
 368         try {
 369             UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
 370         } finally {
 371             Reference.reachabilityFence(this);
 372         }
 373         return this;
 374 #else[rw]
 375         throw new ReadOnlyBufferException();
 376 #end[rw]
 377     }
 378 
 379     public $Type$Buffer put(int i, $type$ x) {
 380 #if[rw]
 381         try {
 382             UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
 383         } finally {
 384             Reference.reachabilityFence(this);
 385         }
 386         return this;
 387 #else[rw]
 388         throw new ReadOnlyBufferException();
 389 #end[rw]
 390     }
 391 
 392     public $Type$Buffer put($Type$Buffer src) {
 393 #if[rw]
 394         if (src instanceof Direct$Type$Buffer$BO$) {
 395             if (src == this)
 396                 throw createSameBufferException();
 397             Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
 398 
 399             int spos = sb.position();
 400             int slim = sb.limit();
 401             assert (spos <= slim);
 402             int srem = (spos <= slim ? slim - spos : 0);
 403 
 404             int pos = position();
 405             int lim = limit();
 406             assert (pos <= lim);
 407             int rem = (pos <= lim ? lim - pos : 0);
 408 
 409             if (srem > rem)
 410                 throw new BufferOverflowException();
 411             try {
 412                 UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
 413             } finally {
 414                 Reference.reachabilityFence(sb);
 415                 Reference.reachabilityFence(this);
 416             }
 417             sb.position(spos + srem);
 418             position(pos + srem);
 419         } else if (src.hb != null) {
 420 
 421             int spos = src.position();
 422             int slim = src.limit();
 423             assert (spos <= slim);
 424             int srem = (spos <= slim ? slim - spos : 0);
 425 
 426             put(src.hb, src.offset + spos, srem);
 427             src.position(spos + srem);
 428 
 429         } else {
 430             super.put(src);
 431         }
 432         return this;
 433 #else[rw]
 434         throw new ReadOnlyBufferException();
 435 #end[rw]
 436     }
 437 
 438     public $Type$Buffer put($type$[] src, int offset, int length) {
 439 #if[rw]
 440         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
 441             checkBounds(offset, length, src.length);
 442             int pos = position();
 443             int lim = limit();
 444             assert (pos <= lim);
 445             int rem = (pos <= lim ? lim - pos : 0);
 446             if (length > rem)
 447                 throw new BufferOverflowException();
 448 
 449             long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
 450             try {
 451 #if[!byte]
 452                 if (order() != ByteOrder.nativeOrder())
 453                     UNSAFE.copySwapMemory(src,
 454                                           srcOffset,
 455                                           null,
 456                                           ix(pos),
 457                                           (long)length << $LG_BYTES_PER_VALUE$,
 458                                           (long)1 << $LG_BYTES_PER_VALUE$);
 459                 else
 460 #end[!byte]
 461                     UNSAFE.copyMemory(src,
 462                                       srcOffset,
 463                                       null,
 464                                       ix(pos),
 465                                       (long)length << $LG_BYTES_PER_VALUE$);
 466             } finally {
 467                 Reference.reachabilityFence(this);
 468             }
 469             position(pos + length);
 470         } else {
 471             super.put(src, offset, length);
 472         }
 473         return this;
 474 #else[rw]
 475         throw new ReadOnlyBufferException();
 476 #end[rw]
 477     }
 478 
 479     public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
 480         //System.out.println("Direct absolute bulk put array");
 481 #if[rw]
 482         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
 483             Objects.checkFromIndexSize(index, length, limit());
 484             Objects.checkFromIndexSize(offset, length, src.length);
 485 
 486 
 487             long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
 488             try {
 489 #if[!byte]
 490                 if (order() != ByteOrder.nativeOrder())
 491                     UNSAFE.copySwapMemory(src,
 492                                           srcOffset,
 493                                           null,
 494                                           ix(index),
 495                                           (long)length << $LG_BYTES_PER_VALUE$,
 496                                           (long)1 << $LG_BYTES_PER_VALUE$);
 497                 else
 498 #end[!byte]
 499                     UNSAFE.copyMemory(src,
 500                                       srcOffset,
 501                                       null,
 502                                       ix(index),
 503                                       (long)length << $LG_BYTES_PER_VALUE$);
 504             } finally {
 505                 Reference.reachabilityFence(this);
 506             }
 507         } else {
 508             super.put(index, src, offset, length);
 509         }
 510         return this;
 511 #else[rw]
 512         throw new ReadOnlyBufferException();
 513 #end[rw]
 514     }
 515 
 516     public $Type$Buffer put(int index, $Type$Buffer src, int srcIndex,
 517         int length) {
 518         //System.out.println("Direct absolute bulk buffer");
 519 #if[rw]
 520         if (src instanceof Direct$Type$Buffer$BO$) {
 521             Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
 522 
 523             Objects.checkFromIndexSize(index, length, limit());
 524             Objects.checkFromIndexSize(srcIndex, length, sb.limit());
 525             try {
 526                 UNSAFE.copyMemory(sb.ix(srcIndex), ix(index),
 527                     (long)length << $LG_BYTES_PER_VALUE$);
 528             } finally {
 529                 Reference.reachabilityFence(sb);
 530                 Reference.reachabilityFence(this);
 531             }
 532         } else if (src.hb != null) {
 533             Objects.checkFromIndexSize(index, length, limit());
 534             Objects.checkFromIndexSize(srcIndex, length, src.limit());
 535             put(index, src.hb, srcIndex, length);
 536         } else {
 537             super.put(index, src, srcIndex, length);
 538         }
 539         return this;
 540 #else[rw]
 541         throw new ReadOnlyBufferException();
 542 #end[rw]
 543     }
 544 
 545     public $Type$Buffer compact() {
 546 #if[rw]
 547         int pos = position();
 548         int lim = limit();
 549         assert (pos <= lim);
 550         int rem = (pos <= lim ? lim - pos : 0);
 551         try {
 552             UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
 553         } finally {
 554             Reference.reachabilityFence(this);
 555         }
 556         position(rem);
 557         limit(capacity());
 558         discardMark();
 559         return this;
 560 #else[rw]
 561         throw new ReadOnlyBufferException();
 562 #end[rw]
 563     }
 564 
 565     public boolean isDirect() {
 566         return true;
 567     }
 568 
 569     public boolean isReadOnly() {
 570         return {#if[rw]?false:true};
 571     }
 572 
 573 
 574 #if[char]
 575 
 576     public String toString(int start, int end) {
 577         if ((end > limit()) || (start > end))
 578             throw new IndexOutOfBoundsException();
 579         try {
 580             int len = end - start;
 581             char[] ca = new char[len];
 582             CharBuffer cb = CharBuffer.wrap(ca);
 583             CharBuffer db = this.duplicate();
 584             db.position(start);
 585             db.limit(end);
 586             cb.put(db);
 587             return new String(ca);
 588         } catch (StringIndexOutOfBoundsException x) {
 589             throw new IndexOutOfBoundsException();
 590         }
 591     }
 592 
 593 
 594     // --- Methods to support CharSequence ---
 595 
 596     public CharBuffer subSequence(int start, int end) {
 597         int pos = position();
 598         int lim = limit();
 599         assert (pos <= lim);
 600         pos = (pos <= lim ? pos : lim);
 601         int len = lim - pos;
 602 
 603         if ((start < 0) || (end > len) || (start > end))
 604             throw new IndexOutOfBoundsException();
 605         return new DirectCharBuffer$RW$$BO$(this,
 606                                             -1,
 607                                             pos + start,
 608                                             pos + end,
 609                                             capacity(),
 610                                             offset);
 611     }
 612 
 613 #end[char]
 614 
 615 
 616 
 617 #if[!byte]
 618 
 619     public ByteOrder order() {
 620 #if[boS]
 621         return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
 622                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
 623 #end[boS]
 624 #if[boU]
 625         return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
 626                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
 627 #end[boU]
 628     }
 629 
 630 #end[!byte]
 631 
 632 #if[char]
 633     ByteOrder charRegionOrder() {
 634         return order();
 635     }
 636 #end[char]
 637 
 638 
 639 #if[byte]
 640     // #BIN
 641     //
 642     // Binary-data access methods  for short, char, int, long, float,
 643     // and double will be inserted here
 644 
 645 #end[byte]
 646 
 647 }