< prev index next >

src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java

Print this page

 31 import java.nio.ByteBuffer;
 32 import java.nio.ByteOrder;
 33 import java.nio.CharBuffer;
 34 import java.nio.DoubleBuffer;
 35 import java.nio.FloatBuffer;
 36 import java.nio.IntBuffer;
 37 import java.nio.LongBuffer;
 38 import java.nio.ShortBuffer;
 39 import java.util.*;
 40 import java.util.function.BiFunction;
 41 import java.util.function.Consumer;
 42 import java.util.function.Function;
 43 import java.util.function.IntFunction;
 44 import java.util.stream.Stream;
 45 import java.util.stream.StreamSupport;
 46 
 47 import jdk.internal.access.JavaNioAccess;
 48 import jdk.internal.access.SharedSecrets;
 49 import jdk.internal.access.foreign.UnmapperProxy;
 50 import jdk.internal.misc.ScopedMemoryAccess;
 51 import jdk.internal.misc.Unsafe;
 52 import jdk.internal.reflect.CallerSensitive;
 53 import jdk.internal.reflect.Reflection;
 54 import jdk.internal.util.ArraysSupport;
 55 import jdk.internal.util.Preconditions;
 56 import jdk.internal.vm.annotation.ForceInline;

 57 
 58 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
 59 
 60 /**
 61  * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
 62  * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
 63  * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
 64  * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
 65  * than the owner thread. See {@link MemorySessionImpl} for more details on management of temporal bounds. Subclasses
 66  * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
 67  * {@link MappedMemorySegmentImpl}.
 68  */
 69 public abstract sealed class AbstractMemorySegmentImpl
 70         implements MemorySegment, SegmentAllocator, BiFunction<String, List<Number>, RuntimeException>
 71         permits HeapMemorySegmentImpl, NativeMemorySegmentImpl {
 72 
 73     private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
 74 
 75     static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
 76 

247     @Override
248     public boolean isMapped() {
249         return false;
250     }
251 
252     @Override
253     public boolean isNative() {
254         return false;
255     }
256 
257     @Override
258     public final Optional<MemorySegment> asOverlappingSlice(MemorySegment other) {
259         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
260         if (unsafeGetBase() == that.unsafeGetBase()) {  // both either native or heap
261             final long thisStart = this.unsafeGetOffset();
262             final long thatStart = that.unsafeGetOffset();
263             final long thisEnd = thisStart + this.byteSize();
264             final long thatEnd = thatStart + that.byteSize();
265 
266             if (thisStart < thatEnd && thisEnd > thatStart) {  //overlap occurs
267                 long offsetToThat = this.segmentOffset(that);
268                 long newOffset = offsetToThat >= 0 ? offsetToThat : 0;
269                 return Optional.of(asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat)));
270             }
271         }
272         return Optional.empty();
273     }
274 
275     @Override
276     public final long segmentOffset(MemorySegment other) {
277         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other);
278         if (unsafeGetBase() == that.unsafeGetBase()) {
279             return that.unsafeGetOffset() - this.unsafeGetOffset();
280         }
281         throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa).");
282     }
283 
284     @Override
285     public void load() {
286         throw notAMappedSegment();
287     }
288 
289     @Override
290     public void unload() {
291         throw notAMappedSegment();
292     }
293 
294     @Override
295     public boolean isLoaded() {
296         throw notAMappedSegment();
297     }
298 
299     @Override
300     public void force() {
301         throw notAMappedSegment();
302     }
303 

