8156552: [JVMCI] remove final and stable field handling from ConstantReflectionProvider
Reviewed-by: kvn, twisti
This commit is contained in:
parent
5405125902
commit
476ef7367c
hotspot
src/jdk.vm.ci/share/classes
jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
HotSpotConstantReflectionProvider.javaHotSpotJVMCIRuntime.javaHotSpotObjectConstantImpl.javaHotSpotResolvedJavaField.javaHotSpotResolvedJavaFieldImpl.java
jdk.vm.ci.meta/src/jdk/vm/ci/meta
test/compiler/jvmci
jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test
HotSpotConstantReflectionProviderTest.javaReadConstantArrayElementDataProvider.javaReadConstantFieldValueDataProvider.javaReadStableFieldValueDataProvider.javaTestHelper.java
jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test
@ -22,20 +22,15 @@
|
||||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.meta.MemoryAccessProvider;
|
||||
import jdk.vm.ci.meta.MethodHandleAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
@ -89,50 +84,6 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
return Array.getLength(arrayObject);
|
||||
}
|
||||
|
||||
public JavaConstant readConstantArrayElement(JavaConstant array, int index) {
|
||||
if (array instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) array).getStableDimension() > 0) {
|
||||
JavaConstant element = readArrayElement(array, index);
|
||||
if (element != null && (((HotSpotObjectConstantImpl) array).isDefaultStable() || !element.isDefaultForKind())) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert {@code offset} into an an index into {@code array}.
|
||||
*
|
||||
* @return the computed index or -1 if the offset isn't within the array
|
||||
*/
|
||||
private int indexForOffset(JavaConstant array, long offset) {
|
||||
if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
|
||||
return -1;
|
||||
}
|
||||
Class<?> componentType = ((HotSpotObjectConstantImpl) array).object().getClass().getComponentType();
|
||||
JavaKind kind = runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(componentType).getJavaKind();
|
||||
int arraybase = getArrayBaseOffset(kind);
|
||||
int scale = getArrayIndexScale(kind);
|
||||
if (offset < arraybase) {
|
||||
return -1;
|
||||
}
|
||||
long index = offset - arraybase;
|
||||
if (index % scale != 0) {
|
||||
return -1;
|
||||
}
|
||||
long result = index / scale;
|
||||
if (result >= Integer.MAX_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
public JavaConstant readConstantArrayElementForOffset(JavaConstant array, long offset) {
|
||||
if (array instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) array).getStableDimension() > 0) {
|
||||
return readConstantArrayElement(array, indexForOffset(array, offset));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant readArrayElement(JavaConstant array, int index) {
|
||||
if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
|
||||
@ -146,11 +97,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
|
||||
if (a instanceof Object[]) {
|
||||
Object element = ((Object[]) a)[index];
|
||||
if (((HotSpotObjectConstantImpl) array).getStableDimension() > 1) {
|
||||
return HotSpotObjectConstantImpl.forStableArray(element, ((HotSpotObjectConstantImpl) array).getStableDimension() - 1, ((HotSpotObjectConstantImpl) array).isDefaultStable());
|
||||
} else {
|
||||
return HotSpotObjectConstantImpl.forObject(element);
|
||||
}
|
||||
return HotSpotObjectConstantImpl.forObject(element);
|
||||
} else {
|
||||
return JavaConstant.forBoxedPrimitive(Array.get(a, index));
|
||||
}
|
||||
@ -228,102 +175,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final String SystemClassName = "Ljava/lang/System;";
|
||||
|
||||
/**
|
||||
* Determines if a static field is constant for the purpose of
|
||||
* {@link #readConstantFieldValue(ResolvedJavaField, JavaConstant)}.
|
||||
*/
|
||||
protected boolean isStaticFieldConstant(HotSpotResolvedJavaField staticField) {
|
||||
if (staticField.isFinal() || (staticField.isStable() && runtime.getConfig().foldStableValues)) {
|
||||
ResolvedJavaType holder = staticField.getDeclaringClass();
|
||||
if (holder.isInitialized() && !holder.getName().equals(SystemClassName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a value read from a {@code final} instance field is considered constant. The
|
||||
* implementation in {@link HotSpotConstantReflectionProvider} returns true if {@code value} is
|
||||
* not the {@link JavaConstant#isDefaultForKind default value} for its kind or if
|
||||
* {@link Option#TrustFinalDefaultFields} is true.
|
||||
*
|
||||
* @param value a value read from a {@code final} instance field
|
||||
* @param receiverClass the {@link Object#getClass() class} of object from which the
|
||||
* {@code value} was read
|
||||
*/
|
||||
protected boolean isFinalInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
|
||||
return !value.isDefaultForKind() || Option.TrustFinalDefaultFields.getBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a value read from a {@link Stable} instance field is considered constant. The
|
||||
* implementation in {@link HotSpotConstantReflectionProvider} returns true if {@code value} is
|
||||
* not the {@link JavaConstant#isDefaultForKind default value} for its kind.
|
||||
*
|
||||
* @param value a value read from a {@link Stable} field
|
||||
* @param receiverClass the {@link Object#getClass() class} of object from which the
|
||||
* {@code value} was read
|
||||
*/
|
||||
protected boolean isStableInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
|
||||
return !value.isDefaultForKind();
|
||||
}
|
||||
|
||||
public JavaConstant readConstantFieldValue(ResolvedJavaField field, JavaConstant receiver) {
|
||||
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
|
||||
|
||||
if (hotspotField.isStatic()) {
|
||||
if (isStaticFieldConstant(hotspotField)) {
|
||||
JavaConstant value = readFieldValue(field, receiver);
|
||||
if (hotspotField.isFinal() || !value.isDefaultForKind()) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* for non-static final fields, we must assume that they are only initialized if they
|
||||
* have a non-default value.
|
||||
*/
|
||||
Object object = receiver.isNull() ? null : ((HotSpotObjectConstantImpl) receiver).object();
|
||||
|
||||
// Canonicalization may attempt to process an unsafe read before
|
||||
// processing a guard (e.g. a null check or a type check) for this read
|
||||
// so we need to check the object being read
|
||||
if (object != null) {
|
||||
if (hotspotField.isFinal()) {
|
||||
if (hotspotField.isInObject(object)) {
|
||||
JavaConstant value = readFieldValue(field, receiver);
|
||||
if (isFinalInstanceFieldValueConstant(value, object.getClass())) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} else if (hotspotField.isStable() && runtime.getConfig().foldStableValues) {
|
||||
if (hotspotField.isInObject(object)) {
|
||||
JavaConstant value = readFieldValue(field, receiver);
|
||||
if (isStableInstanceFieldValueConstant(value, object.getClass())) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) {
|
||||
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
|
||||
if (!hotspotField.isStable()) {
|
||||
return readNonStableFieldValue(field, receiver);
|
||||
} else if (runtime.getConfig().foldStableValues) {
|
||||
return readStableFieldValue(field, receiver, hotspotField.isDefaultStable());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private JavaConstant readNonStableFieldValue(ResolvedJavaField field, JavaConstant receiver) {
|
||||
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
|
||||
if (hotspotField.isStatic()) {
|
||||
HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
|
||||
@ -338,27 +190,6 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
return null;
|
||||
}
|
||||
|
||||
public JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable) {
|
||||
JavaConstant fieldValue = readNonStableFieldValue(field, receiver);
|
||||
if (fieldValue != null && fieldValue.isNonNull()) {
|
||||
JavaType declaredType = field.getType();
|
||||
if (declaredType.getComponentType() != null) {
|
||||
int stableDimension = getArrayDimension(declaredType);
|
||||
return HotSpotObjectConstantImpl.forStableArray(((HotSpotObjectConstantImpl) fieldValue).object(), stableDimension, isDefaultStable);
|
||||
}
|
||||
}
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
private static int getArrayDimension(JavaType type) {
|
||||
int dimensions = 0;
|
||||
JavaType componentType = type;
|
||||
while ((componentType = componentType.getComponentType()) != null) {
|
||||
dimensions++;
|
||||
}
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant asJavaClass(ResolvedJavaType type) {
|
||||
return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedJavaType) type).mirror());
|
||||
|
4
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
4
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
@ -95,14 +95,12 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H
|
||||
*/
|
||||
public enum Option {
|
||||
Compiler(String.class, null, "Selects the system compiler."),
|
||||
ImplicitStableValues(boolean.class, true, "Mark well-known stable fields as such."),
|
||||
// Note: The following one is not used (see InitTimer.ENABLED).
|
||||
InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
|
||||
PrintConfig(boolean.class, false, "Prints all HotSpotVMConfig fields."),
|
||||
PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
|
||||
ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
|
||||
TraceMethodDataFilter(String.class, null, ""),
|
||||
TrustFinalDefaultFields(boolean.class, true, "Determines whether to treat final fields with default values as constant.");
|
||||
TraceMethodDataFilter(String.class, null, "");
|
||||
|
||||
/**
|
||||
* The prefix for system properties that are JVMCI options.
|
||||
|
@ -53,15 +53,6 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotP
|
||||
}
|
||||
}
|
||||
|
||||
static JavaConstant forStableArray(Object object, int stableDimension, boolean isDefaultStable) {
|
||||
if (object == null) {
|
||||
return JavaConstant.NULL_POINTER;
|
||||
} else {
|
||||
assert object.getClass().isArray();
|
||||
return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
|
||||
}
|
||||
}
|
||||
|
||||
public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
|
||||
if (kind == JavaKind.Object) {
|
||||
return HotSpotObjectConstantImpl.forObject(value);
|
||||
@ -82,22 +73,11 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotP
|
||||
|
||||
private final Object object;
|
||||
private final boolean compressed;
|
||||
private final byte stableDimension;
|
||||
private final boolean isDefaultStable;
|
||||
|
||||
private HotSpotObjectConstantImpl(Object object, boolean compressed, int stableDimension, boolean isDefaultStable) {
|
||||
this.object = object;
|
||||
this.compressed = compressed;
|
||||
this.stableDimension = (byte) stableDimension;
|
||||
this.isDefaultStable = isDefaultStable;
|
||||
assert object != null;
|
||||
assert stableDimension == 0 || (object != null && object.getClass().isArray());
|
||||
assert stableDimension >= 0 && stableDimension <= 255;
|
||||
assert !isDefaultStable || stableDimension > 0;
|
||||
}
|
||||
|
||||
private HotSpotObjectConstantImpl(Object object, boolean compressed) {
|
||||
this(object, compressed, 0, false);
|
||||
this.object = object;
|
||||
this.compressed = compressed;
|
||||
assert object != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,12 +98,12 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotP
|
||||
|
||||
public JavaConstant compress() {
|
||||
assert !compressed;
|
||||
return new HotSpotObjectConstantImpl(object, true, stableDimension, isDefaultStable);
|
||||
return new HotSpotObjectConstantImpl(object, true);
|
||||
}
|
||||
|
||||
public JavaConstant uncompress() {
|
||||
assert compressed;
|
||||
return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
|
||||
return new HotSpotObjectConstantImpl(object, false);
|
||||
}
|
||||
|
||||
public HotSpotResolvedObjectType getType() {
|
||||
@ -248,7 +228,7 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotP
|
||||
return true;
|
||||
} else if (o instanceof HotSpotObjectConstantImpl) {
|
||||
HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
|
||||
return object == other.object && compressed == other.compressed && stableDimension == other.stableDimension && isDefaultStable == other.isDefaultStable;
|
||||
return object == other.object && compressed == other.compressed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -266,19 +246,4 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotP
|
||||
public String toString() {
|
||||
return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of stable dimensions if this constant is a stable array.
|
||||
*/
|
||||
public int getStableDimension() {
|
||||
return stableDimension & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this is a stable array constant and its elements should be considered
|
||||
* as stable regardless of whether they are default values.
|
||||
*/
|
||||
public boolean isDefaultStable() {
|
||||
return isDefaultStable;
|
||||
}
|
||||
}
|
||||
|
@ -43,11 +43,4 @@ public interface HotSpotResolvedJavaField extends ResolvedJavaField {
|
||||
* Determines if this field should be treated as a constant.
|
||||
*/
|
||||
boolean isStable();
|
||||
|
||||
/**
|
||||
* Determines if this field should be considered constant if it has the default value for its
|
||||
* type (e.g, 0, null, etc.). The result of this method is undefined if this field is not
|
||||
* {@linkplain #isStable() stable}.
|
||||
*/
|
||||
boolean isDefaultStable();
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@ -153,14 +152,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotP
|
||||
* @return true if field has {@link Stable} annotation, false otherwise
|
||||
*/
|
||||
public boolean isStable() {
|
||||
if ((config().jvmAccFieldStable & modifiers) != 0) {
|
||||
return true;
|
||||
}
|
||||
assert getAnnotation(Stable.class) == null;
|
||||
if (Option.ImplicitStableValues.getBoolean() && isImplicitStableField()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (config().jvmAccFieldStable & modifiers) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -206,65 +198,4 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotP
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isArray() {
|
||||
JavaType fieldType = getType();
|
||||
return fieldType instanceof ResolvedJavaType && ((ResolvedJavaType) fieldType).isArray();
|
||||
}
|
||||
|
||||
private boolean isImplicitStableField() {
|
||||
if (isSyntheticEnumSwitchMap()) {
|
||||
return true;
|
||||
}
|
||||
if (isWellKnownImplicitStableField()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDefaultStable() {
|
||||
assert this.isStable();
|
||||
if (isSyntheticEnumSwitchMap()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSyntheticEnumSwitchMap() {
|
||||
if (isSynthetic() && isStatic() && isArray()) {
|
||||
if (isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) {
|
||||
// generated int[] field for EnumClass::values()
|
||||
return true;
|
||||
} else if (name.startsWith("$SwitchMap$") || name.startsWith("$SWITCH_TABLE$")) {
|
||||
// javac and ecj generate a static field in an inner class for a switch on an enum
|
||||
// named $SwitchMap$p$k$g$EnumClass and $SWITCH_TABLE$p$k$g$EnumClass, respectively
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isWellKnownImplicitStableField() {
|
||||
return WellKnownImplicitStableField.test(this);
|
||||
}
|
||||
|
||||
static class WellKnownImplicitStableField {
|
||||
/**
|
||||
* @return {@code true} if the field is a well-known stable field.
|
||||
*/
|
||||
public static boolean test(HotSpotResolvedJavaField field) {
|
||||
return field.equals(STRING_VALUE_FIELD);
|
||||
}
|
||||
|
||||
private static final ResolvedJavaField STRING_VALUE_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
MetaAccessProvider metaAccess = runtime().getHostJVMCIBackend().getMetaAccess();
|
||||
STRING_VALUE_FIELD = metaAccess.lookupJavaField(String.class.getDeclaredField("value"));
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
throw new JVMCIError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,40 +55,11 @@ public interface ConstantReflectionProvider {
|
||||
*/
|
||||
JavaConstant readArrayElement(JavaConstant array, int index);
|
||||
|
||||
/**
|
||||
* Reads a value from the given array at the given index if it is a stable array. Returns
|
||||
* {@code null} if the constant is not a stable array, if it is a default value, if the index is
|
||||
* out of bounds, or if the value is not available at this point.
|
||||
*/
|
||||
JavaConstant readConstantArrayElement(JavaConstant array, int index);
|
||||
|
||||
/**
|
||||
* Reads a value from the given array at the given offset if it is a stable array. The offset
|
||||
* will be decoded relative to the platform addressing into an index into the array. Returns
|
||||
* {@code null} if the constant is not a stable array, if it is a default value, if the offset
|
||||
* is out of bounds, or if the value is not available at this point.
|
||||
*/
|
||||
JavaConstant readConstantArrayElementForOffset(JavaConstant array, long offset);
|
||||
|
||||
/**
|
||||
* Gets the constant value of this field. Note that a {@code static final} field may not be
|
||||
* considered constant if its declaring class is not yet initialized or if it is a well known
|
||||
* field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
|
||||
*
|
||||
* @param receiver object from which this field's value is to be read. This value is ignored if
|
||||
* this field is static.
|
||||
* @return the constant value of this field or {@code null} if this field is not considered
|
||||
* constant by the runtime
|
||||
*/
|
||||
JavaConstant readConstantFieldValue(ResolvedJavaField field, JavaConstant receiver);
|
||||
|
||||
/**
|
||||
* Gets the current value of this field for a given object, if available.
|
||||
*
|
||||
* There is no guarantee that the same value will be returned by this method for a field unless
|
||||
* the field is considered to be
|
||||
* {@linkplain #readConstantFieldValue(ResolvedJavaField, JavaConstant) constant} by the
|
||||
* runtime.
|
||||
* the field is considered to be constant by the runtime.
|
||||
*
|
||||
* @param receiver object from which this field's value is to be read. This value is ignored if
|
||||
* this field is static.
|
||||
@ -97,23 +68,6 @@ public interface ConstantReflectionProvider {
|
||||
*/
|
||||
JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver);
|
||||
|
||||
/**
|
||||
* Gets the current value of this field for a given object, if available. Like
|
||||
* {@link #readFieldValue(ResolvedJavaField, JavaConstant)} but treats array fields as stable.
|
||||
*
|
||||
* There is no guarantee that the same value will be returned by this method for a field unless
|
||||
* the field is considered to be
|
||||
* {@linkplain #readConstantFieldValue(ResolvedJavaField, JavaConstant) constant} by the
|
||||
* runtime.
|
||||
*
|
||||
* @param receiver object from which this field's value is to be read. This value is ignored if
|
||||
* this field is static.
|
||||
* @param isDefaultStable if {@code true}, default values are considered stable
|
||||
* @return the value of this field or {@code null} if the value is not available (e.g., because
|
||||
* the field holder is not yet initialized).
|
||||
*/
|
||||
JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable);
|
||||
|
||||
/**
|
||||
* Converts the given {@link JavaKind#isPrimitive() primitive} constant to a boxed
|
||||
* {@link JavaKind#Object object} constant, according to the Java boxing rules. Returns
|
||||
|
@ -100,80 +100,6 @@ public class HotSpotConstantReflectionProviderTest {
|
||||
CONSTANT_REFLECTION_PROVIDER.readFieldValue(field, receiver);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readStableFieldValueDataProvider", dataProviderClass = ReadStableFieldValueDataProvider.class)
|
||||
public void testReadStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefStab,
|
||||
JavaConstant expected) {
|
||||
Assert.assertEquals(
|
||||
CONSTANT_REFLECTION_PROVIDER.readStableFieldValue(field, receiver, isDefStab),
|
||||
expected,
|
||||
"Unexpected result:");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readStableFieldValueArrayDataProvider", dataProviderClass = ReadStableFieldValueDataProvider.class)
|
||||
public void testReadStableFieldValueForArray(ResolvedJavaField field, JavaConstant receiver, boolean isDefStab,
|
||||
int arrayDim, JavaConstant expected) {
|
||||
JavaConstant result = CONSTANT_REFLECTION_PROVIDER.readStableFieldValue(field, receiver,
|
||||
isDefStab);
|
||||
boolean resultDefStab = false;
|
||||
int resultStableDim = -1;
|
||||
try {
|
||||
Class<?> hotSpotObjectConstantImplClass = Class.forName(
|
||||
"jdk.vm.ci.hotspot.HotSpotObjectConstantImpl");
|
||||
Method getStableDimensionMethod = hotSpotObjectConstantImplClass.getDeclaredMethod(
|
||||
"getStableDimension");
|
||||
Method isDefaultStableMethod = hotSpotObjectConstantImplClass.getDeclaredMethod(
|
||||
"isDefaultStable");
|
||||
getStableDimensionMethod.setAccessible(true);
|
||||
isDefaultStableMethod.setAccessible(true);
|
||||
resultDefStab = (boolean) isDefaultStableMethod.invoke(result);
|
||||
resultStableDim = (int) getStableDimensionMethod.invoke(result);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new Error("Unexpected error: " + e, e);
|
||||
}
|
||||
Assert.assertEquals(resultDefStab, isDefStab,
|
||||
"Wrong default stable value for " + result.toString());
|
||||
Assert.assertEquals(resultStableDim, arrayDim,
|
||||
"Wrong array dimension for " + result.toString());
|
||||
Assert.assertEquals(result.toString(), expected.toString(), "Unexpected result:");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readStableFieldValueNegativeDataProvider", dataProviderClass = ReadStableFieldValueDataProvider.class, expectedExceptions = {NullPointerException.class})
|
||||
public void testNegativeReadStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefStab) {
|
||||
CONSTANT_REFLECTION_PROVIDER.readStableFieldValue(field, receiver, isDefStab);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readConstantFieldValueDataProvider", dataProviderClass = ReadConstantFieldValueDataProvider.class)
|
||||
public void testReadConstantFieldValue(ResolvedJavaField field, JavaConstant receiver, JavaConstant expected,
|
||||
String testInfo) {
|
||||
String msg = String.format("Unexpected result for %s. Field is stable = %s.", testInfo,
|
||||
((HotSpotResolvedJavaField) field).isStable());
|
||||
Assert.assertEquals(CONSTANT_REFLECTION_PROVIDER.readConstantFieldValue(field, receiver),
|
||||
expected, msg);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readConstantFieldValueNegativeDataProvider", dataProviderClass = ReadConstantFieldValueDataProvider.class, expectedExceptions = {NullPointerException.class})
|
||||
public void testNegativeReadConstantFieldValue(ResolvedJavaField field, JavaConstant receiver) {
|
||||
CONSTANT_REFLECTION_PROVIDER.readConstantFieldValue(field, receiver);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readConstantArrayElementDataProvider", dataProviderClass = ReadConstantArrayElementDataProvider.class)
|
||||
public void testReadConstantArrayElement(JavaConstant array, int index, JavaConstant expected, String testInfo) {
|
||||
JavaConstant actual = CONSTANT_REFLECTION_PROVIDER.readConstantArrayElement(array, index);
|
||||
Assert.assertEquals(actual == null ? "null" : actual.toString(),
|
||||
expected == null ? "null" : expected.toString(),
|
||||
String.format("Unexpected result while testing %s:", testInfo));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "readConstantArrayElementForOffsetDataProvider", dataProviderClass = ReadConstantArrayElementDataProvider.class)
|
||||
public void testReadConstantArrayElementForOffset(JavaConstant array, long offset, JavaConstant expected,
|
||||
String testInfo) {
|
||||
JavaConstant actual = CONSTANT_REFLECTION_PROVIDER.readConstantArrayElementForOffset(array,
|
||||
offset);
|
||||
Assert.assertEquals(actual == null ? "null" : actual.toString(),
|
||||
expected == null ? "null" : expected.toString(),
|
||||
String.format("Unexpected result while testing %s:", testInfo));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "asJavaTypeDataProvider", dataProviderClass = AsJavaTypeDataProvider.class)
|
||||
public void testAsJavaType(JavaConstant constant, String expected) {
|
||||
ResolvedJavaType actual = CONSTANT_REFLECTION_PROVIDER.asJavaType(constant);
|
||||
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 jdk.vm.ci.hotspot.test;
|
||||
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.ARRAY_ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.CONSTANT_REFLECTION_PROVIDER;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.DUMMY_CLASS_CONSTANT;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.DUMMY_CLASS_INSTANCE;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.getResolvedJavaField;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_STABLE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STABLE_ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STABLE_ARRAY_ARRAYS_MAP;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
|
||||
public class ReadConstantArrayElementDataProvider {
|
||||
|
||||
// Non-stable array fields names mapped to their base offsets and index scale
|
||||
private static final List<ArrayFieldParams> NON_STABLE_ARRAY_NAMES = new LinkedList<>();
|
||||
|
||||
static {
|
||||
NON_STABLE_ARRAY_NAMES.add(
|
||||
new ArrayFieldParams("booleanArrayWithValues", Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
|
||||
Unsafe.ARRAY_BOOLEAN_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("byteArrayWithValues",
|
||||
Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
Unsafe.ARRAY_BYTE_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("shortArrayWithValues",
|
||||
Unsafe.ARRAY_SHORT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_SHORT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("charArrayWithValues",
|
||||
Unsafe.ARRAY_CHAR_BASE_OFFSET,
|
||||
Unsafe.ARRAY_CHAR_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("intArrayWithValues",
|
||||
Unsafe.ARRAY_INT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_INT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("longArrayWithValues",
|
||||
Unsafe.ARRAY_LONG_BASE_OFFSET,
|
||||
Unsafe.ARRAY_LONG_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("floatArrayWithValues",
|
||||
Unsafe.ARRAY_FLOAT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_FLOAT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("doubleArrayWithValues",
|
||||
Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
|
||||
Unsafe.ARRAY_DOUBLE_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("objectArrayWithValues",
|
||||
Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
|
||||
Unsafe.ARRAY_BOOLEAN_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("booleanArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("byteArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("shortArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("charArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("intArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("longArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("floatArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("doubleArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
NON_STABLE_ARRAY_NAMES.add(new ArrayFieldParams("objectArrayArrayWithValues",
|
||||
Unsafe.ARRAY_OBJECT_BASE_OFFSET,
|
||||
Unsafe.ARRAY_OBJECT_INDEX_SCALE));
|
||||
}
|
||||
|
||||
// Stable array fields names mapped to their base offsets and index scale
|
||||
private static final List<ArrayFieldParams> STABLE_ARRAY_NAMES = new LinkedList<>();
|
||||
|
||||
static {
|
||||
NON_STABLE_ARRAY_NAMES.stream().forEach((entry) -> {
|
||||
String nsFieldName = entry.name;
|
||||
char firstChar = nsFieldName.charAt(0);
|
||||
char newFirstChar = Character.toUpperCase(firstChar);
|
||||
String sFieldName = nsFieldName.replaceFirst("" + firstChar,
|
||||
"" + newFirstChar);
|
||||
sFieldName = "stable" + sFieldName;
|
||||
STABLE_ARRAY_NAMES.add(new ArrayFieldParams(sFieldName, entry.offsetBase, entry.scale));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider(name = "readConstantArrayElementDataProvider")
|
||||
public static Object[][] readConstantArrayElementDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
for (int i : new int[]{0, 1}) {
|
||||
NON_STABLE_ARRAY_NAMES.stream().forEach((entry) -> {
|
||||
String fieldName = entry.name;
|
||||
cfgSet.add(new Object[]{
|
||||
readFieldValue(fieldName),
|
||||
i,
|
||||
null,
|
||||
"array field \"" + fieldName + "\" for index " + i});
|
||||
});
|
||||
STABLE_ARRAY_NAMES.stream().forEach((entry) -> {
|
||||
String fieldName = entry.name;
|
||||
cfgSet.add(new Object[]{
|
||||
readFieldValue(fieldName),
|
||||
i,
|
||||
i == 0 ? getJavaConstant(fieldName) : null,
|
||||
"array field \"" + fieldName + "\" for index " + i});
|
||||
});
|
||||
}
|
||||
Stream<Map.Entry<ResolvedJavaField, JavaConstant>> arraysStream1 = Stream.concat(ARRAYS_MAP.entrySet().stream(),
|
||||
ARRAY_ARRAYS_MAP.entrySet().stream());
|
||||
Stream<Map.Entry<ResolvedJavaField, JavaConstant>> arraysStream2 = Stream.concat(STABLE_ARRAYS_MAP.entrySet().stream(),
|
||||
STABLE_ARRAY_ARRAYS_MAP.entrySet().stream());
|
||||
Stream.concat(arraysStream1, arraysStream2).forEach((array) -> {
|
||||
for (int i : new int[]{-1, 2}) {
|
||||
cfgSet.add(new Object[]{
|
||||
array.getValue(),
|
||||
i,
|
||||
null,
|
||||
"array field \"" + array.getKey() + "\" for index " + i});
|
||||
}
|
||||
});
|
||||
cfgSet.add(new Object[]{null, 0, null, "null"});
|
||||
cfgSet.add(new Object[]{JavaConstant.NULL_POINTER, 0, null, "JavaConstant.NULL_POINTER"});
|
||||
INSTANCE_FIELDS_MAP.values().forEach((constant) -> {
|
||||
cfgSet.add(new Object[]{constant, 0, null, "non-stable non-array field"});
|
||||
});
|
||||
INSTANCE_STABLE_FIELDS_MAP.values().forEach((constant) -> {
|
||||
cfgSet.add(new Object[]{constant, 0, null, "stable non-array field"});
|
||||
});
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "readConstantArrayElementForOffsetDataProvider")
|
||||
public static Object[][] readConstantArrayElementForOffsetDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
// Testing non-stable arrays. Result should be null in all cases
|
||||
for (double i : new double[]{-1, 0, 0.5, 1, 1.5, 2}) {
|
||||
NON_STABLE_ARRAY_NAMES.stream().forEach(entry -> {
|
||||
String fieldName = entry.name;
|
||||
long offset = (long) (entry.offsetBase + i * entry.scale);
|
||||
cfgSet.add(new Object[]{
|
||||
readFieldValue(fieldName),
|
||||
offset,
|
||||
null,
|
||||
"array field \"" + fieldName + "\" for offset " + offset});
|
||||
});
|
||||
}
|
||||
// Testing stable arrays. Result should be null in all cases except "offset = base + 0"
|
||||
for (double i : new double[]{-1, 0.5, 1, 1.5, 2}) {
|
||||
STABLE_ARRAY_NAMES.stream().forEach(entry -> {
|
||||
String fieldName = entry.name;
|
||||
long offset = (long) Math.ceil(entry.offsetBase + i * entry.scale);
|
||||
cfgSet.add(new Object[]{
|
||||
readFieldValue(fieldName),
|
||||
offset,
|
||||
null,
|
||||
"array field \"" + fieldName + "\" for offset " + offset});
|
||||
});
|
||||
}
|
||||
// Testing stable arrays "offset = base + 0". Result should be non-null
|
||||
STABLE_ARRAY_NAMES.stream().forEach(entry -> {
|
||||
String fieldName = entry.name;
|
||||
long offset = (long) entry.offsetBase;
|
||||
cfgSet.add(new Object[]{
|
||||
readFieldValue(fieldName),
|
||||
offset,
|
||||
getJavaConstant(fieldName),
|
||||
"array field \"" + fieldName + "\" for offset " + offset});
|
||||
});
|
||||
// Testing null as array
|
||||
cfgSet.add(new Object[]{null, 0, null, "null"});
|
||||
// Testing JavaConstant.NULL_POINTER as array
|
||||
cfgSet.add(new Object[]{JavaConstant.NULL_POINTER, 0, null, "JavaConstant.NULL_POINTER"});
|
||||
// Testing non-stable non-array fields
|
||||
INSTANCE_FIELDS_MAP.values().forEach((constant) -> {
|
||||
cfgSet.add(new Object[]{constant, 0, null, "non-stable non-array field"});
|
||||
});
|
||||
// Testing stable non-array fields
|
||||
INSTANCE_STABLE_FIELDS_MAP.values().forEach((constant) -> {
|
||||
cfgSet.add(new Object[]{constant, 0, null, "stable non-array field"});
|
||||
});
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
private static JavaConstant readFieldValue(String fieldName) {
|
||||
return CONSTANT_REFLECTION_PROVIDER.readFieldValue(getResolvedJavaField(DummyClass.class, fieldName),
|
||||
DUMMY_CLASS_CONSTANT);
|
||||
}
|
||||
|
||||
private static JavaConstant getJavaConstant(String fieldName) {
|
||||
Class<DummyClass> dummyClass = DummyClass.class;
|
||||
Field arrayField;
|
||||
try {
|
||||
arrayField = dummyClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
throw new Error("Test bug: wrong field name " + ex, ex);
|
||||
} catch (SecurityException ex) {
|
||||
throw new Error("Unexpected error: " + ex, ex);
|
||||
}
|
||||
arrayField.setAccessible(true);
|
||||
Class<?> componentType = arrayField.getType().getComponentType();
|
||||
if (componentType == null) {
|
||||
throw new Error("Test error: field is not an array");
|
||||
}
|
||||
Object value;
|
||||
try {
|
||||
value = arrayField.get(DUMMY_CLASS_INSTANCE);
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
throw new Error("Unexpected error: " + ex, ex);
|
||||
}
|
||||
if (componentType == boolean.class) {
|
||||
return JavaConstant.forBoolean(((boolean[]) value)[0]);
|
||||
}
|
||||
if (componentType == byte.class) {
|
||||
return JavaConstant.forByte(((byte[]) value)[0]);
|
||||
}
|
||||
if (componentType == short.class) {
|
||||
return JavaConstant.forShort(((short[]) value)[0]);
|
||||
}
|
||||
if (componentType == char.class) {
|
||||
return JavaConstant.forChar(((char[]) value)[0]);
|
||||
}
|
||||
if (componentType == int.class) {
|
||||
return JavaConstant.forInt(((int[]) value)[0]);
|
||||
}
|
||||
if (componentType == long.class) {
|
||||
return JavaConstant.forLong(((long[]) value)[0]);
|
||||
}
|
||||
if (componentType == float.class) {
|
||||
return JavaConstant.forFloat(((float[]) value)[0]);
|
||||
}
|
||||
if (componentType == double.class) {
|
||||
return JavaConstant.forDouble(((double[]) value)[0]);
|
||||
}
|
||||
return CONSTANT_REFLECTION_PROVIDER.forObject(((Object[]) value)[0]);
|
||||
}
|
||||
|
||||
private static class ArrayFieldParams {
|
||||
public final String name;
|
||||
public final int offsetBase;
|
||||
public final int scale;
|
||||
|
||||
ArrayFieldParams(String name, int offsetBase, int scale) {
|
||||
this.name = name;
|
||||
this.offsetBase = offsetBase;
|
||||
this.scale = scale;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 jdk.vm.ci.hotspot.test;
|
||||
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.DUMMY_CLASS_CONSTANT;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_STABLE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_FINAL_DEFAULT_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_FINAL_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_STABLE_DEFAULT_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_FINAL_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_STABLE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_STABLE_DEFAULT_FIELDS_MAP;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
public class ReadConstantFieldValueDataProvider {
|
||||
|
||||
@DataProvider(name = "readConstantFieldValueDataProvider")
|
||||
public static Object[][] readConstantFieldValueDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
// Testing static final fields
|
||||
STATIC_FINAL_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), null, field.getValue(), "static final field"});
|
||||
});
|
||||
// Testing static stable fields
|
||||
STATIC_STABLE_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), null, field.getValue(), "static stable field"});
|
||||
});
|
||||
// Testing instance final non-default fields
|
||||
INSTANCE_FINAL_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
field.getValue(),
|
||||
"instance final field"});
|
||||
});
|
||||
// Testing instance final default fields.
|
||||
boolean trustDefFinal = HotSpotJVMCIRuntime.Option.TrustFinalDefaultFields.getBoolean();
|
||||
INSTANCE_FINAL_DEFAULT_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
JavaConstant expected = trustDefFinal ? field.getValue() : null;
|
||||
cfgSet.add(new Object[]{field.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
expected,
|
||||
"instance final default field"});
|
||||
});
|
||||
// Testing instance stable non-default fields
|
||||
INSTANCE_STABLE_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
field.getValue(),
|
||||
"instance stable field"});
|
||||
});
|
||||
// Testing instance stable default fields
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
null,
|
||||
"instance stable default field"});
|
||||
});
|
||||
// Testing regular instance fields
|
||||
INSTANCE_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), DUMMY_CLASS_CONSTANT, null, "instance field"});
|
||||
});
|
||||
// Testing regular static fields
|
||||
STATIC_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), null, null, "static field"});
|
||||
});
|
||||
// Testing static stable fields
|
||||
STATIC_STABLE_DEFAULT_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), null, null, "static stable default field"});
|
||||
});
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "readConstantFieldValueNegativeDataProvider")
|
||||
public static Object[][] readConstantFieldValueNegativeDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
// Testing instance fields with null as receiver
|
||||
INSTANCE_FIELDS_MAP.entrySet().stream().forEach((field) -> {
|
||||
cfgSet.add(new Object[]{field.getKey(), null});
|
||||
});
|
||||
// Testing null as a field argument
|
||||
cfgSet.add(new Object[]{null, null});
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 jdk.vm.ci.hotspot.test;
|
||||
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.ARRAY_ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.CONSTANT_REFLECTION_PROVIDER;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.DUMMY_CLASS_CONSTANT;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.DUMMY_CLASS_INSTANCE;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STABLE_ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STABLE_ARRAY_ARRAYS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_STABLE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.INSTANCE_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_FIELDS_MAP;
|
||||
import static jdk.vm.ci.hotspot.test.TestHelper.STATIC_STABLE_FIELDS_MAP;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
public class ReadStableFieldValueDataProvider {
|
||||
|
||||
@DataProvider(name = "readStableFieldValueDataProvider")
|
||||
public static Object[][] readStableFieldValueDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
for (boolean isDefStab : new boolean[]{true, false}) {
|
||||
// Testing instance non-stable fields
|
||||
INSTANCE_FIELDS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
// Testing static non-stable fields with null as receiver
|
||||
STATIC_FIELDS_MAP.entrySet().stream().forEach((staticField) -> {
|
||||
cfgSet.add(new Object[]{staticField.getKey(),
|
||||
null,
|
||||
isDefStab,
|
||||
staticField.getValue()});
|
||||
});
|
||||
// Testing static non-stable fields with JavaConstant.NULL_POINTER as receiver
|
||||
STATIC_FIELDS_MAP.entrySet().stream().forEach((staticField) -> {
|
||||
cfgSet.add(new Object[]{staticField.getKey(),
|
||||
JavaConstant.NULL_POINTER,
|
||||
isDefStab,
|
||||
staticField.getValue()});
|
||||
});
|
||||
// Testing instance stable fields
|
||||
INSTANCE_STABLE_FIELDS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
// Testing static stable fields with null as receiver
|
||||
STATIC_STABLE_FIELDS_MAP.entrySet().stream().forEach((staticField) -> {
|
||||
cfgSet.add(new Object[]{staticField.getKey(),
|
||||
null,
|
||||
isDefStab,
|
||||
staticField.getValue()});
|
||||
});
|
||||
// Testing static stable fields with JavaConstant.NULL_POINTER as receiver
|
||||
STATIC_STABLE_FIELDS_MAP.entrySet().stream().forEach((staticField) -> {
|
||||
cfgSet.add(new Object[]{staticField.getKey(),
|
||||
JavaConstant.NULL_POINTER,
|
||||
isDefStab,
|
||||
staticField.getValue()});
|
||||
});
|
||||
// Testing instance fields with JavaConstant.NULL_POINTER as receiver
|
||||
INSTANCE_FIELDS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
JavaConstant.NULL_POINTER,
|
||||
isDefStab,
|
||||
null});
|
||||
});
|
||||
// Testing instance fields with an object that does not have the field
|
||||
INSTANCE_FIELDS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
CONSTANT_REFLECTION_PROVIDER.forObject(DUMMY_CLASS_INSTANCE.objectField),
|
||||
isDefStab,
|
||||
null});
|
||||
});
|
||||
}
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "readStableFieldValueArrayDataProvider")
|
||||
public static Object[][] readStableFieldValueArrayDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
for (boolean isDefStab : new boolean[]{true, false}) {
|
||||
// Testing instance non-stable array fields
|
||||
ARRAYS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
TestHelper.ARRAY_DIMENSION,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
// Testing instance stable array fields
|
||||
STABLE_ARRAYS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
TestHelper.ARRAY_DIMENSION,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
// Testing instance non-stable array-of-array fields
|
||||
ARRAY_ARRAYS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
TestHelper.ARRAY_OF_ARRAYS_DIMENSION,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
// Testing instance stable array-of-array fields
|
||||
STABLE_ARRAY_ARRAYS_MAP.entrySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField.getKey(),
|
||||
DUMMY_CLASS_CONSTANT,
|
||||
isDefStab,
|
||||
TestHelper.ARRAY_OF_ARRAYS_DIMENSION,
|
||||
instanceField.getValue()});
|
||||
});
|
||||
}
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "readStableFieldValueNegativeDataProvider")
|
||||
public static Object[][] readStableFieldValueNegativeDataProvider() {
|
||||
LinkedList<Object[]> cfgSet = new LinkedList<>();
|
||||
for (boolean isDefStab : new boolean[]{true, false}) {
|
||||
// Testing instance fields with null as receiver
|
||||
INSTANCE_FIELDS_MAP.keySet().stream().forEach((instanceField) -> {
|
||||
cfgSet.add(new Object[]{instanceField, null, isDefStab});
|
||||
});
|
||||
// Testing null as a field argument
|
||||
cfgSet.add(new Object[]{null, null, isDefStab});
|
||||
}
|
||||
return cfgSet.toArray(new Object[0][0]);
|
||||
}
|
||||
}
|
@ -157,47 +157,6 @@ public class TestHelper {
|
||||
DUMMY_CLASS_INSTANCE.stableObjectField));
|
||||
}
|
||||
|
||||
public static final Map<ResolvedJavaField, JavaConstant> INSTANCE_STABLE_DEFAULT_FIELDS_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultBooleanField"),
|
||||
JavaConstant.forBoolean(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultBooleanField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultByteField"),
|
||||
JavaConstant.forByte(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultByteField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultShortField"),
|
||||
JavaConstant.forShort(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultShortField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultCharField"),
|
||||
JavaConstant.forChar(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultCharField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultIntField"),
|
||||
JavaConstant.forInt(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultIntField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultLongField"),
|
||||
JavaConstant.forLong(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultLongField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultFloatField"),
|
||||
JavaConstant.forFloat(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultFloatField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultDoubleField"),
|
||||
JavaConstant.forDouble(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultDoubleField));
|
||||
INSTANCE_STABLE_DEFAULT_FIELDS_MAP.put(getResolvedJavaField(DummyClass.class,
|
||||
"stableDefaultObjectField"),
|
||||
CONSTANT_REFLECTION_PROVIDER.forObject(
|
||||
DUMMY_CLASS_INSTANCE.stableDefaultObjectField));
|
||||
}
|
||||
|
||||
public static final Map<ResolvedJavaField, JavaConstant> STATIC_FIELDS_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
@ -37,7 +37,6 @@ package jdk.vm.ci.runtime.test;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@ -45,11 +44,9 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
@ -102,35 +99,6 @@ public class TestResolvedJavaField extends FieldUniverse {
|
||||
}
|
||||
}
|
||||
|
||||
static class ReadConstantValueTestConstants {
|
||||
String stringField = "field";
|
||||
final String constantStringField = "constantField";
|
||||
|
||||
static final Object CONST1 = new ReadConstantValueTestConstants();
|
||||
static final Object CONST2 = null;
|
||||
static final Object CONST3 = new String();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readConstantValueTest() throws NoSuchFieldException {
|
||||
ResolvedJavaField field = metaAccess.lookupJavaField(ReadConstantValueTestConstants.class.getDeclaredField("stringField"));
|
||||
List<ConstantValue> receiverConstants = readConstants(ReadConstantValueTestConstants.class);
|
||||
for (ConstantValue receiver : receiverConstants) {
|
||||
JavaConstant value = constantReflection.readConstantFieldValue(field, receiver.value);
|
||||
assertNull(value);
|
||||
}
|
||||
|
||||
ResolvedJavaField constField = metaAccess.lookupJavaField(ReadConstantValueTestConstants.class.getDeclaredField("constantStringField"));
|
||||
for (ConstantValue receiver : receiverConstants) {
|
||||
JavaConstant value = constantReflection.readConstantFieldValue(constField, receiver.value);
|
||||
if (value != null) {
|
||||
Object expected = "constantField";
|
||||
String actual = ((ReadConstantValueTestConstants) receiver.boxed).constantStringField;
|
||||
assertTrue(actual + " != " + expected, actual == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Method findTestMethod(Method apiMethod) {
|
||||
String testName = apiMethod.getName() + "Test";
|
||||
for (Method m : getClass().getDeclaredMethods()) {
|
||||
|
@ -183,7 +183,7 @@ public class TypeUniverse {
|
||||
if (boxed instanceof JavaConstant) {
|
||||
res.add(new ConstantValue(javaField.format("%H.%n"), (JavaConstant) boxed, boxed));
|
||||
} else {
|
||||
JavaConstant value = constantReflection.readConstantFieldValue(javaField, null);
|
||||
JavaConstant value = constantReflection.readFieldValue(javaField, null);
|
||||
if (value != null) {
|
||||
res.add(new ConstantValue(javaField.format("%H.%n"), value, boxed));
|
||||
if (boxed instanceof Object[]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user