Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8274219: Add back generic factory to create value layouts #579

Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -41,6 +41,7 @@

import static java.lang.constant.ConstantDescs.BSM_GET_STATIC_FINAL;
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
import static java.lang.constant.ConstantDescs.CD_Class;
import static java.lang.constant.ConstantDescs.CD_String;
import static java.lang.constant.ConstantDescs.CD_long;

@@ -210,6 +211,9 @@ public boolean equals(Object other) {
static final MethodHandleDesc MH_UNION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "unionLayout",
MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_MEMORY_LAYOUT.arrayType()));

static final MethodHandleDesc MH_VALUE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "valueLayout",
MethodTypeDesc.of(CD_VALUE_LAYOUT, CD_Class, CD_BYTEORDER));

static final MethodHandleDesc MH_VOID_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, CD_FUNCTION_DESC, "ofVoid",
MethodTypeDesc.of(CD_FUNCTION_DESC, CD_MEMORY_LAYOUT.arrayType()));

@@ -34,6 +34,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Optional;
@@ -680,6 +681,51 @@ static MemoryLayout paddingLayout(long size) {
return new PaddingLayout(size);
}

/**
* Creates a value layout of given Java carrier and byte order. The type of resulting value layout is determined
* by the carrier provided:
* <ul>
* <li>{@link ValueLayout.OfBoolean}, for {@code boolean.class}</li>
* <li>{@link ValueLayout.OfByte}, for {@code byte.class}</li>
* <li>{@link ValueLayout.OfShort}, for {@code short.class}</li>
* <li>{@link ValueLayout.OfChar}, for {@code char.class}</li>
* <li>{@link ValueLayout.OfInt}, for {@code int.class}</li>
* <li>{@link ValueLayout.OfFloat}, for {@code float.class}</li>
* <li>{@link ValueLayout.OfLong}, for {@code long.class}</li>
* <li>{@link ValueLayout.OfDouble}, for {@code double.class}</li>
* <li>{@link ValueLayout.OfAddress}, for {@code MemoryAddress.class}</li>
* </ul>
* @param carrier the value layout carrier.
* @param order the value layout's byte order.
* @return a new value layout.
* @throws IllegalArgumentException if the carrier type is not supported.
*/
static ValueLayout valueLayout(Class<?> carrier, ByteOrder order) {
Objects.requireNonNull(carrier);
Objects.requireNonNull(order);
if (carrier == boolean.class) {
return new ValueLayout.OfBoolean(order);
} else if (carrier == char.class) {
return new ValueLayout.OfChar(order);
} else if (carrier == byte.class) {
return new ValueLayout.OfByte(order);
} else if (carrier == short.class) {
return new ValueLayout.OfShort(order);
} else if (carrier == int.class) {
return new ValueLayout.OfInt(order);
} else if (carrier == float.class) {
return new ValueLayout.OfFloat(order);
} else if (carrier == long.class) {
return new ValueLayout.OfLong(order);
} else if (carrier == double.class) {
return new ValueLayout.OfDouble(order);
} else if (carrier == MemoryAddress.class) {
return new ValueLayout.OfAddress(order);
} else {
throw new IllegalArgumentException("Unsupported carrier: " + carrier.getName());
}
}

