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 #if[rw] 331 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) { 332 Objects.checkFromIndexSize(index, length, limit()); 333 Objects.checkFromIndexSize(offset, length, dst.length); 334 335 long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); 336 try { 337 #if[!byte] 338 if (order() != ByteOrder.nativeOrder()) 339 UNSAFE.copySwapMemory(null, 340 ix(index), 341 dst, 342 dstOffset, 343 (long)length << $LG_BYTES_PER_VALUE$, 344 (long)1 << $LG_BYTES_PER_VALUE$); 345 else 346 #end[!byte] 347 UNSAFE.copyMemory(null, 348 ix(index), 349 dst, 350 dstOffset, 351 (long)length << $LG_BYTES_PER_VALUE$); 352 } finally { 353 Reference.reachabilityFence(this); 354 } 355 } else { 356 super.get(index, dst, offset, length); 357 } 358 return this; 359 #else[rw] 360 throw new ReadOnlyBufferException(); 361 #end[rw] 362 } 363 #end[rw] 364 365 public $Type$Buffer put($type$ x) { 366 #if[rw] 367 try { 368 UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x))); 369 } finally { 370 Reference.reachabilityFence(this); 371 } 372 return this; 373 #else[rw] 374 throw new ReadOnlyBufferException(); 375 #end[rw] 376 } 377 378 public $Type$Buffer put(int i, $type$ x) { 379 #if[rw] 380 try { 381 UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x))); 382 } finally { 383 Reference.reachabilityFence(this); 384 } 385 return this; 386 #else[rw] 387 throw new ReadOnlyBufferException(); 388 #end[rw] 389 } 390 391 public $Type$Buffer put($Type$Buffer src) { 392 #if[rw] 393 if (src instanceof Direct$Type$Buffer$BO$) { 394 if (src == this) 395 throw createSameBufferException(); 396 Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src; 397 398 int spos = sb.position(); 399 int slim = sb.limit(); 400 assert (spos <= slim); 401 int srem = (spos <= slim ? slim - spos : 0); 402 403 int pos = position(); 404 int lim = limit(); 405 assert (pos <= lim); 406 int rem = (pos <= lim ? lim - pos : 0); 407 408 if (srem > rem) 409 throw new BufferOverflowException(); 410 try { 411 UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$); 412 } finally { 413 Reference.reachabilityFence(sb); 414 Reference.reachabilityFence(this); 415 } 416 sb.position(spos + srem); 417 position(pos + srem); 418 } else if (src.hb != null) { 419 420 int spos = src.position(); 421 int slim = src.limit(); 422 assert (spos <= slim); 423 int srem = (spos <= slim ? slim - spos : 0); 424 425 put(src.hb, src.offset + spos, srem); 426 src.position(spos + srem); 427 428 } else { 429 super.put(src); 430 } 431 return this; 432 #else[rw] 433 throw new ReadOnlyBufferException(); 434 #end[rw] 435 } 436 437 public $Type$Buffer put($type$[] src, int offset, int length) { 438 #if[rw] 439 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 440 checkBounds(offset, length, src.length); 441 int pos = position(); 442 int lim = limit(); 443 assert (pos <= lim); 444 int rem = (pos <= lim ? lim - pos : 0); 445 if (length > rem) 446 throw new BufferOverflowException(); 447 448 long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); 449 try { 450 #if[!byte] 451 if (order() != ByteOrder.nativeOrder()) 452 UNSAFE.copySwapMemory(src, 453 srcOffset, 454 null, 455 ix(pos), 456 (long)length << $LG_BYTES_PER_VALUE$, 457 (long)1 << $LG_BYTES_PER_VALUE$); 458 else 459 #end[!byte] 460 UNSAFE.copyMemory(src, 461 srcOffset, 462 null, 463 ix(pos), 464 (long)length << $LG_BYTES_PER_VALUE$); 465 } finally { 466 Reference.reachabilityFence(this); 467 } 468 position(pos + length); 469 } else { 470 super.put(src, offset, length); 471 } 472 return this; 473 #else[rw] 474 throw new ReadOnlyBufferException(); 475 #end[rw] 476 } 477 478 public $Type$Buffer put(int index, $type$[] src, int offset, int length) { 479 #if[rw] 480 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 481 Objects.checkFromIndexSize(index, length, limit()); 482 Objects.checkFromIndexSize(offset, length, src.length); 483 484 485 long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); 486 try { 487 #if[!byte] 488 if (order() != ByteOrder.nativeOrder()) 489 UNSAFE.copySwapMemory(src, 490 srcOffset, 491 null, 492 ix(index), 493 (long)length << $LG_BYTES_PER_VALUE$, 494 (long)1 << $LG_BYTES_PER_VALUE$); 495 else 496 #end[!byte] 497 UNSAFE.copyMemory(src, 498 srcOffset, 499 null, 500 ix(index), 501 (long)length << $LG_BYTES_PER_VALUE$); 502 } finally { 503 Reference.reachabilityFence(this); 504 } 505 } else { 506 super.put(index, src, offset, length); 507 } 508 return this; 509 #else[rw] 510 throw new ReadOnlyBufferException(); 511 #end[rw] 512 } 513 514 public $Type$Buffer compact() { 515 #if[rw] 516 int pos = position(); 517 int lim = limit(); 518 assert (pos <= lim); 519 int rem = (pos <= lim ? lim - pos : 0); 520 try { 521 UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$); 522 } finally { 523 Reference.reachabilityFence(this); 524 } 525 position(rem); 526 limit(capacity()); 527 discardMark(); 528 return this; 529 #else[rw] 530 throw new ReadOnlyBufferException(); 531 #end[rw] 532 } 533 534 public boolean isDirect() { 535 return true; 536 } 537 538 public boolean isReadOnly() { 539 return {#if[rw]?false:true}; 540 } 541 542 543 #if[char] 544 545 public String toString(int start, int end) { 546 if ((end > limit()) || (start > end)) 547 throw new IndexOutOfBoundsException(); 548 try { 549 int len = end - start; 550 char[] ca = new char[len]; 551 CharBuffer cb = CharBuffer.wrap(ca); 552 CharBuffer db = this.duplicate(); 553 db.position(start); 554 db.limit(end); 555 cb.put(db); 556 return new String(ca); 557 } catch (StringIndexOutOfBoundsException x) { 558 throw new IndexOutOfBoundsException(); 559 } 560 } 561 562 563 // --- Methods to support CharSequence --- 564 565 public CharBuffer subSequence(int start, int end) { 566 int pos = position(); 567 int lim = limit(); 568 assert (pos <= lim); 569 pos = (pos <= lim ? pos : lim); 570 int len = lim - pos; 571 572 if ((start < 0) || (end > len) || (start > end)) 573 throw new IndexOutOfBoundsException(); 574 return new DirectCharBuffer$RW$$BO$(this, 575 -1, 576 pos + start, 577 pos + end, 578 capacity(), 579 offset); 580 } 581 582 #end[char] 583 584 585 586 #if[!byte] 587 588 public ByteOrder order() { 589 #if[boS] 590 return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) 591 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 592 #end[boS] 593 #if[boU] 594 return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN) 595 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 596 #end[boU] 597 } 598 599 #end[!byte] 600 601 #if[char] 602 ByteOrder charRegionOrder() { 603 return order(); 604 } 605 #end[char] 606 607 608 #if[byte] 609 // #BIN 610 // 611 // Binary-data access methods for short, char, int, long, float, 612 // and double will be inserted here 613 614 #end[byte] 615 616 }