package st.gravel.support.jvm.runtime;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import st.gravel.support.compiler.ast.InstVarMapping;
public abstract class FieldAccessCallSite extends BaseCallSite {
protected FieldAccessCallSite(Lookup lookup, MethodType type,
String selector) {
super(lookup, type, selector);
}
@Override
protected void resetCache() {
}
@Override
protected void addTargetToCache(Object receiver) {
setTarget(findFieldAccess(receiver.getClass()));
}
protected MethodHandle findFieldAccess(Class receiverClass) {
MethodHandle access = findAccessOrNil(receiverClass);
if (access == null)
throw new RuntimeException("Access not found");
return access.asType(type);
}
protected MethodHandle findAccessOrNil(Class receiverClass) {
// Try to find the highest defined access
MethodHandle found = null;
Class cl = receiverClass;
while (cl != null) {
MethodHandle sFound = localFindAccessOrNil(cl);
if (sFound != null)
found = sFound;
cl = cl.getSuperclass();
}
return found;
}
protected MethodHandle localFindAccessOrNil(Class receiverClass) {
if (receiverClass == null)
return null;
try {
return findAccess(receiverClass);
} catch (NoSuchFieldException e) {
return null;
} catch (IllegalAccessException e) {
return null;
}
}
protected abstract MethodHandle findAccess(Class receiverClass) throws NoSuchFieldException, IllegalAccessException;
protected Class<?> getFieldType(Class receiverClass) throws NoSuchFieldException {
return receiverClass
.getField(selector).getType();
}
}