mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-10 18:38:27 +00:00
Merge
This commit is contained in:
commit
df4bbc7632
@ -917,7 +917,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
|
||||
break;
|
||||
|
||||
case 0x62: // EVEX_4bytes
|
||||
assert((UseAVX > 0), "shouldn't have EVEX prefix");
|
||||
assert(VM_Version::supports_evex(), "shouldn't have EVEX prefix");
|
||||
assert(ip == inst+1, "no prefixes allowed");
|
||||
// no EVEX collisions, all instructions that have 0x62 opcodes
|
||||
// have EVEX versions and are subopcodes of 0x66
|
||||
|
||||
@ -365,6 +365,10 @@ int NativeMovRegMem::instruction_start() const {
|
||||
NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
|
||||
return 3;
|
||||
}
|
||||
if (instr_0 == instruction_EVEX_prefix_4bytes) {
|
||||
assert(VM_Version::supports_evex(), "shouldn't have EVEX prefix");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// First check to see if we have a (prefixed or not) xor
|
||||
if (instr_0 >= instruction_prefix_wide_lo && // 0x40
|
||||
|
||||
@ -356,6 +356,7 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
|
||||
instruction_VEX_prefix_2bytes = Assembler::VEX_2bytes,
|
||||
instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes,
|
||||
instruction_EVEX_prefix_4bytes = Assembler::EVEX_4bytes,
|
||||
|
||||
instruction_size = 4,
|
||||
instruction_offset = 0,
|
||||
|
||||
@ -179,11 +179,14 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
if (hotspotField.isStatic()) {
|
||||
HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
|
||||
if (holder.isInitialized()) {
|
||||
return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), hotspotField.offset());
|
||||
return memoryAccess.readFieldValue(hotspotField, holder.mirror());
|
||||
}
|
||||
} else {
|
||||
if (receiver.isNonNull() && hotspotField.isInObject(((HotSpotObjectConstantImpl) receiver).object())) {
|
||||
return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), receiver, hotspotField.offset());
|
||||
if (receiver.isNonNull()) {
|
||||
Object object = ((HotSpotObjectConstantImpl) receiver).object();
|
||||
if (hotspotField.isInObject(object)) {
|
||||
return memoryAccess.readFieldValue(hotspotField, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -31,6 +31,10 @@ import jdk.vm.ci.meta.MemoryAccessProvider;
|
||||
*/
|
||||
public interface HotSpotMemoryAccessProvider extends MemoryAccessProvider {
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the address computed from {@code base} and
|
||||
* {@code displacement} does not denote a location holding a narrow oop
|
||||
*/
|
||||
JavaConstant readNarrowOopConstant(Constant base, long displacement);
|
||||
|
||||
Constant readKlassPointerConstant(Constant base, long displacement);
|
||||
|
||||
@ -22,13 +22,21 @@
|
||||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
|
||||
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MemoryAccessProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.PrimitiveConstant;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* HotSpot implementation of {@link MemoryAccessProvider}.
|
||||
@ -41,12 +49,93 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
private static Object asObject(Constant base) {
|
||||
/**
|
||||
* Gets the object boxed by {@code base} that is about to have a value of kind {@code kind} read
|
||||
* from it at the offset {@code displacement}.
|
||||
*
|
||||
* @param base constant value containing the base address for a pending read
|
||||
* @return {@code null} if {@code base} does not box an object otherwise the object boxed in
|
||||
* {@code base}
|
||||
*/
|
||||
private Object asObject(Constant base, JavaKind kind, long displacement) {
|
||||
if (base instanceof HotSpotObjectConstantImpl) {
|
||||
return ((HotSpotObjectConstantImpl) base).object();
|
||||
} else {
|
||||
return null;
|
||||
HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
|
||||
HotSpotResolvedObjectType type = constant.getType();
|
||||
Object object = constant.object();
|
||||
checkRead(kind, displacement, type, object);
|
||||
return object;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
|
||||
* as initialization is idempotent.
|
||||
*/
|
||||
private long oopSizeOffset;
|
||||
|
||||
private static int computeOopSizeOffset(HotSpotJVMCIRuntimeProvider runtime) {
|
||||
MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
|
||||
ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
|
||||
for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
|
||||
if (f.getName().equals("oop_size")) {
|
||||
int offset = ((HotSpotResolvedJavaField) f).offset();
|
||||
assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
|
||||
}
|
||||
|
||||
private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object) {
|
||||
if (type.isArray()) {
|
||||
ResolvedJavaType componentType = type.getComponentType();
|
||||
JavaKind componentKind = componentType.getJavaKind();
|
||||
final int headerSize = getArrayBaseOffset(componentKind);
|
||||
int sizeOfElement = getArrayIndexScale(componentKind);
|
||||
int length = Array.getLength(object);
|
||||
long arrayEnd = headerSize + (sizeOfElement * length);
|
||||
boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
|
||||
if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
|
||||
int index = (int) ((displacement - headerSize) / sizeOfElement);
|
||||
throw new AssertionError("Unsafe array access: reading element of kind " + kind +
|
||||
" at offset " + displacement + " (index ~ " + index + ") in " +
|
||||
type.toJavaName() + " object of length " + length);
|
||||
}
|
||||
} else if (kind != JavaKind.Object) {
|
||||
long size;
|
||||
if (object instanceof Class) {
|
||||
if (oopSizeOffset == 0) {
|
||||
oopSizeOffset = computeOopSizeOffset(runtime);
|
||||
}
|
||||
int wordSize = runtime.getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
|
||||
size = UNSAFE.getInt(object, oopSizeOffset) * wordSize;
|
||||
} else {
|
||||
size = Math.abs(type.instanceSize());
|
||||
}
|
||||
int bytesToRead = kind.getByteCount();
|
||||
if (displacement + bytesToRead > size || displacement < 0) {
|
||||
throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
|
||||
type.toJavaName() + " object of size " + size);
|
||||
}
|
||||
} else {
|
||||
ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
|
||||
if (field == null && object instanceof Class) {
|
||||
// Read of a static field
|
||||
MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
|
||||
HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object);
|
||||
field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
|
||||
}
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
|
||||
" at offset " + displacement + " in " + type.toJavaName() + " object");
|
||||
}
|
||||
if (field.getJavaKind() != JavaKind.Object) {
|
||||
throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
|
||||
" at offset " + displacement + " in " + type.toJavaName() + " object");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
|
||||
@ -77,8 +166,8 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
throw new IllegalArgumentException(String.valueOf(base));
|
||||
}
|
||||
|
||||
private static long readRawValue(Constant baseConstant, long displacement, int bits) {
|
||||
Object base = asObject(baseConstant);
|
||||
private long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
|
||||
Object base = asObject(baseConstant, kind, displacement);
|
||||
if (base != null) {
|
||||
switch (bits) {
|
||||
case Byte.SIZE:
|
||||
@ -123,9 +212,8 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
|
||||
private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
|
||||
long displacement = initialDisplacement;
|
||||
|
||||
Object ret;
|
||||
Object base = asObject(baseConstant);
|
||||
Object base = asObject(baseConstant, JavaKind.Object, displacement);
|
||||
if (base == null) {
|
||||
assert !compressed;
|
||||
displacement += asRawPointer(baseConstant);
|
||||
@ -138,34 +226,43 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a value of this kind using a base address and a displacement. No bounds checking or
|
||||
* type checking is performed. Returns {@code null} if the value is not available at this point.
|
||||
*
|
||||
* @param baseConstant the base address from which the value is read.
|
||||
* @param displacement the displacement within the object in bytes
|
||||
* @return the read value encapsulated in a {@link JavaConstant} object, or {@code null} if the
|
||||
* value cannot be read.
|
||||
* @throws IllegalArgumentException if {@code kind} is {@code null}, {@link JavaKind#Void}, not
|
||||
* {@link JavaKind#Object} or not {@linkplain JavaKind#isPrimitive() primitive} kind
|
||||
*/
|
||||
JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) {
|
||||
if (kind == null) {
|
||||
throw new IllegalArgumentException("null JavaKind");
|
||||
}
|
||||
if (kind == JavaKind.Object) {
|
||||
Object o = readRawObject(baseConstant, displacement, runtime.getConfig().useCompressedOops);
|
||||
JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj) {
|
||||
assert obj != null;
|
||||
assert !field.isStatic() || obj instanceof Class;
|
||||
long displacement = field.offset();
|
||||
assert checkRead(field.getJavaKind(), displacement, (HotSpotResolvedObjectType) runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(obj.getClass()), obj);
|
||||
if (field.getJavaKind() == JavaKind.Object) {
|
||||
Object o = UNSAFE.getObject(obj, displacement);
|
||||
return HotSpotObjectConstantImpl.forObject(o);
|
||||
} else {
|
||||
int bits = kind.getByteCount() * Byte.SIZE;
|
||||
return readPrimitiveConstant(kind, baseConstant, displacement, bits);
|
||||
JavaKind kind = field.getJavaKind();
|
||||
switch (kind) {
|
||||
case Boolean:
|
||||
return JavaConstant.forBoolean(UNSAFE.getBoolean(obj, displacement));
|
||||
case Byte:
|
||||
return JavaConstant.forByte(UNSAFE.getByte(obj, displacement));
|
||||
case Char:
|
||||
return JavaConstant.forChar(UNSAFE.getChar(obj, displacement));
|
||||
case Short:
|
||||
return JavaConstant.forShort(UNSAFE.getShort(obj, displacement));
|
||||
case Int:
|
||||
return JavaConstant.forInt(UNSAFE.getInt(obj, displacement));
|
||||
case Long:
|
||||
return JavaConstant.forLong(UNSAFE.getLong(obj, displacement));
|
||||
case Float:
|
||||
return JavaConstant.forFloat(UNSAFE.getFloat(obj, displacement));
|
||||
case Double:
|
||||
return JavaConstant.forDouble(UNSAFE.getDouble(obj, displacement));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported kind: " + kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
|
||||
try {
|
||||
long rawValue = readRawValue(baseConstant, initialDisplacement, bits);
|
||||
long rawValue = readRawValue(baseConstant, initialDisplacement, kind, bits);
|
||||
switch (kind) {
|
||||
case Boolean:
|
||||
return JavaConstant.forBoolean(rawValue != 0);
|
||||
@ -193,6 +290,10 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
|
||||
@Override
|
||||
public JavaConstant readObjectConstant(Constant base, long displacement) {
|
||||
if (base instanceof HotSpotObjectConstantImpl) {
|
||||
Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
|
||||
return HotSpotObjectConstantImpl.forObject(o);
|
||||
}
|
||||
if (!isValidObjectFieldDisplacement(base, displacement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -847,6 +847,15 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
@Override
|
||||
public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
|
||||
ResolvedJavaField[] declaredFields = getInstanceFields(true);
|
||||
return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
|
||||
}
|
||||
|
||||
public ResolvedJavaField findStaticFieldWithOffset(long offset, JavaKind expectedEntryKind) {
|
||||
ResolvedJavaField[] declaredFields = getStaticFields();
|
||||
return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
|
||||
}
|
||||
|
||||
private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
|
||||
for (ResolvedJavaField field : declaredFields) {
|
||||
HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
|
||||
long resolvedFieldOffset = resolvedField.offset();
|
||||
|
||||
@ -35,9 +35,9 @@ public interface MemoryAccessProvider {
|
||||
* @param displacement the displacement within the object in bytes
|
||||
* @param bits the number of bits to read from memory
|
||||
* @return the read value encapsulated in a {@link JavaConstant} object of {@link JavaKind} kind
|
||||
* @throws IllegalArgumentException if {@code kind} is {@link JavaKind#Void} or not
|
||||
* {@linkplain JavaKind#isPrimitive() primitive} kind or {@code bits} is not 8, 16,
|
||||
* 32 or 64
|
||||
* @throws IllegalArgumentException if the read is out of bounds of the object or {@code kind}
|
||||
* is {@link JavaKind#Void} or not {@linkplain JavaKind#isPrimitive() primitive}
|
||||
* kind or {@code bits} is not 8, 16, 32 or 64
|
||||
*/
|
||||
JavaConstant readPrimitiveConstant(JavaKind kind, Constant base, long displacement, int bits) throws IllegalArgumentException;
|
||||
|
||||
@ -46,9 +46,9 @@ public interface MemoryAccessProvider {
|
||||
*
|
||||
* @param base the base address from which the value is read
|
||||
* @param displacement the displacement within the object in bytes
|
||||
* @return the read value encapsulated in a {@link Constant} object or {@code null} if the
|
||||
* address computed from {@code base} and {@code displacement} does not denote a
|
||||
* location holding an {@code Object} value
|
||||
* @return the read value encapsulated in a {@link Constant} object
|
||||
* @throws IllegalArgumentException if the address computed from {@code base} and
|
||||
* {@code displacement} does not denote a location holding an {@code Object} value
|
||||
*/
|
||||
JavaConstant readObjectConstant(Constant base, long displacement);
|
||||
}
|
||||
|
||||
@ -28,9 +28,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
|
||||
@ -43,6 +40,9 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
import org.graalvm.compiler.phases.BasePhase;
|
||||
import org.graalvm.compiler.phases.tiers.PhaseContext;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
|
||||
public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> {
|
||||
/**
|
||||
* Find blocks with class initializing nodes for the class identified the by the constant node.
|
||||
@ -202,7 +202,7 @@ public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContex
|
||||
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, false);
|
||||
ArrayList<Node> redundantInits = new ArrayList<>();
|
||||
for (ConstantNode node : getConstantNodes(graph)) {
|
||||
JavaConstant constant = node.asJavaConstant();
|
||||
Constant constant = node.asConstant();
|
||||
if (constant instanceof HotSpotMetaspaceConstant) {
|
||||
redundantInits.addAll(processConstantNode(cfg, node));
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import java.lang.reflect.Field;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
|
||||
@ -36,6 +37,10 @@ import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.runtime.JVMCI;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MemoryAccessProviderData {
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
@ -43,6 +48,18 @@ public class MemoryAccessProviderData {
|
||||
private static final TestClass TEST_OBJECT = new TestClass();
|
||||
private static final JavaConstant TEST_CONSTANT = CONSTANT_REFLECTION.forObject(TEST_OBJECT);
|
||||
private static final JavaConstant TEST_CLASS_CONSTANT = CONSTANT_REFLECTION.forObject(TestClass.class);
|
||||
private static KindData[] PRIMITIVE_KIND_DATA = {
|
||||
new KindData(JavaKind.Boolean, TEST_OBJECT),
|
||||
new KindData(JavaKind.Byte, TEST_OBJECT),
|
||||
new KindData(JavaKind.Char, TEST_OBJECT),
|
||||
new KindData(JavaKind.Short, TEST_OBJECT),
|
||||
new KindData(JavaKind.Int, TEST_OBJECT),
|
||||
new KindData(JavaKind.Float, TEST_OBJECT),
|
||||
new KindData(JavaKind.Long, TEST_OBJECT),
|
||||
new KindData(JavaKind.Double, TEST_OBJECT)
|
||||
};
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
|
||||
|
||||
@DataProvider(name = "positiveObject")
|
||||
public static Object[][] getPositiveObjectJavaKind() {
|
||||
@ -54,51 +71,40 @@ public class MemoryAccessProviderData {
|
||||
|
||||
@DataProvider(name = "positivePrimitive")
|
||||
public static Object[][] getPositivePrimitiveJavaKinds() {
|
||||
Field booleanField;
|
||||
Field byteField;
|
||||
Field shortField;
|
||||
Field intField;
|
||||
Field longField;
|
||||
Field floatField;
|
||||
Field doubleField;
|
||||
Field charField;
|
||||
try {
|
||||
booleanField = MemoryAccessProviderData.TestClass.class.getDeclaredField("booleanField");
|
||||
byteField = MemoryAccessProviderData.TestClass.class.getDeclaredField("byteField");
|
||||
shortField = MemoryAccessProviderData.TestClass.class.getDeclaredField("shortField");
|
||||
intField = MemoryAccessProviderData.TestClass.class.getDeclaredField("intField");
|
||||
longField = MemoryAccessProviderData.TestClass.class.getDeclaredField("longField");
|
||||
floatField = MemoryAccessProviderData.TestClass.class.getDeclaredField("floatField");
|
||||
doubleField = MemoryAccessProviderData.TestClass.class.getDeclaredField("doubleField");
|
||||
charField = MemoryAccessProviderData.TestClass.class.getDeclaredField("charField");
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new Error("TESTBUG: can't find test field " + e, e);
|
||||
List<Object[]> result = new ArrayList<>();
|
||||
for (KindData k : PRIMITIVE_KIND_DATA) {
|
||||
result.add(new Object[] {k.kind, TEST_CONSTANT, k.instanceFieldOffset, k.instanceFieldValue, Math.max(8, k.kind.getBitCount())});
|
||||
result.add(new Object[] {k.kind, TEST_CLASS_CONSTANT, k.staticFieldOffset, k.staticFieldValue, Math.max(8, k.kind.getBitCount())});
|
||||
}
|
||||
long booleanFieldOffset = UNSAFE.objectFieldOffset(booleanField);
|
||||
long byteFieldOffset = UNSAFE.objectFieldOffset(byteField);
|
||||
long shortFieldOffset = UNSAFE.objectFieldOffset(shortField);
|
||||
long intFieldOffset = UNSAFE.objectFieldOffset(intField);
|
||||
long longFieldOffset = UNSAFE.objectFieldOffset(longField);
|
||||
long floatFieldOffset = UNSAFE.objectFieldOffset(floatField);
|
||||
long doubleFieldOffset = UNSAFE.objectFieldOffset(doubleField);
|
||||
long charFieldOffset = UNSAFE.objectFieldOffset(charField);
|
||||
return new Object[][]{
|
||||
new Object[]{JavaKind.Boolean, TEST_CONSTANT, booleanFieldOffset,
|
||||
JavaConstant.forBoolean(TEST_OBJECT.booleanField), 8},
|
||||
new Object[]{JavaKind.Byte, TEST_CONSTANT, byteFieldOffset,
|
||||
JavaConstant.forByte(TEST_OBJECT.byteField), 8},
|
||||
new Object[]{JavaKind.Short, TEST_CONSTANT, shortFieldOffset,
|
||||
JavaConstant.forShort(TEST_OBJECT.shortField), 16},
|
||||
new Object[]{JavaKind.Int, TEST_CONSTANT, intFieldOffset,
|
||||
JavaConstant.forInt(TEST_OBJECT.intField), 32},
|
||||
new Object[]{JavaKind.Long, TEST_CONSTANT, longFieldOffset,
|
||||
JavaConstant.forLong(TEST_OBJECT.longField), 64},
|
||||
new Object[]{JavaKind.Float, TEST_CONSTANT, floatFieldOffset,
|
||||
JavaConstant.forFloat(TEST_OBJECT.floatField), 32},
|
||||
new Object[]{JavaKind.Double, TEST_CONSTANT, doubleFieldOffset,
|
||||
JavaConstant.forDouble(TEST_OBJECT.doubleField), 64},
|
||||
new Object[]{JavaKind.Char, TEST_CONSTANT, charFieldOffset,
|
||||
JavaConstant.forChar(TEST_OBJECT.charField), 16}};
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "outOfBoundsInstanceFields")
|
||||
public static Object[][] getOutOfBoundsStaticFieldReads() {
|
||||
long instanceSize = WHITE_BOX.getObjectSize(TEST_OBJECT);
|
||||
List<Object[]> result = new ArrayList<>();
|
||||
for (KindData k : PRIMITIVE_KIND_DATA) {
|
||||
long lastValidOffset = instanceSize - (k.kind.getByteCount());
|
||||
result.add(new Object[] {k.kind, TEST_CONSTANT, lastValidOffset, false});
|
||||
result.add(new Object[] {k.kind, TEST_CONSTANT, (long) -1, true});
|
||||
result.add(new Object[] {k.kind, TEST_CONSTANT, lastValidOffset + 1, true});
|
||||
result.add(new Object[] {k.kind, TEST_CONSTANT, lastValidOffset + 100, true});
|
||||
}
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "outOfBoundsStaticFields")
|
||||
public static Object[][] getOutOfBoundsInstanceFieldReads() {
|
||||
long staticsSize = WHITE_BOX.getObjectSize(TEST_OBJECT.getClass());
|
||||
List<Object[]> result = new ArrayList<>();
|
||||
for (KindData k : PRIMITIVE_KIND_DATA) {
|
||||
long lastValidOffset = staticsSize - (k.kind.getByteCount());
|
||||
result.add(new Object[] {k.kind, TEST_CLASS_CONSTANT, lastValidOffset, false});
|
||||
result.add(new Object[] {k.kind, TEST_CLASS_CONSTANT, (long) -1, true});
|
||||
result.add(new Object[] {k.kind, TEST_CLASS_CONSTANT, lastValidOffset + 1, true});
|
||||
result.add(new Object[] {k.kind, TEST_CLASS_CONSTANT, lastValidOffset + 100, true});
|
||||
}
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "negative")
|
||||
@ -108,6 +114,7 @@ public class MemoryAccessProviderData {
|
||||
new Object[]{JavaKind.Illegal, JavaConstant.INT_1}};
|
||||
}
|
||||
|
||||
|
||||
private static class TestClass {
|
||||
public final boolean booleanField = true;
|
||||
public final byte byteField = 2;
|
||||
@ -117,6 +124,43 @@ public class MemoryAccessProviderData {
|
||||
public final double doubleField = 6.0d;
|
||||
public final float floatField = 7.0f;
|
||||
public final char charField = 'a';
|
||||
public final String stringField = "abc";
|
||||
public final String objectField = "abc";
|
||||
|
||||
public static final boolean booleanStaticField = true;
|
||||
public static final byte byteStaticField = 2;
|
||||
public static final short shortStaticField = 3;
|
||||
public static final int intStaticField = 4;
|
||||
public static final long longStaticField = 5L;
|
||||
public static final double doubleStaticField = 6.0d;
|
||||
public static final float floatStaticField = 7.0f;
|
||||
public static final char charStaticField = 'a';
|
||||
public static final String objectStaticField = "abc";
|
||||
}
|
||||
|
||||
|
||||
static class KindData {
|
||||
final JavaKind kind;
|
||||
final Field instanceField;
|
||||
final Field staticField;
|
||||
final long instanceFieldOffset;
|
||||
final long staticFieldOffset;
|
||||
final JavaConstant instanceFieldValue;
|
||||
final JavaConstant staticFieldValue;
|
||||
KindData(JavaKind kind, Object testObject) {
|
||||
this.kind = kind;
|
||||
try {
|
||||
Class<?> c = testObject.getClass();
|
||||
instanceField = c.getDeclaredField(kind.getJavaName() + "Field");
|
||||
staticField = c.getDeclaredField(kind.getJavaName() + "StaticField");
|
||||
instanceField.setAccessible(true);
|
||||
staticField.setAccessible(true);
|
||||
instanceFieldOffset = UNSAFE.objectFieldOffset(instanceField);
|
||||
staticFieldOffset = UNSAFE.staticFieldOffset(staticField);
|
||||
instanceFieldValue = JavaConstant.forBoxedPrimitive(instanceField.get(testObject));
|
||||
staticFieldValue = JavaConstant.forBoxedPrimitive(staticField.get(null));
|
||||
} catch (Exception e) {
|
||||
throw new Error("TESTBUG for kind " + kind, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,12 +31,19 @@
|
||||
* jdk.internal.vm.ci/jdk.vm.ci.runtime
|
||||
* jdk.internal.vm.ci/jdk.vm.ci.hotspot
|
||||
* java.base/jdk.internal.misc
|
||||
* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run testng/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
|
||||
* jdk.vm.ci.hotspot.test.MemoryAccessProviderTest
|
||||
*/
|
||||
|
||||
package jdk.vm.ci.hotspot.test;
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MemoryAccessProvider;
|
||||
@ -59,7 +66,27 @@ public class MemoryAccessProviderTest {
|
||||
|
||||
@Test(dataProvider = "negative", dataProviderClass = MemoryAccessProviderData.class, expectedExceptions = {IllegalArgumentException.class})
|
||||
public void testNegativeReadPrimitiveConstant(JavaKind kind, Constant base) {
|
||||
PROVIDER.readPrimitiveConstant(kind, base, 0L, kind == null ? 0 : kind.getBitCount());
|
||||
PROVIDER.readPrimitiveConstant(kind, base, 0L, kind == null ? 0 : kind.getByteCount() / 8);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "outOfBoundsInstanceFields", dataProviderClass = MemoryAccessProviderData.class)
|
||||
public void testReadPrimitiveInstanceFieldOutOfBounds(JavaKind kind, Constant base, Long offset, boolean isOutOfBounds) {
|
||||
try {
|
||||
PROVIDER.readPrimitiveConstant(kind, base, offset, kind.getByteCount() * 8);
|
||||
Assert.assertFalse(isOutOfBounds);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertTrue(isOutOfBounds);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "outOfBoundsStaticFields", dataProviderClass = MemoryAccessProviderData.class)
|
||||
public void testReadPrimitiveStaticFieldOutOFBounds(JavaKind kind, Constant base, Long offset, boolean isOutOfBounds) {
|
||||
try {
|
||||
PROVIDER.readPrimitiveConstant(kind, base, offset, kind.getByteCount() * 8);
|
||||
Assert.assertFalse(isOutOfBounds);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertTrue(isOutOfBounds);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "positiveObject", dataProviderClass = MemoryAccessProviderData.class, expectedExceptions = {IllegalArgumentException.class})
|
||||
@ -87,7 +114,7 @@ public class MemoryAccessProviderTest {
|
||||
Assert.assertNull(PROVIDER.readObjectConstant(base, offset + 1), "Expected null");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "positivePrimitive", dataProviderClass = MemoryAccessProviderData.class)
|
||||
@Test(dataProvider = "positivePrimitive", dataProviderClass = MemoryAccessProviderData.class, expectedExceptions = {IllegalArgumentException.class})
|
||||
public void testNegativeReadObjectConstantPrimitiveBase(JavaKind kind, Constant base, Long offset, Object expected, int bitsCount) {
|
||||
Assert.assertNull(PROVIDER.readObjectConstant(base, offset), "Expected null");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user