Skip to content
Permalink
Browse files
8274219: Add back generic factory to create value layouts
Reviewed-by: jvernee, psandoz
  • Loading branch information
mcimadamore committed Sep 23, 2021
1 parent 831e75b commit 79b304b4f423189e84bc6085e576ac1d9c9e6ab3
@@ -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);
}
}

0 comments on commit 79b304b

Please sign in to comment.