The two implementations are parallel in structure, and do essentially the same thing, but for two different kinds of references:
type ref store
Heap a[n] a[n] = x
Direct addr unsafe.putInt(addr, x)
(There are other degrees of freedom also, according to element type and endian-ness.)
To handle bulk copies between the two kinds of buffers, there are JNI functions (native methods) which perform heterogeneous array copies.
It would probably be better to use a unified form of reference (for both Java- and C-heap storage).
This would let us have one set of methods for both Heap and Direct buffers.
Details:
The usual problem with mixing heap and non-heap pointers this way is that the GC can *move* a live object, which would leave the direct address dangling.
This can be avoided by the technique Unsafe uses for working generically with heap and non-heap pointers.
Each address is represented not by a byte[] and int offset, or a long address, but by an unsafe pairing of an Object reference and a long offset.
For Java-heap storage, the Object reference points (always) to the header of the heap object, and the long offset is a small number (e.g., 12, 28, etc.).
For C-heap storage (or static storage), the Object reference is (always) null, and the long offset is the absolute address of the storage.
This way, there is always a GC-able reference (or null), and an offset. (Note that null + address must be the same as 0 + address in this scheme.)
Machine instructions which want to load or store the addressed element can blindly do a double-indexed load at *(oopref + offset), and it will always go to the right place.
Recode NIO buffers to use one concrete implementation with the unified Object/offset format.
Thebn common (unsafe) code can implement both Direct and Heap cases.
This would be an advantage to performance, since the compiler would be able to inline monomorphic calls much more readily than the current bimorphic calls.
For bulk copies, an upgraded Unsafe.copyMemory operation is probably a good-enough way to bridge the gap between heap and non-heap.
It would use the above scheme of locating source and destination memory slices each by an Object/offset pair.
It can replace the private native methods in NIO, and (as a single well-known intrinsic) can be open-coded by the compiler.
One missing piece is byte-swapping logic, but we have a separate scalar byte-swap operation which might be acceptable.
(I'm open to suggestions about a byte-swapping, array-copying intrinsic, but I hope it's not necessary.)
- blocks
-
JDK-8157296 Remove fork to xxcodeArrayLoop() and xxcodeBufferLoop() in sun.nio.cs coders
- Open
-
JDK-8158695 Remove fork to xxcodeArrayLoop() and xxcodeBufferLoop() in sun.nio.cs coders
- Closed
- relates to
-
JDK-8149469 ByteBuffer API and implementation enhancements for VarHandles
- Resolved
-
JDK-8080588 VarHandles development
- Resolved
-
JDK-8150921 Update Unsafe getters/setters to use double-register variants
- Resolved
-
JDK-6277756 (bf) reconsider Bits.JNI_COPY_FROM/TO_ARRAY_THRESHOLD values
- Closed
-
JDK-8151163 All Buffer implementations should leverage Unsafe unaligned accessors
- Resolved