< 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 +205,10 @@
   * --------------------
   */
  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 {

@@ -214,12 +216,10 @@
              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",

@@ -260,11 +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);
+             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 +319,10 @@
          BUFFER_LOAD,
          COPY_BUFFER,
          ALLOC_BUFFER,
          BOX_ADDRESS,
          UNBOX_ADDRESS,
-         BASE_ADDRESS,
          TO_SEGMENT,
          DUP
      }
  
      private final Tag tag;

@@ -342,11 +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 || type == boolean.class)
+         if (!type.isPrimitive() || type == void.class)
              throw new IllegalArgumentException("Illegal type: " + type);
      }
  
      private static void checkOffset(long offset) {
          if (offset < 0)

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

@@ -465,12 +464,12 @@
          public Binding.Builder unboxAddress() {
              bindings.add(Binding.unboxAddress());
              return this;
          }
  
-         public Binding.Builder baseAddress() {
-             bindings.add(Binding.baseAddress());
+         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 +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)
-             return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(type, 1, ByteOrder.nativeOrder()), 1, offset);
+             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 +738,12 @@
              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;
+             return context.allocator().allocate(size, alignment)
+                             .copyFrom(operand.asSlice(0, size));
          }
  
          public long size() {
              return size;
          }

@@ -873,31 +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 {
-         private static final UnboxAddress INSTANCE = new UnboxAddress();
-         private UnboxAddress() {
+ 
+         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, MemoryAddress.class);
+             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(((MemoryAddress)stack.pop()).toRawLongValue());
+             stack.push(((Addressable)stack.pop()).address().toRawLongValue());
          }
  
          @Override
          public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) {
-             return filterArguments(specializedHandle, insertPos, MH_UNBOX_ADDRESS);
+             return filterArguments(specializedHandle, insertPos,
+                     MethodHandles.filterReturnValue(toAddress, MH_UNBOX_ADDRESS));
          }
  
          @Override
          public String toString() {
              return "UnboxAddress{}";

@@ -937,45 +953,10 @@
          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
       */
< prev index next >