Skip to content

Commit

Permalink
Add Class.getDeclaringClass0 substitution
Browse files Browse the repository at this point in the history
  • Loading branch information
pejovica committed Jul 21, 2022
1 parent 012f35f commit ce3d101
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,10 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ
private DynamicHub arrayHub;

/**
* The hub for the enclosing class, or null if no enclosing class.
* <p>
* The value is lazily initialized to break cycles. But it is initialized during static
* analysis, so we do not have to annotate is as an {@link UnknownObjectField}.
*
* @see Class#getEnclosingClass()
* The class that declares this class, as returned by {@code Class.getDeclaringClass0} or an
* exception that happened at image-build time.
*/
private DynamicHub enclosingClass;
private final Object declaringClass;

/**
* The interfaces that this class implements. Either null (no interfaces), a {@link DynamicHub}
Expand Down Expand Up @@ -351,7 +347,7 @@ public void setModule(Module module) {
@Platforms(Platform.HOSTED_ONLY.class)
public DynamicHub(Class<?> hostedJavaClass, String name, HubType hubType, ReferenceType referenceType, Object isLocalClass, Object isAnonymousClass, DynamicHub superType, DynamicHub componentHub,
String sourceFileName, int modifiers, ClassLoader classLoader, boolean isHidden, boolean isRecord, Class<?> nestHost, boolean assertionStatus,
boolean hasDefaultMethods, boolean declaresDefaultMethods, boolean isSealed, String simpleBinaryName) {
boolean hasDefaultMethods, boolean declaresDefaultMethods, boolean isSealed, String simpleBinaryName, Object declaringClass) {
this.hostedJavaClass = hostedJavaClass;
this.name = name;
this.hubType = hubType.getValue();
Expand All @@ -364,6 +360,7 @@ public DynamicHub(Class<?> hostedJavaClass, String name, HubType hubType, Refere
this.modifiers = modifiers;
this.nestHost = nestHost;
this.simpleBinaryName = simpleBinaryName;
this.declaringClass = declaringClass;

this.flags = NumUtil.safeToUByte(makeFlag(IS_PRIMITIVE_FLAG_BIT, hostedJavaClass.isPrimitive()) |
makeFlag(IS_INTERFACE_FLAG_BIT, hostedJavaClass.isInterface()) |
Expand Down Expand Up @@ -422,12 +419,6 @@ public void setArrayHub(DynamicHub arrayHub) {
this.arrayHub = arrayHub;
}

@Platforms(Platform.HOSTED_ONLY.class)
public void setEnclosingClass(DynamicHub enclosingClass) {
assert (this.enclosingClass == null || this.enclosingClass == enclosingClass) && enclosingClass != null;
this.enclosingClass = enclosingClass;
}

@Platforms(Platform.HOSTED_ONLY.class)
public void setInterfacesEncoding(Object interfacesEncoding) {
this.interfacesEncoding = interfacesEncoding;
Expand Down Expand Up @@ -823,25 +814,23 @@ public boolean isLocalOrAnonymousClass() {
return isLocalClass() || isAnonymousClass();
}

@Substitute
private Object getEnclosingClass() {
PredefinedClassesSupport.throwIfUnresolvable(toClass(enclosingClass), getClassLoader0());
return enclosingClass;
}
@KeepOriginal
private native Class<?> getEnclosingClass();

@KeepOriginal
private native Object getDeclaringClass();
private native Class<?> getDeclaringClass();

@Substitute
private Object getDeclaringClass0() {
return getDeclaringClassInternal();
}

private Object getDeclaringClassInternal() {
if (isLocalOrAnonymousClass()) {
private Class<?> getDeclaringClass0() {
if (declaringClass == null) {
return null;
} else if (declaringClass instanceof Class) {
PredefinedClassesSupport.throwIfUnresolvable((Class<?>) declaringClass, getClassLoader0());
return (Class<?>) declaringClass;
} else if (declaringClass instanceof LinkageError) {
throw (LinkageError) declaringClass;
} else {
return getEnclosingClass();
throw VMError.shouldNotReachHere();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ private DynamicHub createHub(AnalysisType type) {
final DynamicHub dynamicHub = new DynamicHub(javaClass, className, computeHubType(type), computeReferenceType(type),
isLocalClass(javaClass), isAnonymousClass(javaClass), superHub, componentHub, sourceFileName,
modifiers, hubClassLoader, isHidden, isRecord, nestHost, assertionStatus, type.hasDefaultMethods(),
type.declaresDefaultMethods(), isSealed, simpleBinaryName);
type.declaresDefaultMethods(), isSealed, simpleBinaryName, getDeclaringClass(javaClass));
ModuleAccess.extractAndSetModule(dynamicHub, javaClass);
return dynamicHub;
}
Expand All @@ -406,11 +406,7 @@ private Object isLocalClass(Class<?> javaClass) {
} catch (InternalError e) {
return e;
} catch (LinkageError e) {
if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
return e;
} else {
return unsupportedMethod(javaClass, "isLocalClass");
}
return handleLinkageError(javaClass, "isLocalClass", e);
}
}

Expand All @@ -424,18 +420,32 @@ private Object isAnonymousClass(Class<?> javaClass) {
} catch (InternalError e) {
return e;
} catch (LinkageError e) {
if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
return e;
} else {
return unsupportedMethod(javaClass, "isAnonymousClass");
return handleLinkageError(javaClass, "isAnonymousClass", e);
}
}

private final Method getDeclaringClass0 = ReflectionUtil.lookupMethod(Class.class, "getDeclaringClass0");

private Object getDeclaringClass(Class<?> javaClass) {
try {
return getDeclaringClass0.invoke(javaClass);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof LinkageError) {
return handleLinkageError(javaClass, getDeclaringClass0.getName(), (LinkageError) e.getCause());
}
throw VMError.shouldNotReachHere(e);
} catch (IllegalAccessException e) {
throw VMError.shouldNotReachHere(e);
}
}

private Object unsupportedMethod(Class<?> javaClass, String methodName) {
private LinkageError handleLinkageError(Class<?> javaClass, String methodName, LinkageError linkageError) {
if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
return linkageError; /* It's rethrown at run time. */
}
String message = "Discovered a type for which " + methodName + " cannot be called: " + javaClass.getTypeName() + ". " +
linkAtBuildTimeSupport.errorMessageFor(javaClass);
throw new UnsupportedFeatureException(message);
throw new UnsupportedFeatureException(message, linkageError);
}

