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