< prev index next >

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

Print this page
*** 24,36 ***
   * questions.
   */
  package jdk.internal.foreign.abi.aarch64.linux;
  
  import jdk.incubator.foreign.*;
  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 {
      private static final Unsafe U = Unsafe.getUnsafe();
  
      static final Class<?> CARRIER = MemoryAddress.class;
  
      // See AAPCS Appendix B "Variable Argument Lists" for definition of
--- 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.util.ArrayList;
  import java.util.List;
  import java.util.Objects;
  
  import static jdk.internal.foreign.PlatformLayouts.AArch64;
! 
  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.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, 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 ***
          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());
      private static final MemoryLayout FP_REG
!         = MemoryLayout.valueLayout(128, ByteOrder.nativeOrder());
  
      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);
--- 73,13 ---
          AArch64.C_INT.withName("__gr_offs"),
          AArch64.C_INT.withName("__vr_offs")
      ).withName("__va_list");
  
      private static final MemoryLayout GP_REG
!         = MemoryLayout.paddingLayout(64).withBitAlignment(64);
      private static final MemoryLayout FP_REG
!         = 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 ***
      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_gr_offs
!         = LAYOUT.varHandle(int.class, groupElement("__gr_offs"));
      private static final VarHandle VH_vr_offs
!         = LAYOUT.varHandle(int.class, 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;
--- 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 = 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(groupElement("__gr_offs"));
      private static final VarHandle VH_vr_offs
!         = LAYOUT.varHandle(groupElement("__vr_offs"));
  
      private static final VaList EMPTY
          = new SharedUtils.EmptyVaList(emptyListAddress());
  
      private final MemorySegment segment;
      private final MemorySegment gpRegsArea;

*** 115,23 ***
          this.gpRegsArea = gpRegsArea;
          this.fpRegsArea = fpRegsArea;
      }
  
      private static LinuxAArch64VaList readFromSegment(MemorySegment segment) {
!         MemorySegment gpRegsArea = grTop(segment).addOffset(-MAX_GP_OFFSET).asSegment(
                  MAX_GP_OFFSET, segment.scope());
  
!         MemorySegment fpRegsArea = vrTop(segment).addOffset(-MAX_FP_OFFSET).asSegment(
                  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());
          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);
--- 110,24 ---
          this.gpRegsArea = gpRegsArea;
          this.fpRegsArea = fpRegsArea;
      }
  
      private static LinuxAArch64VaList readFromSegment(MemorySegment segment) {
!         MemorySegment gpRegsArea = MemorySegment.ofAddressNative(grTop(segment).addOffset(-MAX_GP_OFFSET),
                  MAX_GP_OFFSET, segment.scope());
  
!         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());
!         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 ***
      private void postAlignStack(MemoryLayout layout) {
          stackPtr(Utils.alignUp(stackPtr().addOffset(layout.byteSize()), 8));
      }
  
      @Override
!     public int vargAsInt(MemoryLayout layout) {
          return (int) read(int.class, layout);
      }
  
      @Override
!     public long vargAsLong(MemoryLayout layout) {
          return (long) read(long.class, layout);
      }
  
      @Override
!     public double vargAsDouble(MemoryLayout layout) {
          return (double) read(double.class, layout);
      }
  
      @Override
!     public MemoryAddress vargAsAddress(MemoryLayout layout) {
          return (MemoryAddress) read(MemoryAddress.class, layout);
      }
  
      @Override
!     public MemorySegment vargAsSegment(MemoryLayout 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 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());
                      Object res = reader.get(slice);
                      postAlignStack(layout);
                      yield res;
                  }
              };
--- 209,55 ---
      private void postAlignStack(MemoryLayout layout) {
          stackPtr(Utils.alignUp(stackPtr().addOffset(layout.byteSize()), 8));
      }
  
      @Override
!     public int nextVarg(ValueLayout.OfInt layout) {
          return (int) read(int.class, layout);
      }
  
      @Override
!     public long nextVarg(ValueLayout.OfLong layout) {
          return (long) read(long.class, layout);
      }
  
      @Override
!     public double nextVarg(ValueLayout.OfDouble layout) {
          return (double) read(double.class, layout);
      }
  
      @Override
!     public MemoryAddress nextVarg(ValueLayout.OfAddress layout) {
          return (MemoryAddress) read(MemoryAddress.class, layout);
      }
  
      @Override
!     public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) {
          Objects.requireNonNull(allocator);
          return (MemorySegment) read(MemorySegment.class, layout, allocator);
      }
  
      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);
          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 = MemorySegment.ofAddressNative(stackPtr(), layout.byteSize(), scope());
                      MemorySegment seg = allocator.allocate(layout);
                      seg.copyFrom(slice);
                      postAlignStack(layout);
                      yield seg;
                  }
                  case POINTER, INTEGER, FLOAT -> {
!                     VarHandle reader = layout.varHandle();
!                     MemorySegment slice = MemorySegment.ofAddressNative(stackPtr(), layout.byteSize(), scope());
                      Object res = reader.get(slice);
                      postAlignStack(layout);
                      yield res;
                  }
              };

*** 278,12 ***
                      // 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));
                          consumeGPSlots(1);
                          offset += copy;
                      }
                      yield value;
                  }
--- 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.copy(gpRegsArea, currentGPOffset(), value, offset, copy);
                          consumeGPSlots(1);
                          offset += copy;
                      }
                      yield value;
                  }

