3535import java .util .Optional ;
3636import java .util .concurrent .ConcurrentHashMap ;
3737
38+ import org .graalvm .nativeimage .c .function .CFunctionPointer ;
39+
40+ import com .oracle .graal .pointsto .BigBang ;
3841import com .oracle .graal .pointsto .ObjectScanner .OtherReason ;
3942import com .oracle .graal .pointsto .constraints .UnsupportedFeatureException ;
4043import com .oracle .graal .pointsto .constraints .UnsupportedFeatures ;
4144import com .oracle .graal .pointsto .heap .ImageHeapScanner ;
4245import com .oracle .graal .pointsto .meta .AnalysisField ;
4346import com .oracle .graal .pointsto .meta .AnalysisMetaAccess ;
47+ import com .oracle .graal .pointsto .meta .AnalysisMethod ;
4448import com .oracle .graal .pointsto .meta .AnalysisType ;
4549import com .oracle .svm .core .BuildPhaseProvider ;
50+ import com .oracle .svm .core .classinitialization .ClassInitializationInfo ;
4651import com .oracle .svm .core .hub .AnnotatedSuperInfo ;
4752import com .oracle .svm .core .hub .DynamicHub ;
4853import com .oracle .svm .core .hub .GenericInfo ;
54+ import com .oracle .svm .core .meta .MethodPointer ;
4955import com .oracle .svm .core .meta .SubstrateObjectConstant ;
5056import com .oracle .svm .core .util .VMError ;
57+ import com .oracle .svm .hosted .ExceptionSynthesizer ;
5158import com .oracle .svm .hosted .SVMHost ;
59+ import com .oracle .svm .hosted .code .CompilationInfoSupport ;
5260import com .oracle .svm .util .ReflectionUtil ;
5361
5462import jdk .vm .ci .meta .ConstantReflectionProvider ;
5765
5866public class DynamicHubInitializer {
5967
68+ private final BigBang bb ;
6069 private final SVMHost hostVM ;
6170 private final AnalysisMetaAccess metaAccess ;
6271 private final UnsupportedFeatures unsupportedFeatures ;
@@ -66,6 +75,7 @@ public class DynamicHubInitializer {
6675 private final Map <AnnotatedInterfacesEncodingKey , AnnotatedType []> annotatedInterfacesMap ;
6776 private final Map <InterfacesEncodingKey , DynamicHub []> interfacesEncodings ;
6877
78+ private final Field dynamicHubClassInitializationInfoField ;
6979 private final Field dynamicHubArrayHubField ;
7080 private final Field dynamicHubEnclosingClassField ;
7181 private final Field dynamicHubInterfacesEncodingField ;
@@ -74,16 +84,18 @@ public class DynamicHubInitializer {
7484 private final Field dynamicHubAnnotatedSuperInfoField ;
7585 private final Field dynamicHubGenericInfoField ;
7686
77- public DynamicHubInitializer (AnalysisMetaAccess metaAccess , UnsupportedFeatures unsupportedFeatures , ConstantReflectionProvider constantReflection ) {
78- this .metaAccess = metaAccess ;
79- this .hostVM = (SVMHost ) metaAccess .getUniverse ().hostVM ();
80- this .unsupportedFeatures = unsupportedFeatures ;
81- this .constantReflection = constantReflection ;
87+ public DynamicHubInitializer (BigBang bb ) {
88+ this .bb = bb ;
89+ this .metaAccess = bb .getMetaAccess ();
90+ this .hostVM = (SVMHost ) bb .getHostVM ();
91+ this .unsupportedFeatures = bb .getUnsupportedFeatures ();
92+ this .constantReflection = bb .getConstantReflectionProvider ();
8293
8394 this .genericInterfacesMap = new ConcurrentHashMap <>();
8495 this .annotatedInterfacesMap = new ConcurrentHashMap <>();
8596 this .interfacesEncodings = new ConcurrentHashMap <>();
8697
98+ dynamicHubClassInitializationInfoField = ReflectionUtil .lookupField (DynamicHub .class , "classInitializationInfo" );
8799 dynamicHubArrayHubField = ReflectionUtil .lookupField (DynamicHub .class , "arrayHub" );
88100 dynamicHubEnclosingClassField = ReflectionUtil .lookupField (DynamicHub .class , "enclosingClass" );
89101 dynamicHubInterfacesEncodingField = ReflectionUtil .lookupField (DynamicHub .class , "interfacesEncoding" );
@@ -103,6 +115,9 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type)
103115 heapScanner .rescanObject (javaClass .getPackage ());
104116
105117 DynamicHub hub = hostVM .dynamicHub (type );
118+ if (hub .getClassInitializationInfo () == null ) {
119+ buildClassInitializationInfo (heapScanner , type , hub );
120+ }
106121 if (hub .getGenericInfo () == null ) {
107122 fillGenericInfo (heapScanner , type , hub );
108123 }
@@ -205,6 +220,60 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type)
205220 heapScanner .rescanObject (hub , OtherReason .HUB );
206221 }
207222
223+ private void buildClassInitializationInfo (ImageHeapScanner heapScanner , AnalysisType type , DynamicHub hub ) {
224+ ClassInitializationInfo info ;
225+ if (hostVM .getClassInitializationSupport ().shouldInitializeAtRuntime (type )) {
226+ info = buildRuntimeInitializationInfo (type );
227+ } else {
228+ assert type .isInitialized ();
229+ info = type .getClassInitializer () == null ? ClassInitializationInfo .NO_INITIALIZER_INFO_SINGLETON : ClassInitializationInfo .INITIALIZED_INFO_SINGLETON ;
230+ }
231+ hub .setClassInitializationInfo (info );
232+ heapScanner .rescanField (hub , dynamicHubClassInitializationInfoField );
233+ }
234+
235+ private ClassInitializationInfo buildRuntimeInitializationInfo (AnalysisType type ) {
236+ assert !type .isInitialized ();
237+ try {
238+ /*
239+ * Check if there are any linking errors. This method throws an error even if linking
240+ * already failed in a previous attempt.
241+ */
242+ type .link ();
243+
244+ } catch (VerifyError e ) {
245+ /* Synthesize a VerifyError to be thrown at run time. */
246+ AnalysisMethod throwVerifyError = metaAccess .lookupJavaMethod (ExceptionSynthesizer .throwExceptionMethod (VerifyError .class ));
247+ registerAsCompiled (throwVerifyError );
248+ return new ClassInitializationInfo (new MethodPointer (throwVerifyError ));
249+ } catch (Throwable t ) {
250+ /*
251+ * All other linking errors will be reported as NoClassDefFoundError when initialization
252+ * is attempted at run time.
253+ */
254+ return ClassInitializationInfo .FAILED_INFO_SINGLETON ;
255+ }
256+
257+ /*
258+ * Now we now that there are no linking errors, we can register the class initialization
259+ * information.
260+ */
261+ assert type .isLinked ();
262+ CFunctionPointer classInitializerFunction = null ;
263+ AnalysisMethod classInitializer = type .getClassInitializer ();
264+ if (classInitializer != null ) {
265+ assert classInitializer .getCode () != null ;
266+ registerAsCompiled (classInitializer );
267+ classInitializerFunction = new MethodPointer (classInitializer );
268+ }
269+ return new ClassInitializationInfo (classInitializerFunction );
270+ }
271+
272+ private void registerAsCompiled (AnalysisMethod aMethod ) {
273+ bb .addRootMethod (aMethod ).registerAsImplementationInvoked ();
274+ CompilationInfoSupport .singleton ().registerForcedCompilation (aMethod );
275+ }
276+
208277 static class GenericInterfacesEncodingKey {
209278 final Type [] interfaces ;
210279
0 commit comments