< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java

Print this page
*** 22,21 ***
--- 22,24 ---
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  package jdk.internal.foreign.abi;
  
+ import jdk.incubator.foreign.Addressable;
  import jdk.incubator.foreign.MemoryAddress;
  import jdk.incubator.foreign.MemoryHandles;
  import jdk.incubator.foreign.MemoryLayout;
  import jdk.incubator.foreign.MemorySegment;
  import jdk.incubator.foreign.ResourceScope;
  import jdk.incubator.foreign.SegmentAllocator;
+ import jdk.incubator.foreign.ValueLayout;
  import jdk.internal.foreign.MemoryAddressImpl;
  import jdk.internal.foreign.ResourceScopeImpl;
  
  import java.lang.invoke.MethodHandle;
  import java.lang.invoke.MethodHandles;
+ import java.lang.invoke.MethodType;
  import java.util.ArrayList;
  import java.util.Deque;
  import java.util.List;
  import java.util.Objects;
  

*** 202,11 ***
   * --------------------
   */
  public abstract class Binding {
      private static final MethodHandle MH_UNBOX_ADDRESS;
      private static final MethodHandle MH_BOX_ADDRESS;
-     private static final MethodHandle MH_BASE_ADDRESS;
      private static final MethodHandle MH_COPY_BUFFER;
      private static final MethodHandle MH_ALLOCATE_BUFFER;
      private static final MethodHandle MH_TO_SEGMENT;
  
      static {
--- 205,10 ---

*** 214,12 ***
              MethodHandles.Lookup lookup = MethodHandles.lookup();
              MH_UNBOX_ADDRESS = lookup.findVirtual(MemoryAddress.class, "toRawLongValue",
                      methodType(long.class));
              MH_BOX_ADDRESS = lookup.findStatic(MemoryAddress.class, "ofLong",
                      methodType(MemoryAddress.class, long.class));
-             MH_BASE_ADDRESS = lookup.findVirtual(MemorySegment.class, "address",
-                     methodType(MemoryAddress.class));
              MH_COPY_BUFFER = lookup.findStatic(Binding.Copy.class, "copyBuffer",
                      methodType(MemorySegment.class, MemorySegment.class, long.class, long.class, Context.class));
              MH_ALLOCATE_BUFFER = lookup.findStatic(Binding.Allocate.class, "allocateBuffer",
                      methodType(MemorySegment.class, long.class, long.class, Context.class));
              MH_TO_SEGMENT = lookup.findStatic(Binding.ToSegment.class, "toSegment",
--- 216,10 ---

*** 260,11 ***
          /**
           * Create a binding context from given native scope.
           */
          public static Context ofBoundedAllocator(long size) {
              ResourceScope scope = ResourceScope.newConfinedScope();
!             return new Context(SegmentAllocator.arenaAllocator(size, scope), scope);
          }
  
          /**
           * Create a binding context from given segment allocator. The resulting context will throw when
           * the context's scope is accessed.
--- 260,11 ---
          /**
           * Create a binding context from given native scope.
           */
          public static Context ofBoundedAllocator(long size) {
              ResourceScope scope = ResourceScope.newConfinedScope();
!             return new Context(SegmentAllocator.newNativeArena(size, scope), scope);
          }
  
          /**
           * Create a binding context from given segment allocator. The resulting context will throw when
           * the context's scope is accessed.

*** 319,11 ***
          BUFFER_LOAD,
          COPY_BUFFER,
          ALLOC_BUFFER,
          BOX_ADDRESS,
          UNBOX_ADDRESS,
-         BASE_ADDRESS,
          TO_SEGMENT,
          DUP
      }
  
      private final Tag tag;
--- 319,10 ---

*** 342,11 ***
                                     BindingInterpreter.LoadFunc loadFunc, Context context);
  
      public abstract MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos);
  
      private static void checkType(Class<?> type) {
!         if (!type.isPrimitive() || type == void.class || type == boolean.class)
              throw new IllegalArgumentException("Illegal type: " + type);
      }
  
      private static void checkOffset(long offset) {
          if (offset < 0)
--- 341,11 ---
                                     BindingInterpreter.LoadFunc loadFunc, Context context);
  
      public abstract MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos);
  
      private static void checkType(Class<?> type) {
!         if (!type.isPrimitive() || type == void.class)
              throw new IllegalArgumentException("Illegal type: " + type);
      }
  
      private static void checkOffset(long offset) {
          if (offset < 0)

*** 386,15 ***
      public static BoxAddress boxAddress() {
          return BoxAddress.INSTANCE;
      }
  
      public static UnboxAddress unboxAddress() {
!         return UnboxAddress.INSTANCE;
      }
  
!     public static BaseAddress baseAddress() {
!         return BaseAddress.INSTANCE;
      }
  
      public static ToSegment toSegment(MemoryLayout layout) {
          return new ToSegment(layout.byteSize());
      }
--- 385,15 ---
      public static BoxAddress boxAddress() {
          return BoxAddress.INSTANCE;
      }
  
      public static UnboxAddress unboxAddress() {
!         return UnboxAddress.INSTANCE.get(MemoryAddress.class);
      }
  
!     public static UnboxAddress unboxAddress(Class<?> carrier) {
!         return UnboxAddress.INSTANCE.get(carrier);
      }
  
      public static ToSegment toSegment(MemoryLayout layout) {
          return new ToSegment(layout.byteSize());
      }

*** 465,12 ***
          public Binding.Builder unboxAddress() {
              bindings.add(Binding.unboxAddress());
              return this;
          }
  
!         public Binding.Builder baseAddress() {
!             bindings.add(Binding.baseAddress());
              return this;
          }
  
          public Binding.Builder toSegment(MemoryLayout layout) {
              bindings.add(Binding.toSegment(layout));
--- 464,12 ---
          public Binding.Builder unboxAddress() {
              bindings.add(Binding.unboxAddress());
              return this;
          }
  
!         public Binding.Builder unboxAddress(Class<?> carrier) {
!             bindings.add(Binding.unboxAddress(carrier));
              return this;
          }
  
          public Binding.Builder toSegment(MemoryLayout layout) {
              bindings.add(Binding.toSegment(layout));

*** 628,11 ***
  
          public VarHandle varHandle() {
              // alignment is set to 1 byte here to avoid exceptions for cases where we do super word
              // copies of e.g. 2 int fields of a struct as a single long, while the struct is only
              // 4-byte-aligned (since it only contains ints)
!             return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(type, 1, ByteOrder.nativeOrder()), 1, offset);
          }
      }
  
      /**
       * BUFFER_STORE([offset into memory region], [type])
--- 627,12 ---
  
          public VarHandle varHandle() {
              // alignment is set to 1 byte here to avoid exceptions for cases where we do super word
              // copies of e.g. 2 int fields of a struct as a single long, while the struct is only
              // 4-byte-aligned (since it only contains ints)
!             ValueLayout layout = MemoryLayout.valueLayout(type(), ByteOrder.nativeOrder()).withBitAlignment(8);
+             return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(layout), 1, offset);
          }
      }
  
      /**
       * BUFFER_STORE([offset into memory region], [type])

*** 738,13 ***
              this.alignment = alignment;
          }
  
          private static MemorySegment copyBuffer(MemorySegment operand, long size, long alignment,
                                                      Context context) {
!             MemorySegment copy = context.allocator().allocate(size, alignment);
!             copy.copyFrom(operand.asSlice(0, size));
-             return copy;
          }
  
          public long size() {
              return size;
          }
--- 738,12 ---
              this.alignment = alignment;
          }
  
          private static MemorySegment copyBuffer(MemorySegment operand, long size, long alignment,
                                                      Context context) {
!             return context.allocator().allocate(size, alignment)
!                             .copyFrom(operand.asSlice(0, size));
          }
  
          public long size() {
              return size;
          }

*** 873,31 ***
       * UNBOX_ADDRESS()
       * Pops a 'MemoryAddress' from the operand stack, converts it to a 'long',
       *     and pushes that onto the operand stack.
       */
      public static class UnboxAddress extends Binding {
!         private static final UnboxAddress INSTANCE = new UnboxAddress();
!         private UnboxAddress() {
              super(Tag.UNBOX_ADDRESS);
          }
  
          @Override
          public void verify(Deque<Class<?>> stack) {
              Class<?> actualType = stack.pop();
!             SharedUtils.checkType(actualType, MemoryAddress.class);
              stack.push(long.class);
          }
  
          @Override
          public void interpret(Deque<Object> stack, BindingInterpreter.StoreFunc storeFunc,
                                BindingInterpreter.LoadFunc loadFunc, Context context) {
!             stack.push(((MemoryAddress)stack.pop()).toRawLongValue());
          }
  
          @Override
          public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) {
!             return filterArguments(specializedHandle, insertPos, MH_UNBOX_ADDRESS);
          }
  
          @Override
          public String toString() {
              return "UnboxAddress{}";
--- 872,48 ---
       * UNBOX_ADDRESS()
       * Pops a 'MemoryAddress' from the operand stack, converts it to a 'long',
       *     and pushes that onto the operand stack.
       */
      public static class UnboxAddress extends Binding {
! 
!         static final ClassValue<UnboxAddress> INSTANCE = new ClassValue<>() {
+             @Override
+             protected UnboxAddress computeValue(Class<?> type) {
+                 return new UnboxAddress(type);
+             }
+         };
+ 
+         final Class<?> carrier;
+         final MethodHandle toAddress;
+ 
+         private UnboxAddress(Class<?> carrier) {
              super(Tag.UNBOX_ADDRESS);
+             this.carrier = carrier;
+             try {
+                 this.toAddress = MethodHandles.lookup().findVirtual(carrier, "address", MethodType.methodType(MemoryAddress.class));
+             } catch (Throwable ex) {
+                 throw new IllegalArgumentException(ex);
+             }
          }
  
          @Override
          public void verify(Deque<Class<?>> stack) {
              Class<?> actualType = stack.pop();
!             SharedUtils.checkType(actualType, carrier);
              stack.push(long.class);
          }
  
          @Override
          public void interpret(Deque<Object> stack, BindingInterpreter.StoreFunc storeFunc,
                                BindingInterpreter.LoadFunc loadFunc, Context context) {
!             stack.push(((Addressable)stack.pop()).address().toRawLongValue());
          }
  
          @Override
          public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) {
!             return filterArguments(specializedHandle, insertPos,
+                     MethodHandles.filterReturnValue(toAddress, MH_UNBOX_ADDRESS));
          }
  
          @Override
          public String toString() {
              return "UnboxAddress{}";

*** 937,45 ***
          public String toString() {
              return "BoxAddress{}";
          }
      }
  
-     /**
-      * BASE_ADDRESS()
-      *   Pops a MemorySegment from the operand stack, and takes the base address of the segment
-      *   (the MemoryAddress that points to the start), and pushes that onto the operand stack
-      */
-     public static class BaseAddress extends Binding {
-         private static final BaseAddress INSTANCE = new BaseAddress();
-         private BaseAddress() {
-             super(Tag.BASE_ADDRESS);
-         }
- 
-         @Override
-         public void verify(Deque<Class<?>> stack) {
-             Class<?> actualType = stack.pop();
-             SharedUtils.checkType(actualType, MemorySegment.class);
-             stack.push(MemoryAddress.class);
-         }
- 
-         @Override
-         public void interpret(Deque<Object> stack, BindingInterpreter.StoreFunc storeFunc,
-                               BindingInterpreter.LoadFunc loadFunc, Context context) {
-             stack.push(((MemorySegment) stack.pop()).address());
-         }
- 
-         @Override
-         public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) {
-             return filterArguments(specializedHandle, insertPos, MH_BASE_ADDRESS);
-         }
- 
-         @Override
-         public String toString() {
-             return "BaseAddress{}";
-         }
-     }
- 
      /**
       * TO_SEGMENT([size])
       *   Pops a MemoryAddress from the operand stack, and converts it to a MemorySegment
       *   with the given size, and pushes that onto the operand stack
       */
--- 953,10 ---
< prev index next >