2424 */
2525package com .oracle .svm .core .hub ;
2626
27+ import static com .oracle .svm .configure .config .ConfigurationMemberInfo .ConfigurationMemberAccessibility ;
28+ import static com .oracle .svm .configure .config .ConfigurationMemberInfo .ConfigurationMemberDeclaration ;
2729import static com .oracle .svm .core .MissingRegistrationUtils .throwMissingRegistrationErrors ;
2830import static com .oracle .svm .core .Uninterruptible .CALLED_FROM_UNINTERRUPTIBLE_CODE ;
2931import static com .oracle .svm .core .annotate .TargetElement .CONSTRUCTOR_NAME ;
8486import java .util .function .BiFunction ;
8587import java .util .function .IntFunction ;
8688
87- import com .oracle .svm .core .TrackDynamicAccessEnabled ;
8889import org .graalvm .nativeimage .AnnotationAccess ;
8990import org .graalvm .nativeimage .ImageSingletons ;
9091import org .graalvm .nativeimage .Platform ;
9192import org .graalvm .nativeimage .Platforms ;
9293import org .graalvm .word .WordBase ;
9394
95+ import com .oracle .svm .configure .config .ConfigurationType ;
96+ import com .oracle .svm .configure .config .SignatureUtil ;
9497import com .oracle .svm .core .BuildPhaseProvider .AfterHostedUniverse ;
9598import com .oracle .svm .core .BuildPhaseProvider .CompileQueueFinished ;
9699import com .oracle .svm .core .NeverInline ;
97100import com .oracle .svm .core .NeverInlineTrivial ;
98101import com .oracle .svm .core .RuntimeAssertionsSupport ;
99102import com .oracle .svm .core .SubstrateUtil ;
103+ import com .oracle .svm .core .TrackDynamicAccessEnabled ;
100104import com .oracle .svm .core .Uninterruptible ;
101105import com .oracle .svm .core .annotate .Alias ;
102106import com .oracle .svm .core .annotate .Delete ;
121125import com .oracle .svm .core .jdk .ProtectionDomainSupport ;
122126import com .oracle .svm .core .jdk .Resources ;
123127import com .oracle .svm .core .meta .SharedType ;
128+ import com .oracle .svm .core .metadata .MetadataTracer ;
124129import com .oracle .svm .core .reflect .MissingReflectionRegistrationUtils ;
125130import com .oracle .svm .core .reflect .RuntimeMetadataDecoder ;
126131import com .oracle .svm .core .reflect .RuntimeMetadataDecoder .ConstructorDescriptor ;
@@ -704,6 +709,9 @@ private ReflectionMetadata reflectionMetadata() {
704709 }
705710
706711 private void checkClassFlag (int mask , String methodName ) {
712+ if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
713+ traceClassFlagQuery (mask );
714+ }
707715 if (throwMissingRegistrationErrors () && !(isClassFlagSet (mask ) && getConditions ().satisfied ())) {
708716 MissingReflectionRegistrationUtils .forBulkQuery (DynamicHub .toClass (this ), methodName );
709717 }
@@ -726,6 +734,27 @@ private static boolean isClassFlagSet(int mask, ReflectionMetadata reflectionMet
726734 return reflectionMetadata != null && (reflectionMetadata .classFlags & mask ) != 0 ;
727735 }
728736
737+ private void traceClassFlagQuery (int mask ) {
738+ ConfigurationType type = MetadataTracer .singleton ().traceReflectionType (getName ());
739+ // TODO (GR-64765): We over-approximate member accessibility here because we don't trace
740+ // accesses. Once we trace accesses, it will suffice to register the class for reflection.
741+ switch (mask ) {
742+ case ALL_FIELDS_FLAG -> type .setAllPublicFields (ConfigurationMemberAccessibility .ACCESSED );
743+ case ALL_DECLARED_FIELDS_FLAG -> type .setAllDeclaredFields (ConfigurationMemberAccessibility .ACCESSED );
744+ case ALL_METHODS_FLAG -> type .setAllPublicMethods (ConfigurationMemberAccessibility .ACCESSED );
745+ case ALL_DECLARED_METHODS_FLAG -> type .setAllDeclaredMethods (ConfigurationMemberAccessibility .ACCESSED );
746+ case ALL_CONSTRUCTORS_FLAG -> type .setAllPublicConstructors (ConfigurationMemberAccessibility .ACCESSED );
747+ case ALL_DECLARED_CONSTRUCTORS_FLAG -> type .setAllDeclaredConstructors (ConfigurationMemberAccessibility .ACCESSED );
748+ case ALL_CLASSES_FLAG -> type .setAllPublicClasses ();
749+ case ALL_DECLARED_CLASSES_FLAG -> type .setAllDeclaredClasses ();
750+ case ALL_RECORD_COMPONENTS_FLAG -> type .setAllRecordComponents ();
751+ case ALL_PERMITTED_SUBCLASSES_FLAG -> type .setAllPermittedSubclasses ();
752+ case ALL_NEST_MEMBERS_FLAG -> type .setAllNestMembers ();
753+ case ALL_SIGNERS_FLAG -> type .setAllSigners ();
754+ default -> throw VMError .shouldNotReachHere ("unknown class flag " + mask );
755+ }
756+ }
757+
729758 /** Executed at runtime. */
730759 private static Object initEnumConstantsAtRuntime (Method values ) {
731760 try {
@@ -1282,6 +1311,11 @@ public Field getField(String fieldName) throws NoSuchFieldException, SecurityExc
12821311 private void checkField (String fieldName , Field field , boolean publicOnly ) throws NoSuchFieldException {
12831312 boolean throwMissingErrors = throwMissingRegistrationErrors ();
12841313 Class <?> clazz = DynamicHub .toClass (this );
1314+
1315+ if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1316+ traceFieldLookup (fieldName , field , publicOnly );
1317+ }
1318+
12851319 if (field == null ) {
12861320 if (throwMissingErrors && !allElementsRegistered (publicOnly , ALL_DECLARED_FIELDS_FLAG , ALL_FIELDS_FLAG )) {
12871321 MissingReflectionRegistrationUtils .forField (clazz , fieldName );
@@ -1305,6 +1339,21 @@ private void checkField(String fieldName, Field field, boolean publicOnly) throw
13051339 }
13061340 }
13071341
1342+ private void traceFieldLookup (String fieldName , Field field , boolean publicOnly ) {
1343+ ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration .PRESENT : ConfigurationMemberDeclaration .DECLARED ;
1344+ if (field != null ) {
1345+ // register declaring type and field
1346+ ConfigurationType declaringType = MetadataTracer .singleton ().traceReflectionType (field .getDeclaringClass ().getName ());
1347+ declaringType .addField (fieldName , declaration , false );
1348+ // register receiver type
1349+ MetadataTracer .singleton ().traceReflectionType (getName ());
1350+ } else {
1351+ // register receiver type and negative field query
1352+ ConfigurationType receiverType = MetadataTracer .singleton ().traceReflectionType (getName ());
1353+ receiverType .addField (fieldName , declaration , false );
1354+ }
1355+ }
1356+
13081357 @ Substitute
13091358 private Method getMethod (String methodName , Class <?>... parameterTypes ) throws NoSuchMethodException {
13101359 Objects .requireNonNull (methodName );
@@ -1340,6 +1389,11 @@ private void checkConstructor(Class<?>[] parameterTypes, Constructor<?> construc
13401389 private boolean checkExecutableExists (String methodName , Class <?>[] parameterTypes , Executable method , boolean publicOnly ) {
13411390 boolean throwMissingErrors = throwMissingRegistrationErrors ();
13421391 Class <?> clazz = DynamicHub .toClass (this );
1392+
1393+ if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1394+ traceMethodLookup (methodName , parameterTypes , method , publicOnly );
1395+ }
1396+
13431397 if (method == null ) {
13441398 boolean isConstructor = methodName .equals (CONSTRUCTOR_NAME );
13451399 int allDeclaredFlag = isConstructor ? ALL_DECLARED_CONSTRUCTORS_FLAG : ALL_DECLARED_METHODS_FLAG ;
@@ -1366,6 +1420,34 @@ private boolean checkExecutableExists(String methodName, Class<?>[] parameterTyp
13661420 }
13671421 }
13681422
1423+ private void traceMethodLookup (String methodName , Class <?>[] parameterTypes , Executable method , boolean publicOnly ) {
1424+ ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration .PRESENT : ConfigurationMemberDeclaration .DECLARED ;
1425+ if (method != null ) {
1426+ // register declaring type and method
1427+ ConfigurationType declaringType = MetadataTracer .singleton ().traceReflectionType (method .getDeclaringClass ().getName ());
1428+ declaringType .addMethod (methodName , toInternalSignature (parameterTypes ), declaration );
1429+ // register receiver type
1430+ MetadataTracer .singleton ().traceReflectionType (getName ());
1431+ } else {
1432+ // register receiver type and negative method query
1433+ ConfigurationType receiverType = MetadataTracer .singleton ().traceReflectionType (getName ());
1434+ receiverType .addMethod (methodName , toInternalSignature (parameterTypes ), declaration , ConfigurationMemberAccessibility .QUERIED );
1435+ }
1436+ }
1437+
1438+ private static String toInternalSignature (Class <?>[] classes ) {
1439+ List <String > names ;
1440+ if (classes == null ) {
1441+ names = List .of ();
1442+ } else {
1443+ names = new ArrayList <>(classes .length );
1444+ for (Class <?> aClass : classes ) {
1445+ names .add (aClass .getName ());
1446+ }
1447+ }
1448+ return SignatureUtil .toInternalSignature (names );
1449+ }
1450+
13691451 private boolean allElementsRegistered (boolean publicOnly , int allDeclaredElementsFlag , int allPublicElementsFlag ) {
13701452 return isClassFlagSet (allDeclaredElementsFlag ) || (publicOnly && isClassFlagSet (allPublicElementsFlag ));
13711453 }
@@ -1882,6 +1964,8 @@ public DynamicHub arrayType() {
18821964 }
18831965 if (companion .arrayHub == null ) {
18841966 MissingReflectionRegistrationUtils .forClass (getTypeName () + "[]" );
1967+ } else if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1968+ MetadataTracer .singleton ().traceReflectionType (companion .arrayHub .getTypeName ());
18851969 }
18861970 return companion .arrayHub ;
18871971 }
0 commit comments