/**
* Create a new sequence layout with given element layout and element count.
*
@@ -32,6 +32,7 @@
import sun.invoke.util.Wrapper;

import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.DirectMethodHandleDesc;
import java.lang.constant.DynamicConstantDesc;
import java.lang.constant.MethodHandleDesc;
@@ -148,20 +149,8 @@ ValueLayout dup(long alignment, Optional<String> name) {

@Override
public Optional<DynamicConstantDesc<ValueLayout>> describeConstable() {
ClassDesc THIS_DESC = getClass().describeConstable().get();
DynamicConstantDesc<ValueLayout> desc = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, specializedConstantName(), THIS_DESC, CD_VALUE_LAYOUT);
if (order != ByteOrder.nativeOrder()) {
MethodHandleDesc MH_WITH_ORDER = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, THIS_DESC, "withOrder",
MethodTypeDesc.of(THIS_DESC, CD_BYTEORDER));

desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withOrder", desc.constantType(), MH_WITH_ORDER,
desc, order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN);
}
return Optional.of(decorateLayoutConstant(desc));
}

String specializedConstantName() {
throw new IllegalStateException();
return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value",
CD_VALUE_LAYOUT, MH_VALUE, carrier().describeConstable().get(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN)));
}

//hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout
@@ -253,11 +242,6 @@ public OfBoolean withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfBoolean(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_BOOLEAN";
}
}

/**
@@ -292,11 +276,6 @@ public OfByte withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfByte(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_BYTE";
}
}

/**
@@ -331,11 +310,6 @@ public OfChar withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfChar(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_CHAR";
}
}

/**
@@ -370,11 +344,6 @@ public OfShort withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfShort(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_SHORT";
}
}

/**
@@ -409,11 +378,6 @@ public OfInt withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfInt(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_INT";
}
}

/**
@@ -448,11 +412,6 @@ public OfFloat withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfFloat(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_FLOAT";
}
}

/**
@@ -487,11 +446,6 @@ public OfLong withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfLong(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_LONG";
}
}

/**
@@ -526,19 +480,14 @@ public OfDouble withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfDouble(order, alignment, name());
}

@Override
String specializedConstantName() {
return "JAVA_DOUBLE";
}
}

/**
* A value layout whose carrier is {@code MemoryAddress.class}.
*/
public static final class OfAddress extends ValueLayout {
OfAddress(ByteOrder order, long size) {
super(MemoryAddress.class, order, size);
OfAddress(ByteOrder order) {
super(MemoryAddress.class, order, Unsafe.ADDRESS_SIZE * 8);
}

OfAddress(ByteOrder order, long size, long alignment, Optional<String> name) {
@@ -565,65 +514,96 @@ public OfAddress withOrder(ByteOrder order) {
Objects.requireNonNull(order);
return new OfAddress(order, bitSize(), alignment, name());
}

@Override
String specializedConstantName() {
return "ADDRESS";
}
}

/**
* A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}),
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder(), Unsafe.ADDRESS_SIZE * 8).withBitAlignment(8);
public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code byte},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code boolean},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code char},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code short},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code int},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code long},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder())
.withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code float},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(8);

/**
* A value layout constant whose size is the same as that of a Java {@code double},
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
* Equivalent to the following code:
* <blockquote><pre>{@code
MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8);
* }</pre></blockquote>
*/
public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(8);
}
@@ -629,29 +629,8 @@ public VarHandle varHandle() {
// alignment is set to 1 byte here to avoid exceptions for cases where we do super word
// copies of e.g. 2 int fields of a struct as a single long, while the struct is only
// 4-byte-aligned (since it only contains ints)
ValueLayout layout;
if (type() == boolean.class) {
layout = ValueLayout.JAVA_BOOLEAN;
} else if (type() == char.class) {
layout = ValueLayout.JAVA_CHAR;
} else if (type() == byte.class) {
layout = ValueLayout.JAVA_BYTE;
} else if (type() == short.class) {
layout = ValueLayout.JAVA_SHORT;
} else if (type() == int.class) {
layout = ValueLayout.JAVA_INT;
} else if (type() == float.class) {
layout = ValueLayout.JAVA_FLOAT;
} else if (type() == long.class) {
layout = ValueLayout.JAVA_LONG;
} else if (type() == double.class) {
layout = ValueLayout.JAVA_DOUBLE;
} else if (type() == MemoryAddress.class) {
layout = ValueLayout.ADDRESS;
} else {
throw new IllegalStateException("Unsupported carrier: " + type().getName());
}
return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(layout.withOrder(ByteOrder.nativeOrder()).withBitAlignment(8)), 1, offset);
ValueLayout layout = MemoryLayout.valueLayout(type(), ByteOrder.nativeOrder()).withBitAlignment(8);
return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(layout), 1, offset);
}
}