< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

*** 34,27 ***
  import jdk.internal.util.ArraysSupport;
  import jdk.internal.vm.annotation.ForceInline;
  import sun.security.action.GetPropertyAction;
  
  import java.nio.ByteBuffer;
  import java.util.*;
  import java.util.function.Consumer;
  import java.util.function.Function;
  import java.util.function.IntFunction;
  import java.util.stream.Stream;
  import java.util.stream.StreamSupport;
  
  /**
   * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
   * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
   * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
   * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
   * than the owner thread. See {@link ResourceScopeImpl} for more details on management of temporal bounds. Subclasses
   * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
   * {@link MappedMemorySegmentImpl}.
   */
! public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment {
  
      private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
  
      private static final boolean enableSmallSegments =
              Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.SmallSegments", "true"));
--- 34,30 ---
  import jdk.internal.util.ArraysSupport;
  import jdk.internal.vm.annotation.ForceInline;
  import sun.security.action.GetPropertyAction;
  
  import java.nio.ByteBuffer;
+ import java.nio.ByteOrder;
  import java.util.*;
  import java.util.function.Consumer;
  import java.util.function.Function;
  import java.util.function.IntFunction;
  import java.util.stream.Stream;
  import java.util.stream.StreamSupport;
  
+ import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE;
+ 
  /**
   * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information
   * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time.
   * Access to certain sensitive operations on the memory segment will fail with {@code IllegalStateException} if the
   * segment is either in an invalid state (e.g. it has already been closed) or if access occurs from a thread other
   * than the owner thread. See {@link ResourceScopeImpl} for more details on management of temporal bounds. Subclasses
   * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
   * {@link MappedMemorySegmentImpl}.
   */
! public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment, SegmentAllocator, Scoped {
  
      private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
  
      private static final boolean enableSmallSegments =
              Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.SmallSegments", "true"));

*** 138,28 ***
          checkAccess(0, length, false);
          SCOPED_MEMORY_ACCESS.setMemory(scope, base(), min(), length, value);
          return this;
      }
  
!     public void copyFrom(MemorySegment src) {
!         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(src);
!         long size = that.byteSize();
-         checkAccess(0, size, false);
-         that.checkAccess(0, size, true);
-         SCOPED_MEMORY_ACCESS.copyMemory(scope, that.scope,
-                 that.base(), that.min(),
-                 base(), min(), size);
-     }
- 
-     public void copyFromSwap(MemorySegment src, long elemSize) {
-         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)src;
-         long size = that.byteSize();
-         checkAccess(0, size, false);
-         that.checkAccess(0, size, true);
-         SCOPED_MEMORY_ACCESS.copySwapMemory(scope, that.scope,
-                         that.base(), that.min(),
-                         base(), min(), size, elemSize);
      }
  
      @Override
      public long mismatch(MemorySegment other) {
          AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
--- 141,13 ---
          checkAccess(0, length, false);
          SCOPED_MEMORY_ACCESS.setMemory(scope, base(), min(), length, value);
          return this;
      }
  
!     @Override
!     public MemorySegment allocate(long bytesSize, long bytesAlignment) {
!         return asSlice(0, bytesSize);
      }
  
      @Override
      public long mismatch(MemorySegment other) {
          AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);

*** 173,11 ***
              return -1;
          }
  
          long i = 0;
          if (length > 7) {
!             if (MemoryAccess.getByte(this) != MemoryAccess.getByte(that)) {
                  return 0;
              }
              i = vectorizedMismatchLargeForBytes(scope, that.scope,
                      this.base(), this.min(),
                      that.base(), that.min(),
--- 161,11 ---
              return -1;
          }
  
          long i = 0;
          if (length > 7) {
!             if (get(JAVA_BYTE, 0) != that.get(JAVA_BYTE, 0)) {
                  return 0;
              }
              i = vectorizedMismatchLargeForBytes(scope, that.scope,
                      this.base(), this.min(),
                      that.base(), that.min(),

*** 188,11 ***
              long remaining = ~i;
              assert remaining < 8 : "remaining greater than 7: " + remaining;
              i = length - remaining;
          }
          for (; i < length; i++) {
!             if (MemoryAccess.getByteAtOffset(this, i) != MemoryAccess.getByteAtOffset(that, i)) {
                  return i;
              }
          }
          return thisSize != thatSize ? length : -1;
      }
--- 176,11 ---
              long remaining = ~i;
              assert remaining < 8 : "remaining greater than 7: " + remaining;
              i = length - remaining;
          }
          for (; i < length; i++) {
!             if (get(JAVA_BYTE, i) != that.get(JAVA_BYTE, i)) {
                  return i;
              }
          }
          return thisSize != thatSize ? length : -1;
      }

*** 228,13 ***
          }
          return ~remaining;
      }
  
      @Override
!     @ForceInline
!     public final MemoryAddress address() {
-         return new MemoryAddressImpl(this, 0L);
      }
  
      @Override
      public final ByteBuffer asByteBuffer() {
          checkArraySize("ByteBuffer", 1);
--- 216,12 ---
          }
          return ~remaining;
      }
  
      @Override
