< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java

Print this page
@@ -24,36 +24,35 @@
   * questions.
   */
  package jdk.internal.foreign.abi.aarch64.linux;
  
  import jdk.incubator.foreign.*;
+ import jdk.internal.foreign.ResourceScopeImpl;
+ import jdk.internal.foreign.Scoped;
  import jdk.internal.foreign.Utils;
  import jdk.internal.foreign.abi.SharedUtils;
  import jdk.internal.foreign.abi.aarch64.*;
  import jdk.internal.misc.Unsafe;
  
  import java.lang.invoke.VarHandle;
  import java.lang.ref.Cleaner;
- import java.nio.ByteOrder;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Objects;
  
  import static jdk.internal.foreign.PlatformLayouts.AArch64;
- import static jdk.incubator.foreign.CLinker.VaList;
+ 
  import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement;
  import static jdk.internal.foreign.abi.SharedUtils.SimpleVaArg;
  import static jdk.internal.foreign.abi.SharedUtils.THROWING_ALLOCATOR;
- import static jdk.internal.foreign.abi.SharedUtils.checkCompatibleType;
- import static jdk.internal.foreign.abi.SharedUtils.vhPrimitiveOrAddress;
  import static jdk.internal.foreign.abi.aarch64.CallArranger.MAX_REGISTER_ARGUMENTS;
  
  /**
   * Standard va_list implementation as defined by AAPCS document and used on
   * Linux. Variadic parameters may be passed in registers or on the stack.
   */