private final Method getSimpleBinaryName0 = ReflectionUtil.lookupMethod(Class.class, "getSimpleBinaryName0");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatures;
import com.oracle.graal.pointsto.heap.ImageHeapScanner;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
Expand All @@ -61,29 +59,25 @@ public class DynamicHubInitializer {
private final BigBang bb;
private final SVMHost hostVM;
private final AnalysisMetaAccess metaAccess;
private final UnsupportedFeatures unsupportedFeatures;
private final ConstantReflectionProvider constantReflection;

private final Map<InterfacesEncodingKey, DynamicHub[]> interfacesEncodings;

private final Field dynamicHubClassInitializationInfoField;
private final Field dynamicHubArrayHubField;
private final Field dynamicHubEnclosingClassField;
private final Field dynamicHubInterfacesEncodingField;
private final Field dynamicHubAnnotationsEnumConstantsReferenceField;

public DynamicHubInitializer(BigBang bb) {
this.bb = bb;
this.metaAccess = bb.getMetaAccess();
this.hostVM = (SVMHost) bb.getHostVM();
this.unsupportedFeatures = bb.getUnsupportedFeatures();
this.constantReflection = bb.getConstantReflectionProvider();

this.interfacesEncodings = new ConcurrentHashMap<>();

dynamicHubClassInitializationInfoField = ReflectionUtil.lookupField(DynamicHub.class, "classInitializationInfo");
dynamicHubArrayHubField = ReflectionUtil.lookupField(DynamicHub.class, "arrayHub");
dynamicHubEnclosingClassField = ReflectionUtil.lookupField(DynamicHub.class, "enclosingClass");
dynamicHubInterfacesEncodingField = ReflectionUtil.lookupField(DynamicHub.class, "interfacesEncoding");
dynamicHubAnnotationsEnumConstantsReferenceField = ReflectionUtil.lookupField(DynamicHub.class, "enumConstantsReference");
}
Expand Down Expand Up @@ -111,16 +105,6 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type)
heapScanner.rescanField(hub.getComponentHub(), dynamicHubArrayHubField);
}

try {
AnalysisType enclosingType = type.getEnclosingType();
if (enclosingType != null) {
hub.setEnclosingClass(hostVM.dynamicHub(enclosingType));
heapScanner.rescanField(hub, dynamicHubEnclosingClassField);
}
} catch (UnsupportedFeatureException ex) {
unsupportedFeatures.addMessage(type.toJavaName(true), null, ex.getMessage(), null, ex);
}

if (hub.getInterfacesEncoding() == null) {
fillInterfaces(type, hub);
heapScanner.rescanField(hub, dynamicHubInterfacesEncodingField);
Expand Down

0 comments on commit ce3d101

Please sign in to comment.