use of jdk.vm.ci.meta.ResolvedJavaField in project graal by oracle.
the class HotSpotResolvedJavaFieldTest method testEquivalenceForInternalFields.
/**
* Tests that {@code HotSpotResolvedObjectType#createField(String, JavaType, long, int)} always
* returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an internal
* field.
*
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@Test
public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for (Class<?> c : classesWithInternalFields) {
HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(c);
for (ResolvedJavaField field : type.getInstanceFields(false)) {
if (field.isInternal()) {
HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
int index = indexField.getInt(expected);
ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.offset(), expected.getModifiers(), index);
Assert.assertEquals(expected, actual);
}
}
}
}
use of jdk.vm.ci.meta.ResolvedJavaField in project graal by oracle.
the class AnnotationSubstitutionProcessor method handleSubstitutionClass.
private void handleSubstitutionClass(Class<?> annotatedClass, Class<?> originalClass) {
// Not sure what happens if the target class is in a hierarchy - so prohibit that for now.
guarantee(annotatedClass.isInterface() == originalClass.isInterface(), "if original is interface, target must also be interface: %s", annotatedClass);
guarantee(originalClass.getSuperclass() == Object.class || originalClass.isInterface(), "target class must inherit directly from Object: %s", originalClass);
ResolvedJavaType original = metaAccess.lookupJavaType(originalClass);
ResolvedJavaType annotated = metaAccess.lookupJavaType(annotatedClass);
for (int i = 0; i < ARRAY_DIMENSIONS; i++) {
ResolvedJavaType substitution = new SubstitutionType(original, annotated);
register(typeSubstitutions, annotated, original, substitution);
original = original.getArrayClass();
annotated = annotated.getArrayClass();
}
for (Method m : annotatedClass.getDeclaredMethods()) {
handleAnnotatedMethodInSubstitutionClass(m, originalClass);
}
for (Constructor<?> c : annotatedClass.getDeclaredConstructors()) {
handleAnnotatedMethodInSubstitutionClass(c, originalClass);
}
for (Method m : originalClass.getDeclaredMethods()) {
handleOriginalMethodInSubstitutionClass(m);
}
for (Constructor<?> c : originalClass.getDeclaredConstructors()) {
handleOriginalMethodInSubstitutionClass(c);
}
for (Field f : originalClass.getDeclaredFields()) {
registerAsDeleted(null, metaAccess.lookupJavaField(f), SUBSTITUTION_DELETE);
}
for (Field f : annotatedClass.getDeclaredFields()) {
ResolvedJavaField field = metaAccess.lookupJavaField(f);
ResolvedJavaField alias = fieldValueRecomputation(annotatedClass, field, field, f);
if (!alias.equals(field)) {
register(fieldSubstitutions, field, null, alias);
}
}
}
use of jdk.vm.ci.meta.ResolvedJavaField in project graal by oracle.
the class AnnotationSubstitutionProcessor method processComputedValueFields.
/**
* Eagerly register all target fields of recomputed value fields as unsafe accessed.
*/
public void processComputedValueFields(BigBang bb) {
for (ResolvedJavaField field : fieldSubstitutions.values()) {
if (field instanceof ComputedValue) {
ComputedValue cvField = (ComputedValue) field;
switch(cvField.getRecomputeValueKind()) {
case FieldOffset:
AnalysisField targetField = bb.getMetaAccess().lookupJavaField(cvField.getTargetField());
targetField.registerAsAccessed();
targetField.registerAsUnsafeAccessed();
break;
}
}
}
}
use of jdk.vm.ci.meta.ResolvedJavaField in project graal by oracle.
the class AnnotationSubstitutionProcessor method handleFieldInAliasClass.
private void handleFieldInAliasClass(Field annotatedField, Class<?> originalClass) {
if (!NativeImageGenerator.includedIn(ImageSingletons.lookup(Platform.class), lookupAnnotation(annotatedField, Platforms.class))) {
return;
}
ResolvedJavaField annotated = metaAccess.lookupJavaField(annotatedField);
Delete deleteAnnotation = lookupAnnotation(annotatedField, Delete.class);
Alias aliasAnnotation = lookupAnnotation(annotatedField, Alias.class);
Inject injectAnnotation = lookupAnnotation(annotatedField, Inject.class);
int numAnnotations = (deleteAnnotation != null ? 1 : 0) + (aliasAnnotation != null ? 1 : 0) + (injectAnnotation != null ? 1 : 0);
if (numAnnotations == 0) {
guarantee(annotatedField.getName().equals("$assertionsDisabled"), "One of @Delete, @Alias, or @Inject must be used: %s", annotatedField);
/*
* The field $assertionsDisabled can be present in the original class, but does not have
* to. We treat it like an optional @Alias fields without field value recomputation.
*/
ResolvedJavaField original = findOriginalField(annotatedField, originalClass, true);
if (original != null) {
register(fieldSubstitutions, annotated, null, original);
}
return;
}
guarantee(numAnnotations == 1, "Only one of @Delete, @Alias, or @Inject can be used: %s", annotatedField);
if (injectAnnotation != null) {
guarantee(!annotated.isStatic(), "@Inject field must not be static: %s", annotated);
ResolvedJavaField injected = fieldValueRecomputation(originalClass, annotated, annotated, annotatedField);
register(fieldSubstitutions, annotated, null, injected);
ResolvedJavaType original = metaAccess.lookupJavaType(originalClass);
InjectedFieldsType substitution;
if (typeSubstitutions.get(original) instanceof InjectedFieldsType) {
substitution = (InjectedFieldsType) typeSubstitutions.get(original);
register(typeSubstitutions, annotated.getDeclaringClass(), original, substitution);
} else {
substitution = new InjectedFieldsType(original);
register(typeSubstitutions, annotated.getDeclaringClass(), original, substitution);
}
substitution.addInjectedField(injected);
} else {
ResolvedJavaField original = findOriginalField(annotatedField, originalClass, false);
if (original == null) {
return;
}
guarantee(annotated.isStatic() == original.isStatic(), "Static modifier mismatch: %s, %s", annotated, original);
guarantee(annotated.getJavaKind() == original.getJavaKind(), "Type mismatch: %s, %s", annotated, original);
if (deleteAnnotation != null) {
registerAsDeleted(annotated, original, deleteAnnotation);
} else {
ResolvedJavaField alias = fieldValueRecomputation(originalClass, original, annotated, annotatedField);
register(fieldSubstitutions, annotated, original, alias);
}
}
}
use of jdk.vm.ci.meta.ResolvedJavaField in project graal by oracle.
the class UnsafeAutomaticSubstitutionProcessor method tryAutomaticRecomputation.
/**
* Try to register the automatic substitution for a field. Bail if the field was deleted or
* another substitution is detected.
*/
private boolean tryAutomaticRecomputation(ResolvedJavaField field, Kind kind, Supplier<ComputedValueField> substitutionSupplier) {
if (annotationSubstitutions.isDeleted(field)) {
String conflictingSubstitution = "The field " + field.format("%H.%n") + " is marked as deleted. ";
reportConflictingSubstitution(field, kind, conflictingSubstitution);
return false;
} else {
Optional<ResolvedJavaField> annotationSubstitution = annotationSubstitutions.findSubstitution(field);
if (annotationSubstitution.isPresent()) {
/* An annotation substitutions detected. */
ResolvedJavaField substitutionField = annotationSubstitution.get();
if (substitutionField instanceof ComputedValueField) {
ComputedValueField computedSubstitutionField = (ComputedValueField) substitutionField;
if (computedSubstitutionField.getRecomputeValueKind().equals(kind)) {
reportUnnecessarySubstitution(substitutionField, computedSubstitutionField);
return false;
} else if (computedSubstitutionField.getRecomputeValueKind().equals(Kind.None)) {
/*
* This is essentially and @Alias field. An @Alias for a field with an
* automatic recomputed value is allowed but the alias needs to be
* overwritten otherwise would read the value from the original field. To do
* this a new recomputed value field is registered in the automatic
* substitution processor, which follows the annotation substitution
* processor in the substitutions chain. Thus, every time the substitutions
* chain is queried for the original field, e.g., in
* AnalysisUniverse.lookupAllowUnresolved(JavaField), the alias field is
* forwarded to the the automatic substitution.
*/
addSubstitutionField(computedSubstitutionField, substitutionSupplier.get());
reportOvewrittenSubstitution(substitutionField, kind, computedSubstitutionField.getAnnotated(), computedSubstitutionField.getRecomputeValueKind());
return true;
} else {
String conflictingSubstitution = "Detected RecomputeFieldValue." + computedSubstitutionField.getRecomputeValueKind() + " " + computedSubstitutionField.getAnnotated().format("%H.%n") + " substitution field. ";
reportConflictingSubstitution(substitutionField, kind, conflictingSubstitution);
return false;
}
} else {
String conflictingSubstitution = "Detected " + substitutionField.format("%H.%n") + " substitution field. ";
reportConflictingSubstitution(substitutionField, kind, conflictingSubstitution);
return false;
}
} else {
/* No other substitutions detected. */
addSubstitutionField(field, substitutionSupplier.get());
return true;
}
}
}
Aggregations