diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index b9d1f9da589d..3a58b13efd97 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -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. - *

- * 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} @@ -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(); @@ -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()) | @@ -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; @@ -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(); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index aacb4e4b46ce..1d3d76935767 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -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; } @@ -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); } } @@ -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"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java index fd03b8f4021c..0f902c93fb81 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java @@ -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; @@ -61,14 +59,12 @@ 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 interfacesEncodings; private final Field dynamicHubClassInitializationInfoField; private final Field dynamicHubArrayHubField; - private final Field dynamicHubEnclosingClassField; private final Field dynamicHubInterfacesEncodingField; private final Field dynamicHubAnnotationsEnumConstantsReferenceField; @@ -76,14 +72,12 @@ 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"); } @@ -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);