529     public static AbstractMemorySegmentImpl ofBuffer(Buffer bb) {
530         Objects.requireNonNull(bb);
531         Object base = NIO_ACCESS.getBufferBase(bb);
532         if (!bb.isDirect() && base == null) {
533             throw new IllegalArgumentException("The provided heap buffer is not backed by an array.");
534         }
535         long bbAddress = NIO_ACCESS.getBufferAddress(bb);
536         UnmapperProxy unmapper = NIO_ACCESS.unmapper(bb);
537 
538         int pos = bb.position();
539         int limit = bb.limit();
540         int size = limit - pos;
541 
542         AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl) NIO_ACCESS.bufferSegment(bb);
543         boolean readOnly = bb.isReadOnly();
544         int scaleFactor = getScaleFactor(bb);
545         final MemorySessionImpl bufferScope;
546         if (bufferSegment != null) {
547             bufferScope = bufferSegment.scope;
548         } else {
549             bufferScope = MemorySessionImpl.heapSession(bb);
550         }
551         if (base != null) {
552             if (base instanceof byte[]) {
553                 return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
554             } else if (base instanceof short[]) {
555                 return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
556             } else if (base instanceof char[]) {
557                 return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
558             } else if (base instanceof int[]) {
559                 return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
560             } else if (base instanceof float[]) {
561                 return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
562             } else if (base instanceof long[]) {
563                 return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
564             } else if (base instanceof double[]) {
565                 return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
566             } else {
567                 throw new AssertionError("Cannot get here");
568             }
569         } else if (unmapper == null) {
570             return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope);
571         } else {
572             // we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0.
573             return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferScope);
574         }
575     }
576 
577     private static int getScaleFactor(Buffer buffer) {
578         if (buffer instanceof ByteBuffer) {
579             return 0;
580         } else if (buffer instanceof CharBuffer) {
581             return 1;
582         } else if (buffer instanceof ShortBuffer) {
583             return 1;
584         } else if (buffer instanceof IntBuffer) {
585             return 2;
586         } else if (buffer instanceof FloatBuffer) {
587             return 2;
588         } else if (buffer instanceof LongBuffer) {
589             return 3;
590         } else if (buffer instanceof DoubleBuffer) {
591             return 3;
592         } else {
593             throw new AssertionError("Cannot get here");

594         }
595     }
596 
597     @ForceInline
598     public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset,
599                             MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
600                             long elementCount) {
601 
602         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
603         AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment;
604         if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) {
605             throw new IllegalArgumentException("Source and destination layouts must have same size");
606         }
607         Utils.checkElementAlignment(srcElementLayout, "Source layout alignment greater than its size");
608         Utils.checkElementAlignment(dstElementLayout, "Destination layout alignment greater than its size");
609         if (!srcImpl.isAlignedForElement(srcOffset, srcElementLayout)) {
610             throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
611         }
612         if (!dstImpl.isAlignedForElement(dstOffset, dstElementLayout)) {
613             throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
614         }
615         long size = elementCount * srcElementLayout.byteSize();
616         srcImpl.checkAccess(srcOffset, size, true);
617         dstImpl.checkAccess(dstOffset, size, false);
618         if (srcElementLayout.byteSize() == 1 || srcElementLayout.order() == dstElementLayout.order()) {
619             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
620                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
621                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size);
622         } else {
623             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
624                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
625                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size, srcElementLayout.byteSize());
626         }
627     }
628 
629     @ForceInline
630     public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset,
631                             Object dstArray, int dstIndex,
632                             int elementCount) {
633 
634         long baseAndScale = getBaseAndScale(dstArray.getClass());
635         if (dstArray.getClass().componentType() != srcLayout.carrier()) {
636             throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
637         }
638         int dstBase = (int)baseAndScale;
639         long dstWidth = (int)(baseAndScale >> 32); // Use long arithmetics below
640         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
641         Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
642         if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
643             throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
644         }
645         srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true);
646         Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray));
647         if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) {
648             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null,
649                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
650                     dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth);
651         } else {
652             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null,
653                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
654                     dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth, dstWidth);
655         }
656     }
657 
658     @ForceInline
659     public static void copy(Object srcArray, int srcIndex,
660                             MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
661                             int elementCount) {
662 
663         long baseAndScale = getBaseAndScale(srcArray.getClass());
664         if (srcArray.getClass().componentType() != dstLayout.carrier()) {
665             throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
666         }
667         int srcBase = (int)baseAndScale;
668         long srcWidth = (int)(baseAndScale >> 32); // Use long arithmetics below
669         Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray));
670         AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
671         Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
672         if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
673             throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
674         }
675         destImpl.checkAccess(dstOffset, elementCount * srcWidth, false);
676         if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
677             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(),
678                     srcArray, srcBase + (srcIndex * srcWidth),
679                     destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth);
680         } else {
681             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(),
682                     srcArray, srcBase + (srcIndex * srcWidth),
683                     destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth);
684         }
685     }
686 
687     public static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOffset,
688                                 MemorySegment dstSegment, long dstFromOffset, long dstToOffset) {
689         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(srcSegment);
690         AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(dstSegment);
691         long srcBytes = srcToOffset - srcFromOffset;
692         long dstBytes = dstToOffset - dstFromOffset;
693         srcImpl.checkAccess(srcFromOffset, srcBytes, true);
694         dstImpl.checkAccess(dstFromOffset, dstBytes, true);
695         if (dstImpl == srcImpl) {
696             srcImpl.checkValidState();
697             return -1;
698         }
699 
700         long bytes = Math.min(srcBytes, dstBytes);
701         long i = 0;
702         if (bytes > 7) {
703             if (srcImpl.get(JAVA_BYTE, srcFromOffset) != dstImpl.get(JAVA_BYTE, dstFromOffset)) {

705             }
706             i = AbstractMemorySegmentImpl.vectorizedMismatchLargeForBytes(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
707                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcFromOffset,
708                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstFromOffset,
709                     bytes);
710             if (i >= 0) {
711                 return i;
712             }
713             long remaining = ~i;
714             assert remaining < 8 : "remaining greater than 7: " + remaining;
715             i = bytes - remaining;
716         }
717         for (; i < bytes; i++) {
718             if (srcImpl.get(JAVA_BYTE, srcFromOffset + i) != dstImpl.get(JAVA_BYTE, dstFromOffset + i)) {
719                 return i;
720             }
721         }
722         return srcBytes != dstBytes ? bytes : -1;
723     }
724 
725     private static long getBaseAndScale(Class<?> arrayType) {
726         if (arrayType.equals(byte[].class)) {
727             return (long) Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32);
728         } else if (arrayType.equals(char[].class)) {
729             return (long) Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32);
730         } else if (arrayType.equals(short[].class)) {
731             return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32);
732         } else if (arrayType.equals(int[].class)) {
733             return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32);
734         } else if (arrayType.equals(float[].class)) {
735             return (long)Unsafe.ARRAY_FLOAT_BASE_OFFSET | ((long)Unsafe.ARRAY_FLOAT_INDEX_SCALE << 32);
736         } else if (arrayType.equals(long[].class)) {
737             return (long)Unsafe.ARRAY_LONG_BASE_OFFSET | ((long)Unsafe.ARRAY_LONG_INDEX_SCALE << 32);
738         } else if (arrayType.equals(double[].class)) {
739             return (long)Unsafe.ARRAY_DOUBLE_BASE_OFFSET | ((long)Unsafe.ARRAY_DOUBLE_INDEX_SCALE << 32);
740         } else {
741             throw new IllegalArgumentException("Not a supported array class: " + arrayType.getSimpleName());
742         }
743     }
744 }

 31 import java.nio.ByteBuffer;
 32 import java.nio.ByteOrder;
 33 import java.nio.CharBuffer;
 34 import java.nio.DoubleBuffer;
 35 import java.nio.FloatBuffer;
 36 import java.nio.IntBuffer;
 37 import java.nio.LongBuffer;
 38 import java.nio.ShortBuffer;
 39 import java.util.*;
 40 import java.util.function.BiFunction;
 41 import java.util.function.Consumer;
 42 import java.util.function.Function;
 43 import java.util.function.IntFunction;
 44 import java.util.stream.Stream;
 45 import java.util.stream.StreamSupport;
 46 
 47 import jdk.internal.access.JavaNioAccess;
 48 import jdk.internal.access.SharedSecrets;
 49 import jdk.internal.access.foreign.UnmapperProxy;
 50 import jdk.internal.misc.ScopedMemoryAccess;

 51 import jdk.internal.reflect.CallerSensitive;
 52 import jdk.internal.reflect.Reflection;
 53 import jdk.internal.util.ArraysSupport;
 54 import jdk.internal.util.Preconditions;
 55 import jdk.internal.vm.annotation.ForceInline;
 56 import sun.nio.ch.DirectBuffer;
 57 
 58 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
 59 
 60 /**
 61  * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
 62  * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
 63  * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
 64  * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
 65  * than the owner thread. See {@link MemorySessionImpl} for more details on management of temporal bounds. Subclasses
 66  * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
 67  * {@link MappedMemorySegmentImpl}.
 68  */
 69 public abstract sealed class AbstractMemorySegmentImpl
 70         implements MemorySegment, SegmentAllocator, BiFunction<String, List<Number>, RuntimeException>
 71         permits HeapMemorySegmentImpl, NativeMemorySegmentImpl {
 72 
 73     private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
 74 
 75     static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
 76 

247     @Override
248     public boolean isMapped() {
249         return false;
250     }
251 
252     @Override
253     public boolean isNative() {
254         return false;
255     }
256 
257     @Override
258     public final Optional<MemorySegment> asOverlappingSlice(MemorySegment other) {
259         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
260         if (unsafeGetBase() == that.unsafeGetBase()) {  // both either native or heap
261             final long thisStart = this.unsafeGetOffset();
262             final long thatStart = that.unsafeGetOffset();
263             final long thisEnd = thisStart + this.byteSize();
264             final long thatEnd = thatStart + that.byteSize();
265 
266             if (thisStart < thatEnd && thisEnd > thatStart) {  //overlap occurs
267                 long offsetToThat = that.address() - this.address();
268                 long newOffset = offsetToThat >= 0 ? offsetToThat : 0;
269                 return Optional.of(asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat)));
270             }
271         }
272         return Optional.empty();
273     }
274 









