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