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