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 }