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