package com.oracle.svm.hosted.meta;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.svm.core.meta.ReadableJavaField;
import com.oracle.svm.core.meta.SharedField;
import com.oracle.svm.core.meta.SubstrateObjectConstant;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaTypeProfile;
public class HostedField implements ReadableJavaField, OriginalFieldProvider, SharedField, Comparable<HostedField> {
private final HostedUniverse universe;
private final HostedMetaAccess metaAccess;
public final AnalysisField wrapped;
private final HostedType holder;
private final HostedType type;
protected int location;
private final JavaTypeProfile typeProfile;
private static final int LOC_UNMATERIALIZED_STATIC_CONSTANT = -10;
public HostedField(HostedUniverse universe, HostedMetaAccess metaAccess, AnalysisField wrapped, HostedType holder, HostedType type, JavaTypeProfile typeProfile) {
this.universe = universe;
this.metaAccess = metaAccess;
this.wrapped = wrapped;
this.holder = holder;
this.type = type;
this.typeProfile = typeProfile;
this.location = LOC_UNINITIALIZED;
}
public JavaTypeProfile getFieldTypeProfile() {
return typeProfile;
}
protected void setLocation(int location) {
assert this.location == LOC_UNINITIALIZED;
assert location >= 0;
this.location = location;
}
protected void setUnmaterializedStaticConstant() {
assert this.location == LOC_UNINITIALIZED && isStatic();
this.location = LOC_UNMATERIALIZED_STATIC_CONSTANT;
}
public JavaConstant getConstantValue() {
if (isStatic() && allowConstantFolding()) {
return readValue(null);
} else {
return null;
}
}
public boolean hasLocation() {
return location >= 0;
}
@Override
public int getLocation() {
return location;
}
@Override
public boolean isAccessed() {
return wrapped.isAccessed();
}
public boolean isInImageHeap() {
return wrapped.isInImageHeap();
}
@Override
public boolean isWritten() {
return wrapped.isWritten();
}
@Override
public String getName() {
return wrapped.getName();
}
@Override
public HostedType getType() {
return type;
}
@Override
public int getModifiers() {
return wrapped.getModifiers();
}
@Override
public int getOffset() {
return getLocation();
}
@Override
public int hashCode() {
return wrapped.hashCode();
}
@Override
public JavaConstant readValue(JavaConstant receiver) {
JavaConstant wrappedReceiver;
if (receiver != null && SubstrateObjectConstant.asObject(receiver) instanceof Class) {
wrappedReceiver = SubstrateObjectConstant.forObject(metaAccess.lookupJavaType((Class<?>) SubstrateObjectConstant.asObject(receiver)).getHub());
} else {
wrappedReceiver = receiver;
}
return universe.lookup(universe.getConstantReflectionProvider().readFieldValue(wrapped, wrappedReceiver));
}
@Override
public boolean allowConstantFolding() {
if (location == LOC_UNMATERIALIZED_STATIC_CONSTANT) {
return true;
} else if (!wrapped.isWritten()) {
return true;
} else if (Modifier.isFinal(getModifiers()) && !Modifier.isStatic(getModifiers())) {
return true;
}
return false;
}
@Override
public boolean injectFinalForRuntimeCompilation() {
return ReadableJavaField.injectFinalForRuntimeCompilation(wrapped);
}
public JavaConstant readStorageValue(JavaConstant receiver) {
JavaConstant result = readValue(receiver);
assert result.getJavaKind() == getType().getStorageKind() : this;
return result;
}
@Override
public HostedType getDeclaringClass() {
return holder;
}
@Override
public boolean isInternal() {
return wrapped.isInternal();
}
@Override
public boolean isSynthetic() {
return wrapped.isSynthetic();
}
@Override
public Annotation[] getAnnotations() {
return wrapped.getAnnotations();
}
@Override
public Annotation[] getDeclaredAnnotations() {
return wrapped.getDeclaredAnnotations();
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return wrapped.getAnnotation(annotationClass);
}
@Override
public String toString() {
return "HostedField<" + format("%h.%n") + " location: " + location + " " + wrapped.toString() + ">";
}
@Override
public JavaKind getStorageKind() {
return getType().getStorageKind();
}
@Override
public int compareTo(HostedField other) {
int result = other.getJavaKind().ordinal() - this.getJavaKind().ordinal();
return result;
}
@Override
public Field getJavaField() {
return OriginalFieldProvider.getJavaField(getDeclaringClass().universe.getSnippetReflection(), wrapped);
}
}