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 att = db; 198 #else[rw] 199 super(db, mark, pos, lim, cap, off); 200 this.isReadOnly = true; 201 #end[rw] 202 } 203 204 @Override 205 Object base() { 206 return null; 207 } 208 209 public $Type$Buffer slice() { 210 int pos = this.position(); 211 int lim = this.limit(); 212 assert (pos <= lim); 213 int rem = (pos <= lim ? lim - pos : 0); 214 int off = (pos << $LG_BYTES_PER_VALUE$); 215 assert (off >= 0); 216 return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off); 217 } 218 219 #if[byte] 220 public $Type$Buffer slice(int pos, int lim) { 221 assert (pos >= 0); 222 assert (pos <= lim); 223 int rem = lim - pos; 224 return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos); 225 } 226 #end[byte] 227 228 public $Type$Buffer duplicate() { 229 return new Direct$Type$Buffer$RW$$BO$(this, 230 this.markValue(), 231 this.position(), 232 this.limit(), 233 this.capacity(), 234 0); 235 } 236 237 public $Type$Buffer asReadOnlyBuffer() { 238 #if[rw] 239 return new Direct$Type$BufferR$BO$(this, 240 this.markValue(), 241 this.position(), 242 this.limit(), 243 this.capacity(), 244 0); 245 #else[rw] 246 return duplicate(); 247 #end[rw] 248 } 249 250 #if[rw] 251 252 public long address() { 253 return address; 254 } 255 256 private long ix(int i) { 257 return address + ((long)i << $LG_BYTES_PER_VALUE$); 258 } 259 260 public $type$ get() { 261 try { 262 return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex())))); 263 } finally { 264 Reference.reachabilityFence(this); 265 } 266 } 267 268 public $type$ get(int i) { 269 try { 270 return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i))))); 271 } finally { 272 Reference.reachabilityFence(this); 273 } 274 } 275 276 #if[streamableType] 277 $type$ getUnchecked(int i) { 278 try { 279 return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i)))); 280 } finally { 281 Reference.reachabilityFence(this); 282 } 283 } 284 #end[streamableType] 285 286 public $Type$Buffer get($type$[] dst, int offset, int length) { 287 #if[rw] 288 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) { 289 checkBounds(offset, length, dst.length); 290 int pos = position(); 291 int lim = limit(); 292 assert (pos <= lim); 293 int rem = (pos <= lim ? lim - pos : 0); 294 if (length > rem) 295 throw new BufferUnderflowException(); 296 297 long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); 298 try { 299 #if[!byte] 300 if (order() != ByteOrder.nativeOrder()) 301 UNSAFE.copySwapMemory(null, 302 ix(pos), 303 dst, 304 dstOffset, 305 (long)length << $LG_BYTES_PER_VALUE$, 306 (long)1 << $LG_BYTES_PER_VALUE$); 307 else 308 #end[!byte] 309 UNSAFE.copyMemory(null, 310 ix(pos), 311 dst, 312 dstOffset, 313 (long)length << $LG_BYTES_PER_VALUE$); 314 } finally { 315 Reference.reachabilityFence(this); 316 } 317 position(pos + length); 318 } else { 319 super.get(dst, offset, length); 320 } 321 return this; 322 #else[rw] 323 throw new ReadOnlyBufferException(); 324 #end[rw] 325 } 326 327 #end[rw] 328 329 public $Type$Buffer put($type$ x) { 330 #if[rw] 331 try { 332 UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x))); 333 } finally { 334 Reference.reachabilityFence(this); 335 } 336 return this; 337 #else[rw] 338 throw new ReadOnlyBufferException(); 339 #end[rw] 340 } 341 342 public $Type$Buffer put(int i, $type$ x) { 343 #if[rw] 344 try { 345 UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x))); 346 } finally { 347 Reference.reachabilityFence(this); 348 } 349 return this; 350 #else[rw] 351 throw new ReadOnlyBufferException(); 352 #end[rw] 353 } 354 355 public $Type$Buffer put($Type$Buffer src) { 356 #if[rw] 357 if (src instanceof Direct$Type$Buffer$BO$) { 358 if (src == this) 359 throw createSameBufferException(); 360 Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src; 361 362 int spos = sb.position(); 363 int slim = sb.limit(); 364 assert (spos <= slim); 365 int srem = (spos <= slim ? slim - spos : 0); 366 367 int pos = position(); 368 int lim = limit(); 369 assert (pos <= lim); 370 int rem = (pos <= lim ? lim - pos : 0); 371 372 if (srem > rem) 373 throw new BufferOverflowException(); 374 try { 375 UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$); 376 } finally { 377 Reference.reachabilityFence(sb); 378 Reference.reachabilityFence(this); 379 } 380 sb.position(spos + srem); 381 position(pos + srem); 382 } else if (src.hb != null) { 383 384 int spos = src.position(); 385 int slim = src.limit(); 386 assert (spos <= slim); 387 int srem = (spos <= slim ? slim - spos : 0); 388 389 put(src.hb, src.offset + spos, srem); 390 src.position(spos + srem); 391 392 } else { 393 super.put(src); 394 } 395 return this; 396 #else[rw] 397 throw new ReadOnlyBufferException(); 398 #end[rw] 399 } 400 401 public $Type$Buffer put($type$[] src, int offset, int length) { 402 #if[rw] 403 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 404 checkBounds(offset, length, src.length); 405 int pos = position(); 406 int lim = limit(); 407 assert (pos <= lim); 408 int rem = (pos <= lim ? lim - pos : 0); 409 if (length > rem) 410 throw new BufferOverflowException(); 411 412 long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); 413 try { 414 #if[!byte] 415 if (order() != ByteOrder.nativeOrder()) 416 UNSAFE.copySwapMemory(src, 417 srcOffset, 418 null, 419 ix(pos), 420 (long)length << $LG_BYTES_PER_VALUE$, 421 (long)1 << $LG_BYTES_PER_VALUE$); 422 else 423 #end[!byte] 424 UNSAFE.copyMemory(src, 425 srcOffset, 426 null, 427 ix(pos), 428 (long)length << $LG_BYTES_PER_VALUE$); 429 } finally { 430 Reference.reachabilityFence(this); 431 } 432 position(pos + length); 433 } else { 434 super.put(src, offset, length); 435 } 436 return this; 437 #else[rw] 438 throw new ReadOnlyBufferException(); 439 #end[rw] 440 } 441 442 public $Type$Buffer compact() { 443 #if[rw] 444 int pos = position(); 445 int lim = limit(); 446 assert (pos <= lim); 447 int rem = (pos <= lim ? lim - pos : 0); 448 try { 449 UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$); 450 } finally { 451 Reference.reachabilityFence(this); 452 } 453 position(rem); 454 limit(capacity()); 455 discardMark(); 456 return this; 457 #else[rw] 458 throw new ReadOnlyBufferException(); 459 #end[rw] 460 } 461 462 public boolean isDirect() { 463 return true; 464 } 465 466 public boolean isReadOnly() { 467 return {#if[rw]?false:true}; 468 } 469 470 471 #if[char] 472 473 public String toString(int start, int end) { 474 if ((end > limit()) || (start > end)) 475 throw new IndexOutOfBoundsException(); 476 try { 477 int len = end - start; 478 char[] ca = new char[len]; 479 CharBuffer cb = CharBuffer.wrap(ca); 480 CharBuffer db = this.duplicate(); 481 db.position(start); 482 db.limit(end); 483 cb.put(db); 484 return new String(ca); 485 } catch (StringIndexOutOfBoundsException x) { 486 throw new IndexOutOfBoundsException(); 487 } 488 } 489 490 491 // --- Methods to support CharSequence --- 492 493 public CharBuffer subSequence(int start, int end) { 494 int pos = position(); 495 int lim = limit(); 496 assert (pos <= lim); 497 pos = (pos <= lim ? pos : lim); 498 int len = lim - pos; 499 500 if ((start < 0) || (end > len) || (start > end)) 501 throw new IndexOutOfBoundsException(); 502 return new DirectCharBuffer$RW$$BO$(this, 503 -1, 504 pos + start, 505 pos + end, 506 capacity(), 507 offset); 508 } 509 510 #end[char] 511 512 513 514 #if[!byte] 515 516 public ByteOrder order() { 517 #if[boS] 518 return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) 519 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 520 #end[boS] 521 #if[boU] 522 return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN) 523 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 524 #end[boU] 525 } 526 527 #end[!byte] 528 529 #if[char] 530 ByteOrder charRegionOrder() { 531 return order(); 532 } 533 #end[char] 534 535 536 #if[byte] 537 // #BIN 538 // 539 // Binary-data access methods for short, char, int, long, float, 540 // and double will be inserted here 541 542 #end[byte] 543 544 }