*** 294,38 ***
                      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));
                          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);
                      MemoryAddress ptr = (MemoryAddress) ptrReader.get(
                          gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
  
!                     MemorySegment slice = ptr.asSegment(layout.byteSize(), scope());
                      MemorySegment seg = allocator.allocate(layout);
                      seg.copyFrom(slice);
                      yield seg;
                  }
                  case POINTER, INTEGER -> {
!                     VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
                      Object res = reader.get(gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
                      yield res;
                  }
                  case FLOAT -> {
!                     VarHandle reader = layout.varHandle(carrier);
                      Object res = reader.get(fpRegsArea.asSlice(currentFPOffset()));
                      consumeFPSlots(1);
                      yield res;
                  }
              };
--- 282,36 ---
                      GroupLayout group = (GroupLayout)layout;
                      long offset = 0;
                      for (MemoryLayout elem : group.memberLayouts()) {
                          assert elem.byteSize() <= 8;
                          final long copy = elem.byteSize();
!                         MemorySegment.copy(gpRegsArea, 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 = AArch64.C_POINTER.varHandle();
                      MemoryAddress ptr = (MemoryAddress) ptrReader.get(
                          gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
  
!                     MemorySegment slice = MemorySegment.ofAddressNative(ptr, layout.byteSize(), scope());
                      MemorySegment seg = allocator.allocate(layout);
                      seg.copyFrom(slice);
                      yield seg;
                  }
                  case POINTER, INTEGER -> {
!                     VarHandle reader = layout.varHandle();
                      Object res = reader.get(gpRegsArea.asSlice(currentGPOffset()));
                      consumeGPSlots(1);
                      yield res;
                  }
                  case FLOAT -> {
!                     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 ***
      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));
      }
  
      @Override
      public ResourceScope scope() {
          return segment.scope();
--- 341,11 ---
      static LinuxAArch64VaList.Builder builder(ResourceScope scope) {
          return new LinuxAArch64VaList.Builder(scope);
      }
  
      public static VaList ofAddress(MemoryAddress ma, ResourceScope scope) {
!         return readFromSegment(MemorySegment.ofAddressNative(ma, LAYOUT.byteSize(), scope));
      }
  
      @Override
      public ResourceScope scope() {
          return segment.scope();

*** 416,39 ***
              this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, scope);
              this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, scope);
          }
  
          @Override
!         public Builder vargFromInt(ValueLayout layout, int value) {
              return arg(int.class, layout, value);
          }
  
          @Override
!         public Builder vargFromLong(ValueLayout layout, long value) {
              return arg(long.class, layout, value);
          }
  
          @Override
!         public Builder vargFromDouble(ValueLayout layout, double value) {
              return arg(double.class, layout, value);
          }
  
          @Override
!         public Builder vargFromAddress(ValueLayout layout, Addressable value) {
              return arg(MemoryAddress.class, layout, value.address());
          }
  
          @Override
!         public Builder vargFromSegment(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) {
--- 403,37 ---
              this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, scope);
              this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, scope);
          }
  
          @Override
!         public Builder addVarg(ValueLayout.OfInt layout, int value) {
              return arg(int.class, layout, value);
          }
  
          @Override
!         public Builder addVarg(ValueLayout.OfLong layout, long value) {
              return arg(long.class, layout, value);
          }
  
          @Override
!         public Builder addVarg(ValueLayout.OfDouble layout, double value) {
              return arg(double.class, layout, value);
          }
  
          @Override
!         public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) {
              return arg(MemoryAddress.class, layout, value.address());
          }
  
          @Override
!         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);
              TypeClass typeClass = TypeClass.classifyLayout(layout);
              if (isRegOverflow(currentGPOffset, currentFPOffset, typeClass, layout)) {
                  stackArgs.add(new SimpleVaArg(carrier, layout, value));
              } else {
                  switch (typeClass) {

*** 456,12 ***
                          // 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);
                              currentGPOffset += GP_SLOT_SIZE;
                              offset += copy;
                          }
                      }
                      case STRUCT_HFA -> {
--- 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.copy(valueSegment, offset, gpRegs, currentGPOffset, copy);
                              currentGPOffset += GP_SLOT_SIZE;
                              offset += copy;
                          }
                      }
                      case STRUCT_HFA -> {

*** 471,33 ***
                          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);
                              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);
                          writer.set(gpRegs.asSlice(currentGPOffset),
                                     valueSegment.address());
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case POINTER, INTEGER -> {
!                         VarHandle writer = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
                          writer.set(gpRegs.asSlice(currentGPOffset), value);
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case FLOAT -> {
!                         VarHandle writer = layout.varHandle(carrier);
                          writer.set(fpRegs.asSlice(currentFPOffset), value);
                          currentFPOffset += FP_SLOT_SIZE;
                      }
                  }
              }
--- 455,30 ---
                          GroupLayout group = (GroupLayout)layout;
                          long offset = 0;
                          for (MemoryLayout elem : group.memberLayouts()) {
                              assert elem.byteSize() <= 8;
                              final long copy = elem.byteSize();
!                             MemorySegment.copy(valueSegment, offset, gpRegs, 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 = AArch64.C_POINTER.varHandle();
                          writer.set(gpRegs.asSlice(currentGPOffset),
                                     valueSegment.address());
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case POINTER, INTEGER -> {
!                         VarHandle writer = layout.varHandle();
                          writer.set(gpRegs.asSlice(currentGPOffset), value);
                          currentGPOffset += GP_SLOT_SIZE;
                      }
                      case FLOAT -> {
!                         VarHandle writer = layout.varHandle();
                          writer.set(fpRegs.asSlice(currentFPOffset), value);
                          currentFPOffset += FP_SLOT_SIZE;
                      }
                  }
              }

*** 511,11 ***
          public VaList build() {
              if (isEmpty()) {
                  return EMPTY;
              }
  
!             SegmentAllocator allocator = SegmentAllocator.arenaAllocator(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);
--- 492,11 ---
          public VaList build() {
              if (isEmpty()) {
                  return EMPTY;
              }
  
!             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 >