< prev index next >

src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java

Print this page
*** 35,17 ***
  import java.lang.foreign.StructLayout;
  import java.lang.foreign.UnionLayout;
  import java.lang.foreign.ValueLayout;
  import java.lang.invoke.VarHandle;
  import java.util.Collections;
- import java.util.Comparator;
  import java.util.List;
  import java.util.Map;
  import java.util.Objects;
  import java.util.function.Predicate;
  
  import static java.lang.foreign.ValueLayout.ADDRESS;
  import static java.lang.foreign.ValueLayout.JAVA_INT;
  import static java.lang.foreign.ValueLayout.JAVA_LONG;
  import static java.lang.foreign.ValueLayout.JAVA_SHORT;
  
  /**
--- 35,17 ---
  import java.lang.foreign.StructLayout;
  import java.lang.foreign.UnionLayout;
  import java.lang.foreign.ValueLayout;
  import java.lang.invoke.VarHandle;
  import java.util.Collections;
  import java.util.List;
  import java.util.Map;
  import java.util.Objects;
  import java.util.function.Predicate;
  
  import static java.lang.foreign.ValueLayout.ADDRESS;
+ import static java.lang.foreign.ValueLayout.JAVA_BYTE;
  import static java.lang.foreign.ValueLayout.JAVA_INT;
  import static java.lang.foreign.ValueLayout.JAVA_LONG;
  import static java.lang.foreign.ValueLayout.JAVA_SHORT;
  
  /**

*** 56,22 ***
   *   unsigned short type;
   *   struct _ffi_type **elements;
   * } ffi_type;
   */
  class FFIType {
!     private static final ValueLayout SIZE_T = switch ((int) ADDRESS.byteSize()) {
-             case 8 -> JAVA_LONG;
-             case 4 -> JAVA_INT;
-             default -> throw new IllegalStateException("Address size not supported: " + ADDRESS.byteSize());
-         };
      private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
      private static final StructLayout LAYOUT = Utils.computePaddedStructLayout(
              SIZE_T, UNSIGNED_SHORT, UNSIGNED_SHORT.withName("type"), ADDRESS.withName("elements"));
  
      private static final VarHandle VH_TYPE = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("type"));
      private static final VarHandle VH_ELEMENTS = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("elements"));
!     private static final VarHandle VH_SIZE_T_ARRAY = SIZE_T.arrayElementVarHandle();
  
      private static MemorySegment make(List<MemoryLayout> elements, FFIABI abi, Arena scope) {
          MemorySegment elementsSeg = scope.allocate((elements.size() + 1) * ADDRESS.byteSize());
          int i = 0;
          for (; i < elements.size(); i++) {
--- 56,18 ---
   *   unsigned short type;
   *   struct _ffi_type **elements;
   * } ffi_type;
   */
  class FFIType {
!     static final ValueLayout SIZE_T = layoutFor((int)ADDRESS.byteSize());
      private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
      private static final StructLayout LAYOUT = Utils.computePaddedStructLayout(
              SIZE_T, UNSIGNED_SHORT, UNSIGNED_SHORT.withName("type"), ADDRESS.withName("elements"));
  
      private static final VarHandle VH_TYPE = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("type"));
      private static final VarHandle VH_ELEMENTS = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("elements"));
!     private static final VarHandle VH_SIZE_T = SIZE_T.varHandle();
  
      private static MemorySegment make(List<MemoryLayout> elements, FFIABI abi, Arena scope) {
          MemorySegment elementsSeg = scope.allocate((elements.size() + 1) * ADDRESS.byteSize());
          int i = 0;
          for (; i < elements.size(); i++) {

*** 81,12 ***
          }
          // elements array is null-terminated
          elementsSeg.setAtIndex(ADDRESS, i, MemorySegment.NULL);
  
          MemorySegment ffiType = scope.allocate(LAYOUT);
!         VH_TYPE.set(ffiType, LibFallback.structTag());
!         VH_ELEMENTS.set(ffiType, elementsSeg);
  
          return ffiType;
      }
  
      private static final Map<Class<?>, MemorySegment> CARRIER_TO_TYPE = Map.of(
--- 77,12 ---
          }
          // elements array is null-terminated
          elementsSeg.setAtIndex(ADDRESS, i, MemorySegment.NULL);
  
          MemorySegment ffiType = scope.allocate(LAYOUT);
!         VH_TYPE.set(ffiType, 0L, LibFallback.structTag());
!         VH_ELEMENTS.set(ffiType, 0L, elementsSeg);
  
          return ffiType;
      }
  
      private static final Map<Class<?>, MemorySegment> CARRIER_TO_TYPE = Map.of(

*** 130,17 ***
              LibFallback.getStructOffsets(structType, offsetsOut, abi);
              long expectedOffset = 0;
              int offsetIdx = 0;
              for (MemoryLayout element : structLayout.memberLayouts()) {
                  if (!(element instanceof PaddingLayout)) {
!                     long ffiOffset = (long) VH_SIZE_T_ARRAY.get(offsetsOut, offsetIdx++);
                      if (ffiOffset != expectedOffset) {
                          throw new IllegalArgumentException("Invalid group layout." +
                                  " Offset of '" + element.name().orElse("<unnamed>")
                                  + "': " + expectedOffset + " != " + ffiOffset);
                      }
                  }
                  expectedOffset += element.byteSize();
              }
          }
      }
  }
--- 126,36 ---
              LibFallback.getStructOffsets(structType, offsetsOut, abi);
              long expectedOffset = 0;
              int offsetIdx = 0;
              for (MemoryLayout element : structLayout.memberLayouts()) {
                  if (!(element instanceof PaddingLayout)) {
!                     long ffiOffset = sizeTAtIndex(offsetsOut, offsetIdx++);
                      if (ffiOffset != expectedOffset) {
                          throw new IllegalArgumentException("Invalid group layout." +
                                  " Offset of '" + element.name().orElse("<unnamed>")
                                  + "': " + expectedOffset + " != " + ffiOffset);
                      }
                  }
                  expectedOffset += element.byteSize();
              }
          }
      }
+ 
+     static ValueLayout layoutFor(int byteSize) {
+         return switch (byteSize) {
+             case 1 -> JAVA_BYTE;
+             case 2 -> JAVA_SHORT;
+             case 4 -> JAVA_INT;
+             case 8 -> JAVA_LONG;
+             default -> throw new IllegalStateException("Unsupported size: " + byteSize);
+         };
+     }
+ 
+     private static long sizeTAtIndex(MemorySegment segment, int index) {
+         long offset = SIZE_T.scale(0, index);
+         if (VH_SIZE_T.varType() == long.class) {
+             return (long) VH_SIZE_T.get(segment, offset);
+         } else {
+             return (int) VH_SIZE_T.get(segment, offset); // 'erase' to long
+         }
+     }
  }
< prev index next >