275     @Override
276     public void load() {
277         throw notAMappedSegment();
278     }
279 
280     @Override
281     public void unload() {
282         throw notAMappedSegment();
283     }
284 
285     @Override
286     public boolean isLoaded() {
287         throw notAMappedSegment();
288     }
289 
290     @Override
291     public void force() {
292         throw notAMappedSegment();
293     }
294 

520     public static AbstractMemorySegmentImpl ofBuffer(Buffer bb) {
521         Objects.requireNonNull(bb);
522         Object base = NIO_ACCESS.getBufferBase(bb);
523         if (!bb.isDirect() && base == null) {
524             throw new IllegalArgumentException("The provided heap buffer is not backed by an array.");
525         }
526         long bbAddress = NIO_ACCESS.getBufferAddress(bb);
527         UnmapperProxy unmapper = NIO_ACCESS.unmapper(bb);
528 
529         int pos = bb.position();
530         int limit = bb.limit();
531         int size = limit - pos;
532 
533         AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl) NIO_ACCESS.bufferSegment(bb);
534         boolean readOnly = bb.isReadOnly();
535         int scaleFactor = getScaleFactor(bb);
536         final MemorySessionImpl bufferScope;
537         if (bufferSegment != null) {
538             bufferScope = bufferSegment.scope;
539         } else {
540             bufferScope = MemorySessionImpl.createHeap(bufferRef(bb));
541         }
542         if (base != null) {
543             return switch (base) {
544                 case byte[] __ ->
545                         new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
546                 case short[] __ ->
547                         new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
548                 case char[] __ ->
549                         new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
550                 case int[] __ ->
551                         new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
552                 case float[] __ ->
553                         new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
554                 case long[] __ ->
555                         new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
556                 case double[] __ ->
557                         new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
558                 default -> throw new AssertionError("Cannot get here");
559             };
560         } else if (unmapper == null) {
561             return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope);
562         } else {
563             // we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0.
564             return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferScope);
565         }
566     }
567 
568     private static Object bufferRef(Buffer buffer) {
569         if (buffer instanceof DirectBuffer directBuffer) {
570             // direct buffer, return either the buffer attachment (for slices and views), or the buffer itself
571             return directBuffer.attachment() != null ?
572                     directBuffer.attachment() : directBuffer;










573         } else {
574             // heap buffer, return the underlying array
575             return NIO_ACCESS.getBufferBase(buffer);
576         }
577     }
578 
579     @ForceInline
580     public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset,
581                             MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
582                             long elementCount) {
583 
584         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
585         AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment;
586         if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) {
587             throw new IllegalArgumentException("Source and destination layouts must have same size");
588         }
589         Utils.checkElementAlignment(srcElementLayout, "Source layout alignment greater than its size");
590         Utils.checkElementAlignment(dstElementLayout, "Destination layout alignment greater than its size");
591         if (!srcImpl.isAlignedForElement(srcOffset, srcElementLayout)) {
592             throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
593         }
594         if (!dstImpl.isAlignedForElement(dstOffset, dstElementLayout)) {
595             throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
596         }
597         long size = elementCount * srcElementLayout.byteSize();
598         srcImpl.checkAccess(srcOffset, size, true);
599         dstImpl.checkAccess(dstOffset, size, false);
600         if (srcElementLayout.byteSize() == 1 || srcElementLayout.order() == dstElementLayout.order()) {
601             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
602                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
603                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size);
604         } else {
605             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
606                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
607                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size, srcElementLayout.byteSize());
608         }
609     }
610 
611     @ForceInline
612     public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset,
613                             Object dstArray, int dstIndex,
614                             int elementCount) {
615 
616         var dstInfo = Utils.BaseAndScale.of(dstArray);
617         if (dstArray.getClass().componentType() != srcLayout.carrier()) {
618             throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
619         }


620         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
621         Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
622         if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
623             throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
624         }
625         srcImpl.checkAccess(srcOffset, elementCount * dstInfo.scale(), true);
626         Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray));
627         if (dstInfo.scale() == 1 || srcLayout.order() == ByteOrder.nativeOrder()) {
628             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null,
629                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
630                     dstArray, dstInfo.base() + (dstIndex * dstInfo.scale()), elementCount * dstInfo.scale());
631         } else {
632             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null,
633                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
634                     dstArray, dstInfo.base() + (dstIndex * dstInfo.scale()), elementCount * dstInfo.scale(), dstInfo.scale());
635         }
636     }
637 
638     @ForceInline
639     public static void copy(Object srcArray, int srcIndex,
640                             MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
641                             int elementCount) {
642 
643         var srcInfo = Utils.BaseAndScale.of(srcArray);
644         if (srcArray.getClass().componentType() != dstLayout.carrier()) {
645             throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
646         }


647         Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray));
648         AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
649         Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
650         if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
651             throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
652         }
653         destImpl.checkAccess(dstOffset, elementCount * srcInfo.scale(), false);
654         if (srcInfo.scale() == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
655             ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(),
656                     srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
657                     destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale());
658         } else {
659             ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(),
660                     srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
661                     destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale(), srcInfo.scale());
662         }
663     }
664 
665     public static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOffset,
666                                 MemorySegment dstSegment, long dstFromOffset, long dstToOffset) {
667         AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(srcSegment);
668         AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(dstSegment);
669         long srcBytes = srcToOffset - srcFromOffset;
670         long dstBytes = dstToOffset - dstFromOffset;
671         srcImpl.checkAccess(srcFromOffset, srcBytes, true);
672         dstImpl.checkAccess(dstFromOffset, dstBytes, true);
673         if (dstImpl == srcImpl) {
674             srcImpl.checkValidState();
675             return -1;
676         }
677 
678         long bytes = Math.min(srcBytes, dstBytes);
679         long i = 0;
680         if (bytes > 7) {
681             if (srcImpl.get(JAVA_BYTE, srcFromOffset) != dstImpl.get(JAVA_BYTE, dstFromOffset)) {

683             }
684             i = AbstractMemorySegmentImpl.vectorizedMismatchLargeForBytes(srcImpl.sessionImpl(), dstImpl.sessionImpl(),
685                     srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcFromOffset,
686                     dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstFromOffset,
687                     bytes);
688             if (i >= 0) {
689                 return i;
690             }
691             long remaining = ~i;
692             assert remaining < 8 : "remaining greater than 7: " + remaining;
693             i = bytes - remaining;
694         }
695         for (; i < bytes; i++) {
696             if (srcImpl.get(JAVA_BYTE, srcFromOffset + i) != dstImpl.get(JAVA_BYTE, dstFromOffset + i)) {
697                 return i;
698             }
699         }
700         return srcBytes != dstBytes ? bytes : -1;
701     }
702 
703     private static int getScaleFactor(Buffer buffer) {
704         return switch (buffer) {
705             case ByteBuffer   __ -> 0;
706             case CharBuffer   __ -> 1;
707             case ShortBuffer  __ -> 1;
708             case IntBuffer    __ -> 2;
709             case FloatBuffer  __ -> 2;
710             case LongBuffer   __ -> 3;
711             case DoubleBuffer __ -> 3;
712         };








713     }
714 }
< prev index next >