diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java index 6865eda87c8..7acb5f290ff 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java @@ -40,49 +40,52 @@ import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.lang.constant.ConstantDescs.BSM_INVOKE; +import static java.lang.constant.ConstantDescs.CD_String; +import static java.lang.constant.ConstantDescs.CD_long; abstract class AbstractLayout implements MemoryLayout { + // memory layout attribute key for layout name + static final String NAME = "name"; + private final OptionalLong size; final long alignment; - protected final Map annotations; + protected final Map attributes; - public AbstractLayout(OptionalLong size, long alignment, Map annotations) { + public AbstractLayout(OptionalLong size, long alignment, Map attributes) { this.size = size; this.alignment = alignment; - this.annotations = Collections.unmodifiableMap(annotations); + this.attributes = Collections.unmodifiableMap(attributes); } - Optional optName() { - return Optional.ofNullable((String)annotations.get(NAME)); - } - - // memory layout annotation key for abi native type - static final String NATIVE_TYPE = "abi/native-type"; - - Optional optABIType() { - return Optional.ofNullable((SystemABI.Type)annotations.get(NATIVE_TYPE)); + @Override + public AbstractLayout withName(String name) { + return withAttribute(NAME, name); } @Override - public AbstractLayout withName(String name) { - return withAnnotation(NAME, name); + public final Optional name() { + return attribute(NAME).map(String.class::cast); } - @SuppressWarnings("unchecked") - public Z withAnnotation(String name, Constable value) { - Map new_annos = new HashMap<>(annotations); - new_annos.put(name, value); - return (Z)dup(alignment, new_annos); + @Override + public Optional attribute(String name) { + return Optional.ofNullable(attributes.get(name)); } @Override - public final Optional name() { - return optName(); + public Stream attributes() { + return attributes.keySet().stream(); } @Override - public final Optional abiType() { - return optABIType(); + public AbstractLayout withAttribute(String name, Constable value) { + Map newAttributes = new HashMap<>(attributes); + newAttributes.put(name, value); + return dup(alignment, newAttributes); } abstract AbstractLayout dup(long alignment, Map annos); @@ -90,7 +93,7 @@ public final Optional abiType() { @Override public AbstractLayout withBitAlignment(long alignmentBits) { checkAlignment(alignmentBits); - return dup(alignmentBits, annotations); + return dup(alignmentBits, attributes); } void checkAlignment(long alignmentBitCount) { @@ -134,22 +137,40 @@ private static UnsupportedOperationException badSizeException() { } String decorateLayoutString(String s) { - if (optName().isPresent()) { - s = String.format("%s(%s)", s, optName().get()); + if (name().isPresent()) { + s = String.format("%s(%s)", s, name().get()); } if (!hasNaturalAlignment()) { s = alignment + "%" + s; } + if (!attributes.isEmpty()) { + s += attributes.entrySet().stream() + .map(e -> e.getKey() + "=" + e.getValue()) + .collect(Collectors.joining(",", "[", "]")); + } return s; } + DynamicConstantDesc decorateLayoutConstant(DynamicConstantDesc desc) { + if (!hasNaturalAlignment()) { + desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withBitAlignment", desc.constantType(), MH_WITH_BIT_ALIGNMENT, + desc, bitAlignment()); + } + for (var e : attributes.entrySet()) { + desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withAttribute", desc.constantType(), MH_WITH_ATTRIBUTE, + desc, e.getKey(), e.getValue().describeConstable().orElseThrow()); + } + + return desc; + } + boolean hasNaturalAlignment() { return size.isPresent() && size.getAsLong() == alignment; } @Override public int hashCode() { - return annotations.hashCode() << Long.hashCode(alignment); + return attributes.hashCode() << Long.hashCode(alignment); } @Override @@ -162,19 +183,17 @@ public boolean equals(Object other) { return false; } - return Objects.equals(annotations, ((AbstractLayout)other).annotations) && - Objects.equals(alignment, ((AbstractLayout)other).alignment); + return Objects.equals(attributes, ((AbstractLayout) other).attributes) && + Objects.equals(alignment, ((AbstractLayout) other).alignment); } - static final String NAME = "name"; - /*** Helper constants for implementing Layout::describeConstable ***/ static final DirectMethodHandleDesc BSM_GET_STATIC_FINAL = ConstantDescs.ofConstantBootstrap(ConstantDescs.CD_ConstantBootstraps, "getStaticFinal", ConstantDescs.CD_Object, ConstantDescs.CD_Class); - static final ClassDesc CD_LAYOUT = MemoryLayout.class.describeConstable().get(); + static final ClassDesc CD_MEMORY_LAYOUT = MemoryLayout.class.describeConstable().get(); static final ClassDesc CD_VALUE_LAYOUT = ValueLayout.class.describeConstable().get(); @@ -186,6 +205,8 @@ public boolean equals(Object other) { static final ClassDesc CD_FUNCTION_DESC = FunctionDescriptor.class.describeConstable().get(); + static final ClassDesc CD_Constable = Constable.class.describeConstable().get(); + static final ConstantDesc BIG_ENDIAN = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, "BIG_ENDIAN", CD_BYTEORDER, CD_BYTEORDER); static final ConstantDesc LITTLE_ENDIAN = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, "LITTLE_ENDIAN", CD_BYTEORDER, CD_BYTEORDER); @@ -194,27 +215,33 @@ public boolean equals(Object other) { static final ConstantDesc FALSE = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, "FALSE", ConstantDescs.CD_Boolean, ConstantDescs.CD_Boolean); - static final MethodHandleDesc MH_PADDING = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofPaddingBits", - MethodTypeDesc.of(CD_LAYOUT, ConstantDescs.CD_long)); + static final MethodHandleDesc MH_PADDING = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofPaddingBits", + MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_long)); + + static final MethodHandleDesc MH_VALUE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofValueBits", + MethodTypeDesc.of(CD_VALUE_LAYOUT, CD_long, CD_BYTEORDER)); + + static final MethodHandleDesc MH_SIZED_SEQUENCE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofSequence", + MethodTypeDesc.of(CD_SEQUENCE_LAYOUT, CD_long, CD_MEMORY_LAYOUT)); - static final MethodHandleDesc MH_VALUE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofValueBits", - MethodTypeDesc.of(CD_VALUE_LAYOUT, ConstantDescs.CD_long, CD_BYTEORDER)); + static final MethodHandleDesc MH_UNSIZED_SEQUENCE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofSequence", + MethodTypeDesc.of(CD_SEQUENCE_LAYOUT, CD_MEMORY_LAYOUT)); - static final MethodHandleDesc MH_SIZED_SEQUENCE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofSequence", - MethodTypeDesc.of(CD_SEQUENCE_LAYOUT, ConstantDescs.CD_long, CD_LAYOUT)); + static final MethodHandleDesc MH_STRUCT = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofStruct", + MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_MEMORY_LAYOUT.arrayType())); - static final MethodHandleDesc MH_UNSIZED_SEQUENCE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofSequence", - MethodTypeDesc.of(CD_SEQUENCE_LAYOUT, CD_LAYOUT)); + static final MethodHandleDesc MH_UNION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "ofUnion", + MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_MEMORY_LAYOUT.arrayType())); - static final MethodHandleDesc MH_STRUCT = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofStruct", - MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_LAYOUT.arrayType())); + static final MethodHandleDesc MH_VOID_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, CD_FUNCTION_DESC, "ofVoid", + MethodTypeDesc.of(CD_FUNCTION_DESC, CD_MEMORY_LAYOUT.arrayType())); - static final MethodHandleDesc MH_UNION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_LAYOUT, "ofUnion", - MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_LAYOUT.arrayType())); + static final MethodHandleDesc MH_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, CD_FUNCTION_DESC, "of", + MethodTypeDesc.of(CD_FUNCTION_DESC, CD_MEMORY_LAYOUT, CD_MEMORY_LAYOUT.arrayType())); - static final MethodHandleDesc MH_VOID_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_FUNCTION_DESC, "ofVoid", - MethodTypeDesc.of(CD_FUNCTION_DESC, CD_LAYOUT.arrayType())); + static final MethodHandleDesc MH_WITH_BIT_ALIGNMENT = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, CD_MEMORY_LAYOUT, "withBitAlignment", + MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_long)); - static final MethodHandleDesc MH_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_FUNCTION_DESC, "of", - MethodTypeDesc.of(CD_FUNCTION_DESC, CD_LAYOUT, CD_LAYOUT.arrayType())); + static final MethodHandleDesc MH_WITH_ATTRIBUTE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, CD_MEMORY_LAYOUT, "withAttribute", + MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_String, CD_Constable)); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java index 7f5e22ed747..a158a649d68 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java @@ -31,6 +31,7 @@ import java.lang.constant.DynamicConstantDesc; import java.lang.constant.MethodHandleDesc; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -105,8 +106,8 @@ long alignof(List elems) { this(kind, elements, kind.alignof(elements), Map.of()); } - GroupLayout(Kind kind, List elements, long alignment, Map annotations) { - super(kind.sizeof(elements), alignment, annotations); + GroupLayout(Kind kind, List elements, long alignment, Map attributes) { + super(kind.sizeof(elements), alignment, attributes); this.kind = kind; this.elements = elements; } @@ -170,8 +171,8 @@ public int hashCode() { } @Override - GroupLayout dup(long alignment, Map annotations) { - return new GroupLayout(kind, elements, alignment, annotations); + GroupLayout dup(long alignment, Map attributes) { + return new GroupLayout(kind, elements, alignment, attributes); } @Override @@ -186,9 +187,9 @@ public Optional> describeConstable() { for (int i = 0 ; i < elements.size() ; i++) { constants[i + 1] = elements.get(i).describeConstable().get(); } - return Optional.of(DynamicConstantDesc.ofNamed( + return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed( ConstantDescs.BSM_INVOKE, kind.name().toLowerCase(), - CD_GROUP_LAYOUT, constants)); + CD_GROUP_LAYOUT, constants))); } //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout @@ -209,4 +210,12 @@ public GroupLayout withName(String name) { public GroupLayout withBitAlignment(long alignmentBits) { return (GroupLayout)super.withBitAlignment(alignmentBits); } + + /** + * {@inheritDoc} + */ + @Override + public GroupLayout withAttribute(String name, Constable value) { + return (GroupLayout)super.withAttribute(name, value); + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java index 01d4e265e40..1ec48d46509 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.UnaryOperator; +import java.util.stream.Stream; /** * A memory layout can be used to describe the contents of a memory segment in a language neutral fashion. @@ -226,13 +227,6 @@ default long byteSize() { */ Optional name(); - /** - * Return the ABI type (if any) associated with this layout. - * - * @return the layout ABI type (if any). - */ - Optional abiType(); - /** * Creates a new layout which features the desired layout name. * @@ -291,6 +285,30 @@ default long byteAlignment() { */ MemoryLayout withBitAlignment(long bitAlignment); + /** + * Returns the attribute with the given name if it exists, or an empty optional + * + * @param name the name of the attribute + * @return the optional attribute + */ + Optional attribute(String name); + + /** + * Returns a new MemoryLayout with the given additional attribute + * + * @param name the name of the attribute + * @param value the value of the attribute + * @return the new MemoryLayout + */ + MemoryLayout withAttribute(String name, Constable value); + + /** + * Returns a stream of the names of the attributes of this layout + * + * @return the stream of names + */ + Stream attributes(); + /** * Computes the offset, in bits, of the layout selected by a given layout path, where the path is considered rooted in this * layout. diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java index ab17301b4db..2e7ae1eb0b6 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java @@ -288,107 +288,107 @@ private SysV() { * The {@code _Bool} native type. */ public static final ValueLayout C_BOOL = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.BOOL); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.BOOL); /** * The {@code unsigned char} native type. */ public static final ValueLayout C_UCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); /** * The {@code signed char} native type. */ public static final ValueLayout C_SCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); /** * The {@code char} native type. */ public static final ValueLayout C_CHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.CHAR); /** * The {@code short} native type. */ public static final ValueLayout C_SHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SHORT); /** * The {@code unsigned short} native type. */ public static final ValueLayout C_USHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); /** * The {@code int} native type. */ public static final ValueLayout C_INT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.INT); /** * The {@code unsigned int} native type. */ public static final ValueLayout C_UINT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); /** * The {@code long} native type. */ public static final ValueLayout C_LONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG); /** * The {@code unsigned long} native type. */ public static final ValueLayout C_ULONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); /** * The {@code long long} native type. */ public static final ValueLayout C_LONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_LONG); /** * The {@code unsigned long long} native type. */ public static final ValueLayout C_ULONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); /** * The {@code float} native type. */ public static final ValueLayout C_FLOAT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.FLOAT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.FLOAT); /** * The {@code double} native type. */ public static final ValueLayout C_DOUBLE = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.DOUBLE); /** * The {@code long double} native type. */ public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN) - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); /** * The {@code complex long double} native type. */ public static final GroupLayout C_COMPLEX_LONGDOUBLE = MemoryLayout.ofStruct(C_LONGDOUBLE, C_LONGDOUBLE) - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.COMPLEX_LONG_DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.COMPLEX_LONG_DOUBLE); /** * The {@code T*} native type. */ public static final ValueLayout C_POINTER = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.POINTER); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.POINTER); } /** @@ -399,100 +399,100 @@ public static final class WinABI { * The {@code _Bool} native type. */ public static final ValueLayout C_BOOL = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.BOOL); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.BOOL); /** * The {@code unsigned char} native type. */ public static final ValueLayout C_UCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); /** * The {@code signed char} native type. */ public static final ValueLayout C_SCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); /** * The {@code char} native type. */ public static final ValueLayout C_CHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.CHAR); /** * The {@code short} native type. */ public static final ValueLayout C_SHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SHORT); /** * The {@code unsigned short} native type. */ public static final ValueLayout C_USHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); /** * The {@code int} native type. */ public static final ValueLayout C_INT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.INT); /** * The {@code unsigned int} native type. */ public static final ValueLayout C_UINT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); /** * The {@code long} native type. */ public static final ValueLayout C_LONG = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG); /** * The {@code unsigned long} native type. */ public static final ValueLayout C_ULONG = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); /** * The {@code long long} native type. */ public static final ValueLayout C_LONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_LONG); /** * The {@code unsigned long long} native type. */ public static final ValueLayout C_ULONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); /** * The {@code float} native type. */ public static final ValueLayout C_FLOAT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.FLOAT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.FLOAT); /** * The {@code double} native type. */ public static final ValueLayout C_DOUBLE = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.DOUBLE); /** * The {@code long double} native type. */ public static final ValueLayout C_LONGDOUBLE = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); /** * The {@code T*} native type. */ public static final ValueLayout C_POINTER = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.POINTER); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.POINTER); public static ValueLayout asVarArg(ValueLayout l) { - return l.withAnnotation(Windowsx64ABI.VARARGS_ANNOTATION_NAME, "true"); + return l.withAttribute(Windowsx64ABI.VARARGS_ATTRIBUTE_NAME, "true"); } } @@ -504,97 +504,97 @@ public static final class AArch64ABI { * The {@code _Bool} native type. */ public static final ValueLayout C_BOOL = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.BOOL); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.BOOL); /** * The {@code unsigned char} native type. */ public static final ValueLayout C_UCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_CHAR); /** * The {@code signed char} native type. */ public static final ValueLayout C_SCHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SIGNED_CHAR); /** * The {@code char} native type. */ public static final ValueLayout C_CHAR = SharedLayouts.BITS_8_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.CHAR); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.CHAR); /** * The {@code short} native type. */ public static final ValueLayout C_SHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.SHORT); /** * The {@code unsigned short} native type. */ public static final ValueLayout C_USHORT = SharedLayouts.BITS_16_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_SHORT); /** * The {@code int} native type. */ public static final ValueLayout C_INT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.INT); /** * The {@code unsigned int} native type. */ public static final ValueLayout C_UINT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_INT); /** * The {@code long} native type. */ public static final ValueLayout C_LONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG); /** * The {@code unsigned long} native type. */ public static final ValueLayout C_ULONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG); /** * The {@code long long} native type. */ public static final ValueLayout C_LONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_LONG); /** * The {@code unsigned long long} native type. */ public static final ValueLayout C_ULONGLONG = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.UNSIGNED_LONG_LONG); /** * The {@code float} native type. */ public static final ValueLayout C_FLOAT = SharedLayouts.BITS_32_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.FLOAT); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.FLOAT); /** * The {@code double} native type. */ public static final ValueLayout C_DOUBLE = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.DOUBLE); /** * The {@code long double} native type. */ public static final ValueLayout C_LONGDOUBLE = MemoryLayout.ofValueBits(128, ByteOrder.LITTLE_ENDIAN) - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.LONG_DOUBLE); /** * The {@code T*} native type. */ public static final ValueLayout C_POINTER = SharedLayouts.BITS_64_LE - .withAnnotation(AbstractLayout.NATIVE_TYPE, SystemABI.Type.POINTER); + .withAttribute(SystemABI.NATIVE_TYPE, SystemABI.Type.POINTER); } private static class SharedLayouts { // Separate class to prevent circular clinit references diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java index f66091202c9..d3994227595 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java @@ -52,8 +52,8 @@ this(size, 1, Map.of()); } - PaddingLayout(long size, long alignment, Map annotations) { - super(OptionalLong.of(size), alignment, annotations); + PaddingLayout(long size, long alignment, Map attributes) { + super(OptionalLong.of(size), alignment, attributes); } @Override @@ -82,14 +82,19 @@ public int hashCode() { } @Override - PaddingLayout dup(long alignment, Map annotations) { - return new PaddingLayout(bitSize(), alignment, annotations); + PaddingLayout dup(long alignment, Map attributes) { + return new PaddingLayout(bitSize(), alignment, attributes); + } + + @Override + public boolean hasNaturalAlignment() { + return true; } @Override public Optional> describeConstable() { - return Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "padding", - CD_LAYOUT, MH_PADDING, bitSize())); + return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "padding", + CD_MEMORY_LAYOUT, MH_PADDING, bitSize()))); } //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout @@ -110,4 +115,12 @@ public PaddingLayout withName(String name) { public PaddingLayout withBitAlignment(long alignmentBits) { return (PaddingLayout)super.withBitAlignment(alignmentBits); } + + /** + * {@inheritDoc} + */ + @Override + public PaddingLayout withAttribute(String name, Constable value) { + return (PaddingLayout)super.withAttribute(name, value); + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java index 28083a76503..ae15f466cb4 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java @@ -71,10 +71,10 @@ public final class SequenceLayout extends AbstractLayout { this(elemCount, elementLayout, elementLayout.bitAlignment(), Map.of()); } - SequenceLayout(OptionalLong elemCount, MemoryLayout elementLayout, long alignment, Map annotations) { + SequenceLayout(OptionalLong elemCount, MemoryLayout elementLayout, long alignment, Map attributes) { super(elemCount.isPresent() && AbstractLayout.optSize(elementLayout).isPresent() ? OptionalLong.of(elemCount.getAsLong() * elementLayout.bitSize()) : - OptionalLong.empty(), alignment, annotations); + OptionalLong.empty(), alignment, attributes); this.elemCount = elemCount; this.elementLayout = elementLayout; } @@ -106,7 +106,7 @@ public OptionalLong elementCount() { */ public SequenceLayout withElementCount(long elementCount) { AbstractLayout.checkSize(elementCount, true); - return new SequenceLayout(OptionalLong.of(elementCount), elementLayout, alignment, annotations); + return new SequenceLayout(OptionalLong.of(elementCount), elementLayout, alignment, attributes); } @Override @@ -136,8 +136,8 @@ public int hashCode() { } @Override - SequenceLayout dup(long alignment, Map annotations) { - return new SequenceLayout(elementCount(), elementLayout, alignment, annotations); + SequenceLayout dup(long alignment, Map attributes) { + return new SequenceLayout(elementCount(), elementLayout, alignment, attributes); } @Override @@ -147,11 +147,11 @@ boolean hasNaturalAlignment() { @Override public Optional> describeConstable() { - return elemCount.isPresent() ? - Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", - CD_SEQUENCE_LAYOUT, MH_SIZED_SEQUENCE, elemCount.getAsLong(), elementLayout.describeConstable().get())) : - Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", - CD_SEQUENCE_LAYOUT, MH_UNSIZED_SEQUENCE, elementLayout.describeConstable().get())); + return Optional.of(decorateLayoutConstant(elemCount.isPresent() ? + DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", + CD_SEQUENCE_LAYOUT, MH_SIZED_SEQUENCE, elemCount.getAsLong(), elementLayout.describeConstable().get()) : + DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", + CD_SEQUENCE_LAYOUT, MH_UNSIZED_SEQUENCE, elementLayout.describeConstable().get()))); } //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout @@ -172,4 +172,12 @@ public SequenceLayout withName(String name) { public SequenceLayout withBitAlignment(long alignmentBits) { return (SequenceLayout)super.withBitAlignment(alignmentBits); } + + /** + * {@inheritDoc} + */ + @Override + public SequenceLayout withAttribute(String name, Constable value) { + return (SequenceLayout)super.withAttribute(name, value); + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SystemABI.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SystemABI.java index d8ad4a2e584..74718d98968 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SystemABI.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SystemABI.java @@ -52,6 +52,11 @@ public interface SystemABI { */ String ABI_AARCH64 = "AArch64"; + /** + * memory layout attribute key for abi native type + */ + String NATIVE_TYPE = "abi/native-type"; + /** * Obtain a method handle which can be used to call a given native function. * @@ -174,7 +179,21 @@ enum Type { /** * The {@code T*} native type. */ - POINTER + POINTER; + + /** + * Retrieve the ABI type attached to the given layout, + * or throw an {@code IllegalArgumentException} if there is none + * + * @param ml the layout to retrieve the ABI type of + * @return the retrieved ABI type + * @throws IllegalArgumentException if the given layout does not have an ABI type attribute + */ + public static Type fromLayout(MemoryLayout ml) throws IllegalArgumentException { + return ml.attribute(NATIVE_TYPE) + .map(SystemABI.Type.class::cast) + .orElseThrow(() -> new IllegalArgumentException("No ABI attribute present")); + } } /** diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java index 6567fe298fe..ee62081308c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java @@ -56,8 +56,8 @@ public final class ValueLayout extends AbstractLayout implements MemoryLayout { this(order, size, size, Map.of()); } - ValueLayout(ByteOrder order, long size, long alignment, Map annotations) { - super(OptionalLong.of(size), alignment, annotations); + ValueLayout(ByteOrder order, long size, long alignment, Map attributes) { + super(OptionalLong.of(size), alignment, attributes); this.order = order; } @@ -77,7 +77,7 @@ public ByteOrder order() { * @return a new value layout with given byte order. */ public ValueLayout withOrder(ByteOrder order) { - return new ValueLayout(order, bitSize(), alignment, annotations); + return new ValueLayout(order, bitSize(), alignment, attributes); } @Override @@ -110,14 +110,14 @@ public int hashCode() { } @Override - ValueLayout dup(long alignment, Map annotations) { - return new ValueLayout(order, bitSize(), alignment, annotations); + ValueLayout dup(long alignment, Map attributes) { + return new ValueLayout(order, bitSize(), alignment, attributes); } @Override public Optional> describeConstable() { - return Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", - CD_VALUE_LAYOUT, MH_VALUE, bitSize(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN)); + return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", + CD_VALUE_LAYOUT, MH_VALUE, bitSize(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN))); } //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout @@ -138,4 +138,12 @@ public ValueLayout withName(String name) { public ValueLayout withBitAlignment(long alignmentBits) { return (ValueLayout)super.withBitAlignment(alignmentBits); } + + /** + * {@inheritDoc} + */ + @Override + public ValueLayout withAttribute(String name, Constable value) { + return (ValueLayout)super.withAttribute(name, value); + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java index 45b1638c370..1c8f081c592 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java @@ -117,21 +117,6 @@ public static boolean isPadding(MemoryLayout layout) { return layout.getClass() == PADDING_CLASS; } - @SuppressWarnings("unchecked") - public static Map getAnnotations(MemoryLayout layout) { - try { - Field f = ValueLayout.class.getSuperclass().getDeclaredField("annotations"); - f.setAccessible(true); - return (Map) f.get(layout); - } catch (ReflectiveOperationException ex) { - throw new IllegalStateException(ex); - } - } - - public static Constable getAnnotation(MemoryLayout layout, String name) { - return getAnnotations(layout).get(name); - } - public static MemoryAddress resizeNativeAddress(MemoryAddress base, long byteSize) { return new MemoryAddressImpl((MemorySegmentImpl)Utils.makeNativeSegmentUnchecked(base, byteSize), 0); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index 7e067ad8ebe..7a76e66dbba 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -30,6 +30,7 @@ import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SystemABI; import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.CallingSequenceBuilder; @@ -162,10 +163,7 @@ private enum TypeClass { } private static TypeClass classifyValueType(ValueLayout type) { - var optAbiType = type.abiType(); - //padding not allowed here - ArgumentClassImpl clazz = optAbiType.map(AArch64ABI::argumentClassFor). - orElseThrow(()->new IllegalStateException("Unexpected value layout: could not determine ABI class")); + ArgumentClassImpl clazz = AArch64ABI.argumentClassFor(SystemABI.Type.fromLayout(type)); if (clazz == null) { //padding not allowed here throw new IllegalStateException("Unexpected value layout: could not determine ABI class"); @@ -200,14 +198,12 @@ static boolean isHomogeneousFloatAggregate(MemoryLayout type) { if (!(baseType instanceof ValueLayout)) return false; - var optAbiType = baseType.abiType(); - ArgumentClassImpl baseArgClass = optAbiType.map(AArch64ABI::argumentClassFor).orElse(null); + ArgumentClassImpl baseArgClass = AArch64ABI.argumentClassFor(SystemABI.Type.fromLayout(baseType)); if (baseArgClass != ArgumentClassImpl.VECTOR) return false; for (MemoryLayout elem : groupLayout.memberLayouts()) { - optAbiType = elem.abiType(); - ArgumentClassImpl argClass = optAbiType.map(AArch64ABI::argumentClassFor).orElse(null); + ArgumentClassImpl argClass = AArch64ABI.argumentClassFor(SystemABI.Type.fromLayout(elem)); if (!(elem instanceof ValueLayout) || elem.bitSize() != baseType.bitSize() || elem.bitAlignment() != baseType.bitAlignment() || diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index bb39d5bacc2..bd3820b5103 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -32,6 +32,7 @@ import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SystemABI; import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.CallingSequenceBuilder; @@ -428,10 +429,7 @@ private static List createMemoryClassArray(long size) { private static List classifyValueType(ValueLayout type) { ArrayList classes = new ArrayList<>(); - var optAbiType = type.abiType(); - //padding not allowed here - ArgumentClassImpl clazz = optAbiType.map(SysVx64ABI::argumentClassFor). - orElseThrow(()->new IllegalStateException("Unexpected value layout: could not determine ABI class")); + ArgumentClassImpl clazz = SysVx64ABI.argumentClassFor(SystemABI.Type.fromLayout(type)); if (clazz == null) { //padding not allowed here throw new IllegalStateException("Unexpected value layout: could not determine ABI class"); @@ -519,9 +517,11 @@ private static List classifyArrayType(SequenceLayout type) { // TODO: handle zero length arrays // TODO: Handle nested structs (and primitives) private static List classifyStructType(GroupLayout type) { - var optAbiType = type.abiType(); - var clazz = optAbiType.map(SysVx64ABI::argumentClassFor).orElse(null); - if (clazz == ArgumentClassImpl.COMPLEX_X87) { + if (type.attribute(SystemABI.NATIVE_TYPE) + .map(SystemABI.Type.class::cast) + .map(SysVx64ABI::argumentClassFor) + .filter(ArgumentClassImpl.COMPLEX_X87::equals) + .isPresent()) { return COMPLEX_X87_CLASSES; } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index d70f8f3f526..bed924224b5 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -29,6 +29,7 @@ import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SystemABI; import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.CallingSequenceBuilder; @@ -42,6 +43,7 @@ import jdk.internal.foreign.abi.x64.X86_64Architecture; import jdk.internal.foreign.abi.x64.ArgumentClassImpl; import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.foreign.abi.x64.sysv.SysVx64ABI; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -49,7 +51,7 @@ import java.util.Optional; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; -import static jdk.internal.foreign.abi.x64.windows.Windowsx64ABI.VARARGS_ANNOTATION_NAME; +import static jdk.internal.foreign.abi.x64.windows.Windowsx64ABI.VARARGS_ATTRIBUTE_NAME; /** * For the Windowx x64 C ABI specifically, this class uses the ProgrammableInvoker API, namely CallingSequenceBuilder2 @@ -161,10 +163,7 @@ private enum TypeClass { } private static TypeClass classifyValueType(ValueLayout type) { - var optAbiType = type.abiType(); - //padding not allowed here - ArgumentClassImpl clazz = optAbiType.map(Windowsx64ABI::argumentClassFor). - orElseThrow(()->new IllegalStateException("Unexpected value layout: could not determine ABI class")); + ArgumentClassImpl clazz = Windowsx64ABI.argumentClassFor(SystemABI.Type.fromLayout(type)); if (clazz == null) { //padding not allowed here throw new IllegalStateException("Unexpected value layout: could not determine ABI class"); @@ -184,7 +183,9 @@ private static TypeClass classifyValueType(ValueLayout type) { } else if(clazz == ArgumentClassImpl.POINTER) { return TypeClass.POINTER; } else if (clazz == ArgumentClassImpl.SSE) { - if (Boolean.parseBoolean((String) Utils.getAnnotation(type, VARARGS_ANNOTATION_NAME))) { + if (type.attribute(VARARGS_ATTRIBUTE_NAME) + .map(String.class::cast) + .map(Boolean::parseBoolean).orElse(false)) { return TypeClass.VARARG_FLOAT; } return TypeClass.FLOAT; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64ABI.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64ABI.java index ca933e2b3cb..32bcaa95f5c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64ABI.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64ABI.java @@ -51,7 +51,7 @@ public class Windowsx64ABI implements SystemABI { public static final int MAX_REGISTER_ARGUMENTS = 4; public static final int MAX_REGISTER_RETURNS = 1; - public static final String VARARGS_ANNOTATION_NAME = "abi/windows/varargs"; + public static final String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs"; private static Windowsx64ABI instance; diff --git a/test/jdk/java/foreign/NativeTestHelper.java b/test/jdk/java/foreign/NativeTestHelper.java index f8a40b805a5..fd946aa6bb4 100644 --- a/test/jdk/java/foreign/NativeTestHelper.java +++ b/test/jdk/java/foreign/NativeTestHelper.java @@ -38,11 +38,7 @@ public class NativeTestHelper { public static final SystemABI ABI = Foreign.getInstance().getSystemABI(); public static boolean isIntegral(MemoryLayout layout) { - var optAbiType = layout.abiType(); - if (!optAbiType.isPresent()) { - return false; - } - return switch(optAbiType.get()) { + return switch(SystemABI.Type.fromLayout(layout)) { case BOOL, UNSIGNED_CHAR, SIGNED_CHAR, CHAR, SHORT, UNSIGNED_SHORT, INT, UNSIGNED_INT, LONG, UNSIGNED_LONG, LONG_LONG, UNSIGNED_LONG_LONG -> true; default -> false; @@ -50,7 +46,7 @@ public static boolean isIntegral(MemoryLayout layout) { } public static boolean isPointer(MemoryLayout layout) { - return layout.abiType().filter(Predicate.isEqual(Type.POINTER)).isPresent(); + return SystemABI.Type.fromLayout(layout) == Type.POINTER; } public static ValueLayout asVarArg(ValueLayout layout) { diff --git a/test/jdk/java/foreign/TestLayoutAttributes.java b/test/jdk/java/foreign/TestLayoutAttributes.java new file mode 100644 index 00000000000..6673a8be3a1 --- /dev/null +++ b/test/jdk/java/foreign/TestLayoutAttributes.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng TestLayoutAttributes + */ + +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayouts; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class TestLayoutAttributes { + + @Test + public void testAttribute() { + MemoryLayout ml = MemoryLayouts.BITS_32_LE + .withAttribute("MyAttribute", 10L); + assertEquals((long) ml.attribute("MyAttribute").orElseThrow(), 10L); + } + + @Test + public void testAttributeNonExistent() { + MemoryLayout ml = MemoryLayouts.BITS_32_LE + .withAttribute("MyAttribute", 10L); + assertTrue(ml.attribute("Foo").isEmpty()); + } + + @Test + public void testNameAttribute() { + MemoryLayout ml = MemoryLayouts.BITS_32_LE + .withName("foo"); + assertEquals(ml.name().orElseThrow(), "foo"); + assertEquals(ml.attribute("name").orElseThrow(), "foo"); + } + + @Test + public void testAttributesStream() { + MemoryLayout ml = MemoryLayouts.BITS_32_LE + .withName("foo") + .withAttribute("MyAttribute", 10L); + List attribs = ml.attributes().collect(Collectors.toList()); + assertEquals(attribs, List.of("name", "MyAttribute")); + } + +} diff --git a/test/jdk/java/foreign/TestLayoutConstants.java b/test/jdk/java/foreign/TestLayoutConstants.java index 269db77a64b..2bd1e067277 100644 --- a/test/jdk/java/foreign/TestLayoutConstants.java +++ b/test/jdk/java/foreign/TestLayoutConstants.java @@ -106,6 +106,9 @@ public Object[][] createLayouts() { MemoryLayout.ofStruct( MemoryLayouts.PAD_8, MemoryLayouts.BITS_32_BE)) }, + { MemoryLayouts.BITS_32_LE.withName("myInt") }, + { MemoryLayouts.BITS_32_LE.withBitAlignment(8) }, + { MemoryLayouts.BITS_32_LE.withAttribute("xyz", "abc") }, }; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverhead.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverhead.java new file mode 100644 index 00000000000..834da256bcb --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverhead.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.jdk.incubator.foreign; + +import jdk.incubator.foreign.Foreign; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.LibraryLookup; +import jdk.incubator.foreign.SystemABI; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +import static jdk.incubator.foreign.MemoryLayouts.C_INT; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(3) +public class CallOverhead { + + static final SystemABI abi = Foreign.getInstance().getSystemABI(); + static final MethodHandle func; + static final MethodHandle identity; + + static { + System.loadLibrary("CallOverheadJNI"); + + try { + LibraryLookup ll = LibraryLookup.ofLibrary(MethodHandles.lookup(), "CallOverhead"); + func = abi.downcallHandle(ll.lookup("func"), + MethodType.methodType(void.class), + FunctionDescriptor.ofVoid()); + identity = abi.downcallHandle(ll.lookup("identity"), + MethodType.methodType(int.class, int.class), + FunctionDescriptor.of(C_INT, C_INT)); + } catch (NoSuchMethodException e) { + throw new BootstrapMethodError(e); + } + } + + static native void blank(); + static native int identity(int x); + + @Benchmark + public void jni_blank() throws Throwable { + blank(); + } + + @Benchmark + public void panama_blank() throws Throwable { + func.invokeExact(); + } + + @Benchmark + public int jni_identity() throws Throwable { + return identity(10); + } + + @Benchmark + public int panama_identity() throws Throwable { + return (int) identity.invokeExact(10); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c new file mode 100644 index 00000000000..0cad4f1f6f9 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void func() {} + +EXPORT int identity(int x) { + return x; +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverheadJNI.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverheadJNI.c new file mode 100644 index 00000000000..1344f29f176 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverheadJNI.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include + +void func() {} + +int identity(int x) { + return x; +} + +JNIEXPORT void JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_CallOverhead_blank + (JNIEnv *env, jclass cls) { + func(); +} + +JNIEXPORT jint JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_CallOverhead_identity + (JNIEnv *env, jclass cls, jint x) { + return identity(x); +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/PointsDistance.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/PointsDistance.java new file mode 100644 index 00000000000..9593850cbc0 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/PointsDistance.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.jdk.incubator.foreign.points; + +import org.openjdk.bench.jdk.incubator.foreign.points.support.BBPoint; +import org.openjdk.bench.jdk.incubator.foreign.points.support.JNIPoint; +import org.openjdk.bench.jdk.incubator.foreign.points.support.PanamaPoint; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(3) +public class PointsDistance { + + BBPoint jniP1; + BBPoint jniP2; + + JNIPoint nativeP1; + JNIPoint nativeP2; + + PanamaPoint panamaPointP1; + PanamaPoint panamaPointP2; + + @Setup + public void setup() { + jniP1 = new BBPoint(0, 0); + jniP2 = new BBPoint(1, 1); + + nativeP1 = new JNIPoint(0, 0); + nativeP2 = new JNIPoint(1, 1); + + panamaPointP1 = new PanamaPoint(0, 0); + panamaPointP2 = new PanamaPoint(1, 1); + } + + @TearDown + public void tearDown() { + nativeP1.free(); + nativeP2.free(); + + panamaPointP1.close(); + panamaPointP2.close(); + } + + @Benchmark + public double jni_ByteBuffer() throws Throwable { + return jniP1.distanceTo(jniP2); + } + + @Benchmark + public double jni_long() throws Throwable { + return nativeP1.distanceTo(nativeP2); + } + + @Benchmark + public double panama_MemorySegment() throws Throwable { + return panamaPointP1.distanceTo(panamaPointP2); + } + + @Benchmark + public double panama_MemoryAddress() throws Throwable { + return panamaPointP1.distanceToPtrs(panamaPointP2); + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/BBPoint.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/BBPoint.java index 06b8c430054..f627aeb2663 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/BBPoint.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/BBPoint.java @@ -27,6 +27,10 @@ public class BBPoint { + static { + System.loadLibrary("JNIPoint"); + } + private final ByteBuffer buff; public BBPoint(int x, int y) { @@ -50,4 +54,10 @@ public int getY() { public void setY(int y) { buff.putInt(0, y); } + + public double distanceTo(BBPoint other) { + return distance(buff, other.buff); + } + + private static native double distance(ByteBuffer p1, ByteBuffer p2); } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/JNIPoint.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/JNIPoint.java index baebbde67d2..872e16f0b4d 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/JNIPoint.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/JNIPoint.java @@ -56,6 +56,10 @@ public void setY(int value) { setY(peer, value); } + public double distanceTo(JNIPoint other) { + return distance(peer, other.peer); + } + private static native long allocate(); private static native void free(long ptr); @@ -65,6 +69,8 @@ public void setY(int value) { private static native int getY(long ptr); private static native void setY(long ptr, int y); + private static native double distance(long p1, long p2); + @Override public void close() { free(); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java index 924909f5648..fc5fa219a6a 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java @@ -22,26 +22,55 @@ */ package org.openjdk.bench.jdk.incubator.foreign.points.support; +import jdk.incubator.foreign.Foreign; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.LibraryLookup; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.SystemABI; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.nio.ByteOrder; +import static java.lang.invoke.MethodType.methodType; import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; +import static jdk.incubator.foreign.MemoryLayouts.*; public class PanamaPoint implements AutoCloseable { public static final MemoryLayout LAYOUT = MemoryLayout.ofStruct( - MemoryLayouts.JAVA_INT.withOrder(ByteOrder.nativeOrder()).withName("x"), - MemoryLayouts.JAVA_INT.withOrder(ByteOrder.nativeOrder()).withName("y") + MemoryLayouts.C_INT.withName("x"), + MemoryLayouts.C_INT.withName("y") ); private static final VarHandle VH_x = LAYOUT.varHandle(int.class, groupElement("x")); private static final VarHandle VH_y = LAYOUT.varHandle(int.class, groupElement("y")); + private static final MethodHandle MH_distance; + private static final MethodHandle MH_distance_ptrs; - private final MemorySegment segment; + static { + try { + SystemABI abi = Foreign.getInstance().getSystemABI(); + LibraryLookup lookup = LibraryLookup.ofLibrary(MethodHandles.lookup(), "Point"); + MH_distance = abi.downcallHandle( + lookup.lookup("distance"), + methodType(double.class, MemorySegment.class, MemorySegment.class), + FunctionDescriptor.of(C_DOUBLE, LAYOUT, LAYOUT) + ); + MH_distance_ptrs = abi.downcallHandle( + lookup.lookup("distance_ptrs"), + methodType(double.class, MemoryAddress.class, MemoryAddress.class), + FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_POINTER) + ); + } catch (NoSuchMethodException e) { + throw new BootstrapMethodError(e); + } + } + + private final MemoryAddress address; public PanamaPoint(int x, int y) { this(MemorySegment.allocateNative(LAYOUT), x, y); @@ -54,27 +83,43 @@ public PanamaPoint(MemorySegment segment, int x, int y) { } public PanamaPoint(MemorySegment segment) { - this.segment = segment; + this.address = segment.baseAddress(); } public void setX(int x) { - VH_x.set(segment.baseAddress(), x); + VH_x.set(address, x); } public int getX() { - return (int) VH_x.get(segment.baseAddress()); + return (int) VH_x.get(address); } public void setY(int y) { - VH_y.set(segment.baseAddress(), y); + VH_y.set(address, y); } public int getY() { - return (int) VH_y.get(segment.baseAddress()); + return (int) VH_y.get(address); + } + + public double distanceTo(PanamaPoint other) { + try { + return (double) MH_distance.invokeExact(address.segment(), other.address.segment()); + } catch (Throwable throwable) { + throw new InternalError(throwable); + } + } + + public double distanceToPtrs(PanamaPoint other) { + try { + return (double) MH_distance_ptrs.invokeExact(address, other.address); + } catch (Throwable throwable) { + throw new InternalError(throwable); + } } @Override public void close() { - segment.close(); + address.segment().close(); } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libJNIPoint.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libJNIPoint.c index aa4f62b1963..0afcb8d4070 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libJNIPoint.c +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libJNIPoint.c @@ -22,9 +22,16 @@ */ #include #include +#include #include "points.h" +double distance(Point p1, Point p2) { + int xDist = abs(p1.x - p2.x); + int yDist = abs(p1.y - p2.y); + return sqrt((xDist * xDist) + (yDist * yDist)); +} + JNIEXPORT jlong JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_points_support_JNIPoint_allocate (JNIEnv *env, jclass nativePointClass) { Point* p = malloc(sizeof *p); @@ -59,3 +66,17 @@ JNIEXPORT void JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_points_suppo Point* point = (Point*) thisPoint; point->y = value; } + +JNIEXPORT jdouble JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_points_support_JNIPoint_distance + (JNIEnv *env, jclass cls, jlong thisPoint, jlong other) { + Point* p1 = (Point*) thisPoint; + Point* p2 = (Point*) other; + return distance(*p1, *p2); +} + +JNIEXPORT jdouble JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_points_support_BBPoint_distance + (JNIEnv *env, jclass ignored, jobject buffP1, jobject buffP2) { + Point* p1 = (Point*) (*env)->GetDirectBufferAddress(env, buffP1); + Point* p2 = (Point*) (*env)->GetDirectBufferAddress(env, buffP2); + return distance(*p1, *p2); +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libPoint.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libPoint.c new file mode 100644 index 00000000000..480f54b39a7 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/libPoint.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include + +#include "points.h" + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT double distance(Point p1, Point p2) { + int xDist = abs(p1.x - p2.x); + int yDist = abs(p1.y - p2.y); + return sqrt((xDist * xDist) + (yDist * yDist)); +} + +EXPORT double distance_ptrs(Point* p1, Point* p2) { + return distance(*p1, *p2); +}