- public non-sealed class LinuxAArch64VaList implements VaList {
+ public non-sealed class LinuxAArch64VaList implements VaList, Scoped {
      private static final Unsafe U = Unsafe.getUnsafe();
  
      static final Class<?> CARRIER = MemoryAddress.class;
  
      // See AAPCS Appendix B "Variable Argument Lists" for definition of

@@ -74,13 +73,13 @@
          AArch64.C_INT.withName("__gr_offs"),
          AArch64.C_INT.withName("__vr_offs")
      ).withName("__va_list");
  
      private static final MemoryLayout GP_REG
-         = MemoryLayout.valueLayout(64, ByteOrder.nativeOrder());
+         = MemoryLayout.paddingLayout(64).withBitAlignment(64);
      private static final MemoryLayout FP_REG
-         = MemoryLayout.valueLayout(128, ByteOrder.nativeOrder());
+         = MemoryLayout.paddingLayout(128).withBitAlignment(128);
  
      private static final MemoryLayout LAYOUT_GP_REGS
          = MemoryLayout.sequenceLayout(MAX_REGISTER_ARGUMENTS, GP_REG);
      private static final MemoryLayout LAYOUT_FP_REGS
          = MemoryLayout.sequenceLayout(MAX_REGISTER_ARGUMENTS, FP_REG);

@@ -89,22 +88,18 @@
      private static final int FP_SLOT_SIZE = (int) FP_REG.byteSize();
  
      private static final int MAX_GP_OFFSET = (int) LAYOUT_GP_REGS.byteSize();
      private static final int MAX_FP_OFFSET = (int) LAYOUT_FP_REGS.byteSize();
  
-     private static final VarHandle VH_stack
-         = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__stack")));
-     private static final VarHandle VH_gr_top
-         = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__gr_top")));
-     private static final VarHandle VH_vr_top
-         = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__vr_top")));
+     private static final VarHandle VH_stack = LAYOUT.varHandle(groupElement("__stack"));
+     private static final VarHandle VH_gr_top = LAYOUT.varHandle(groupElement("__gr_top"));
+     private static final VarHandle VH_vr_top = LAYOUT.varHandle(groupElement("__vr_top"));
      private static final VarHandle VH_gr_offs
-         = LAYOUT.varHandle(int.class, groupElement("__gr_offs"));
+         = LAYOUT.varHandle(groupElement("__gr_offs"));
      private static final VarHandle VH_vr_offs
-         = LAYOUT.varHandle(int.class, groupElement("__vr_offs"));
+         = LAYOUT.varHandle(groupElement("__vr_offs"));
  
-     private static final Cleaner cleaner = Cleaner.create();
      private static final VaList EMPTY
          = new SharedUtils.EmptyVaList(emptyListAddress());
  
      private final MemorySegment segment;
      private final MemorySegment gpRegsArea;

@@ -115,23 +110,24 @@
          this.gpRegsArea = gpRegsArea;
          this.fpRegsArea = fpRegsArea;
      }
  
      private static LinuxAArch64VaList readFromSegment(MemorySegment segment) {
-         MemorySegment gpRegsArea = grTop(segment).addOffset(-MAX_GP_OFFSET).asSegment(
+         MemorySegment gpRegsArea = MemorySegment.ofAddressNative(grTop(segment).addOffset(-MAX_GP_OFFSET),
                  MAX_GP_OFFSET, segment.scope());
  
-         MemorySegment fpRegsArea = vrTop(segment).addOffset(-MAX_FP_OFFSET).asSegment(
+         MemorySegment fpRegsArea = MemorySegment.ofAddressNative(vrTop(segment).addOffset(-MAX_FP_OFFSET),
                  MAX_FP_OFFSET, segment.scope());
          return new LinuxAArch64VaList(segment, gpRegsArea, fpRegsArea);
      }
  
      private static MemoryAddress emptyListAddress() {
          long ptr = U.allocateMemory(LAYOUT.byteSize());
-         MemorySegment ms = MemoryAddress.ofLong(ptr).asSegment(
-                 LAYOUT.byteSize(), () -> U.freeMemory(ptr), ResourceScope.newSharedScope());
-         cleaner.register(LinuxAArch64VaList.class, () -> ms.scope().close());
+         ResourceScope scope = ResourceScope.newImplicitScope();
+         scope.addCloseAction(() -> U.freeMemory(ptr));
+         MemorySegment ms = MemorySegment.ofAddressNative(MemoryAddress.ofLong(ptr),
+                 LAYOUT.byteSize(), scope);
          VH_stack.set(ms, MemoryAddress.NULL);
          VH_gr_top.set(ms, MemoryAddress.NULL);
          VH_vr_top.set(ms, MemoryAddress.NULL);
          VH_gr_offs.set(ms, 0);
          VH_vr_offs.set(ms, 0);

@@ -213,62 +209,55 @@
      private void postAlignStack(MemoryLayout layout) {
          stackPtr(Utils.alignUp(stackPtr().addOffset(layout.byteSize()), 8));
      }
  
      @Override
-     public int vargAsInt(MemoryLayout layout) {
+     public int nextVarg(ValueLayout.OfInt layout) {
          return (int) read(int.class, layout);
      }
  
      @Override
-     public long vargAsLong(MemoryLayout layout) {
+     public long nextVarg(ValueLayout.OfLong layout) {
          return (long) read(long.class, layout);
      }
  
      @Override
-     public double vargAsDouble(MemoryLayout layout) {
+     public double nextVarg(ValueLayout.OfDouble layout) {
          return (double) read(double.class, layout);
      }
  
      @Override
-     public MemoryAddress vargAsAddress(MemoryLayout layout) {
+     public MemoryAddress nextVarg(ValueLayout.OfAddress layout) {
          return (MemoryAddress) read(MemoryAddress.class, layout);
      }
  
      @Override
-     public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) {
+     public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) {
          Objects.requireNonNull(allocator);
          return (MemorySegment) read(MemorySegment.class, layout, allocator);
      }
  
-     @Override
-     public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) {
-         return vargAsSegment(layout, SegmentAllocator.ofScope(scope));
-     }
- 
      private Object read(Class<?> carrier, MemoryLayout layout) {
          return read(carrier, layout, THROWING_ALLOCATOR);
      }
  
      private Object read(Class<?> carrier, MemoryLayout layout, SegmentAllocator allocator) {
          Objects.requireNonNull(layout);
-         checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE);
- 
          TypeClass typeClass = TypeClass.classifyLayout(layout);
          if (isRegOverflow(currentGPOffset(), currentFPOffset(), typeClass, layout)) {
              preAlignStack(layout);
              return switch (typeClass) {
                  case STRUCT_REGISTER, STRUCT_HFA, STRUCT_REFERENCE -> {
-                     MemorySegment slice = stackPtr().asSegment(layout.byteSize(), scope());
+                     MemorySegment slice = MemorySegment.ofAddressNative(stackPtr(), layout.byteSize(), scope());
                      MemorySegment seg = allocator.allocate(layout);
                      seg.copyFrom(slice);
                      postAlignStack(layout);
                      yield seg;
                  }
                  case POINTER, INTEGER, FLOAT -> {
-                     VarHandle reader = vhPrimitiveOrAddress(carrier, layout);
-                     MemorySegment slice = stackPtr().asSegment(layout.byteSize(), scope());
+                     VarHandle reader = layout.varHandle();
+                     MemorySegment slice = MemorySegment.ofAddressNative(stackPtr(), layout.byteSize(), scope());
                      Object res = reader.get(slice);
                      postAlignStack(layout);
                      yield res;
                  }
              };

@@ -278,12 +267,11 @@
                      // Struct is passed packed in integer registers.
                      MemorySegment value = allocator.allocate(layout);
                      long offset = 0;
                      while (offset < layout.byteSize()) {
                          final long copy = Math.min(layout.byteSize() - offset, 8);
-                         MemorySegment slice = value.asSlice(offset, copy);
-                         slice.copyFrom(gpRegsArea.asSlice(currentGPOffset(), copy));
+                         MemorySegment.copy(gpRegsArea, currentGPOffset(), value, offset, copy);
                          consumeGPSlots(1);
                          offset += copy;
                      }
                      yield value;
                  }

@@ -294,38 +282,36 @@
                      GroupLayout group = (GroupLayout)layout;
                      long offset = 0;
                      for (MemoryLayout elem : group.memberLayouts()) {
                          assert elem.byteSize() <= 8;
                          final long copy = elem.byteSize();
-                         MemorySegment slice = value.asSlice(offset, copy);
-                         slice.copyFrom(fpRegsArea.asSlice(currentFPOffset(), copy));
+                         MemorySegment.copy(fpRegsArea, currentFPOffset(), value, offset, copy);
                          consumeFPSlots(1);
                          offset += copy;
                      }
                      yield value;
                  }
                  case STRUCT_REFERENCE -> {
                      // Struct is passed indirectly via a pointer in an integer register.
-                     VarHandle ptrReader
-                         = SharedUtils.vhPrimitiveOrAddress(MemoryAddress.class, AArch64.C_POINTER);
+                     VarHandle ptrReader = AArch64.C_POINTER.varHandle();
                      MemoryAddress ptr = (MemoryAddress) ptrReader.get(
                          gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
  
-                     MemorySegment slice = ptr.asSegment(layout.byteSize(), scope());
+                     MemorySegment slice = MemorySegment.ofAddressNative(ptr, layout.byteSize(), scope());
                      MemorySegment seg = allocator.allocate(layout);
                      seg.copyFrom(slice);
                      yield seg;
                  }
                  case POINTER, INTEGER -> {
-                     VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
+                     VarHandle reader = layout.varHandle();
                      Object res = reader.get(gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
                      yield res;
                  }
                  case FLOAT -> {
-                     VarHandle reader = layout.varHandle(carrier);
+                     VarHandle reader = layout.varHandle();
                      Object res = reader.get(fpRegsArea.asSlice(currentFPOffset()));
                      consumeFPSlots(1);
                      yield res;
                  }
              };

@@ -333,10 +319,11 @@
      }
  
      @Override
      public void skip(MemoryLayout... layouts) {
          Objects.requireNonNull(layouts);
+         ((ResourceScopeImpl)segment.scope()).checkValidStateSlow();
          for (MemoryLayout layout : layouts) {
              Objects.requireNonNull(layout);
              TypeClass typeClass = TypeClass.classifyLayout(layout);
              if (isRegOverflow(currentGPOffset(), currentFPOffset(), typeClass, layout)) {
                  preAlignStack(layout);

@@ -354,11 +341,11 @@
      static LinuxAArch64VaList.Builder builder(ResourceScope scope) {
          return new LinuxAArch64VaList.Builder(scope);
      }
  
      public static VaList ofAddress(MemoryAddress ma, ResourceScope scope) {
-         return readFromSegment(ma.asSegment(LAYOUT.byteSize(), scope));
+         return readFromSegment(MemorySegment.ofAddressNative(ma, LAYOUT.byteSize(), scope));
      }
  
      @Override
      public ResourceScope scope() {
          return segment.scope();

@@ -416,39 +403,37 @@
              this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, scope);
              this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, scope);
          }
  
          @Override
-         public Builder vargFromInt(ValueLayout layout, int value) {
+         public Builder addVarg(ValueLayout.OfInt layout, int value) {
              return arg(int.class, layout, value);
          }
  
          @Override
-         public Builder vargFromLong(ValueLayout layout, long value) {
+         public Builder addVarg(ValueLayout.OfLong layout, long value) {
              return arg(long.class, layout, value);
          }
  
          @Override
-         public Builder vargFromDouble(ValueLayout layout, double value) {
+         public Builder addVarg(ValueLayout.OfDouble layout, double value) {
              return arg(double.class, layout, value);
          }
  
          @Override
-         public Builder vargFromAddress(ValueLayout layout, Addressable value) {
+         public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) {
              return arg(MemoryAddress.class, layout, value.address());
          }
  
          @Override
-         public Builder vargFromSegment(GroupLayout layout, MemorySegment value) {
+         public Builder addVarg(GroupLayout layout, MemorySegment value) {
              return arg(MemorySegment.class, layout, value);
          }
  
          private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
              Objects.requireNonNull(layout);
              Objects.requireNonNull(value);
-             checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE);
- 
              TypeClass typeClass = TypeClass.classifyLayout(layout);
              if (isRegOverflow(currentGPOffset, currentFPOffset, typeClass, layout)) {
                  stackArgs.add(new SimpleVaArg(carrier, layout, value));
              } else {
                  switch (typeClass) {

@@ -456,12 +441,11 @@
                          // Struct is passed packed in integer registers.
                          MemorySegment valueSegment = (MemorySegment) value;
                          long offset = 0;
                          while (offset < layout.byteSize()) {
                              final long copy = Math.min(layout.byteSize() - offset, 8);
-                             MemorySegment slice = valueSegment.asSlice(offset, copy);
-                             gpRegs.asSlice(currentGPOffset, copy).copyFrom(slice);
+                             MemorySegment.copy(valueSegment, offset, gpRegs, currentGPOffset, copy);
                              currentGPOffset += GP_SLOT_SIZE;
                              offset += copy;
                          }
                      }
                      case STRUCT_HFA -> {

@@ -471,33 +455,30 @@
                          GroupLayout group = (GroupLayout)layout;
                          long offset = 0;
                          for (MemoryLayout elem : group.memberLayouts()) {
                              assert elem.byteSize() <= 8;
                              final long copy = elem.byteSize();
-                             MemorySegment slice = valueSegment.asSlice(offset, copy);
-                             fpRegs.asSlice(currentFPOffset, copy).copyFrom(slice);
+                             MemorySegment.copy(valueSegment, offset, fpRegs, currentFPOffset, copy);
                              currentFPOffset += FP_SLOT_SIZE;
                              offset += copy;
                          }
                      }
                      case STRUCT_REFERENCE -> {
                          // Struct is passed indirectly via a pointer in an integer register.
                          MemorySegment valueSegment = (MemorySegment) value;
-                         VarHandle writer
-                             = SharedUtils.vhPrimitiveOrAddress(MemoryAddress.class,
-                                                                AArch64.C_POINTER);
+                         VarHandle writer = AArch64.C_POINTER.varHandle();
                          writer.set(gpRegs.asSlice(currentGPOffset),
                                     valueSegment.address());
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case POINTER, INTEGER -> {
-                         VarHandle writer = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
+                         VarHandle writer = layout.varHandle();
                          writer.set(gpRegs.asSlice(currentGPOffset), value);
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case FLOAT -> {
-                         VarHandle writer = layout.varHandle(carrier);
+                         VarHandle writer = layout.varHandle();
                          writer.set(fpRegs.asSlice(currentFPOffset), value);
                          currentFPOffset += FP_SLOT_SIZE;
                      }
                  }
              }

@@ -511,11 +492,11 @@
          public VaList build() {
              if (isEmpty()) {
                  return EMPTY;
              }
  
-             SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope);
+             SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope);
              MemorySegment vaListSegment = allocator.allocate(LAYOUT);
              MemoryAddress stackArgsPtr = MemoryAddress.NULL;
              if (!stackArgs.isEmpty()) {
                  long stackArgsSize = stackArgs.stream()
                      .reduce(0L, (acc, e) -> acc + Utils.alignUp(e.layout.byteSize(), 8), Long::sum);
< prev index next >