!     public MemoryAddress address() {
!         throw new UnsupportedOperationException("Cannot obtain address of on-heap segment");
      }
  
      @Override
      public final ByteBuffer asByteBuffer() {
          checkArraySize("ByteBuffer", 1);

*** 267,10 ***
--- 254,37 ---
      @Override
      public boolean isNative() {
          return false;
      }
  
+     @Override
+     public final MemorySegment asOverlappingSlice(MemorySegment other) {
+         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
+         if (base() == that.base()) {  // both either native or heap
+             final long thisStart = this.min();
+             final long thatStart = that.min();
+             final long thisEnd = thisStart + this.byteSize();
+             final long thatEnd = thatStart + that.byteSize();
+ 
+             if (thisStart < thatEnd && thisEnd > thatStart) {  //overlap occurs
+                 long offsetToThat = this.segmentOffset(that);
+                 long newOffset = offsetToThat >= 0 ? offsetToThat : 0;
+                 return asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat));
+             }
+         }
+         return null;
+     }
+ 
+     @Override
+     public final long segmentOffset(MemorySegment other) {
+         AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other);
+         if (base() == that.base()) {
+             return that.min() - this.min();
+         }
+         throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa).");
+     }
+ 
      @Override
      public void load() {
          throw new UnsupportedOperationException("Not a mapped segment");
      }
  

*** 288,49 ***
      public void force() {
          throw new UnsupportedOperationException("Not a mapped segment");
      }
  
      @Override
!     public final byte[] toByteArray() {
!         return toArray(byte[].class, 1, byte[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final short[] toShortArray() {
!         return toArray(short[].class, 2, short[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final char[] toCharArray() {
!         return toArray(char[].class, 2, char[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final int[] toIntArray() {
!         return toArray(int[].class, 4, int[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final float[] toFloatArray() {
!         return toArray(float[].class, 4, float[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final long[] toLongArray() {
!         return toArray(long[].class, 8, long[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final double[] toDoubleArray() {
!         return toArray(double[].class, 8, double[]::new, MemorySegment::ofArray);
      }
  
!     private <Z> Z toArray(Class<Z> arrayClass, int elemSize, IntFunction<Z> arrayFactory, Function<Z, MemorySegment> segmentFactory) {
!         int size = checkArraySize(arrayClass.getSimpleName(), elemSize);
          Z arr = arrayFactory.apply(size);
          MemorySegment arrSegment = segmentFactory.apply(arr);
!         arrSegment.copyFrom(this);
          return arr;
      }
  
      @Override
      public boolean isSmall() {
--- 302,49 ---
      public void force() {
          throw new UnsupportedOperationException("Not a mapped segment");
      }
  
      @Override
!     public final byte[] toArray(ValueLayout.OfByte elementLayout) {
!         return toArray(byte[].class, elementLayout, byte[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final short[] toArray(ValueLayout.OfShort elementLayout) {
!         return toArray(short[].class, elementLayout, short[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final char[] toArray(ValueLayout.OfChar elementLayout) {
!         return toArray(char[].class, elementLayout, char[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final int[] toArray(ValueLayout.OfInt elementLayout) {
!         return toArray(int[].class, elementLayout, int[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final float[] toArray(ValueLayout.OfFloat elementLayout) {
!         return toArray(float[].class, elementLayout, float[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final long[] toArray(ValueLayout.OfLong elementLayout) {
!         return toArray(long[].class, elementLayout, long[]::new, MemorySegment::ofArray);
      }
  
      @Override
!     public final double[] toArray(ValueLayout.OfDouble elementLayout) {
!         return toArray(double[].class, elementLayout, double[]::new, MemorySegment::ofArray);
      }
  
!     private <Z> Z toArray(Class<Z> arrayClass, ValueLayout elemLayout, IntFunction<Z> arrayFactory, Function<Z, MemorySegment> segmentFactory) {
!         int size = checkArraySize(arrayClass.getSimpleName(), (int)elemLayout.byteSize());
          Z arr = arrayFactory.apply(size);
          MemorySegment arrSegment = segmentFactory.apply(arr);
!         MemorySegment.copy(this, elemLayout, 0, arrSegment, elemLayout.withOrder(ByteOrder.nativeOrder()), 0, size);
          return arr;
      }
  
      @Override
      public boolean isSmall() {

*** 380,15 ***
          return (int)arraySize;
      }
  
      private void checkBounds(long offset, long length) {
          if (isSmall() &&
!                 offset < Integer.MAX_VALUE && length < Integer.MAX_VALUE &&
!                 offset > Integer.MIN_VALUE && length > Integer.MIN_VALUE) {
              checkBoundsSmall((int)offset, (int)length);
!         } else {
!             if (length < 0 ||
                      offset < 0 ||
                      offset > this.length - length) { // careful of overflow
                  throw outOfBoundException(offset, length);
              }
          }
--- 394,16 ---
          return (int)arraySize;
      }
  
      private void checkBounds(long offset, long length) {
          if (isSmall() &&
!                 offset <= Integer.MAX_VALUE && length <= Integer.MAX_VALUE &&
!                 offset >= Integer.MIN_VALUE && length >= Integer.MIN_VALUE) {
              checkBoundsSmall((int)offset, (int)length);
!         } else if (this != NativeMemorySegmentImpl.EVERYTHING) { // oob not possible for everything segment
!             if (
+                     length < 0 ||
                      offset < 0 ||
                      offset > this.length - length) { // careful of overflow
                  throw outOfBoundException(offset, length);
              }
          }
< prev index next >