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,30 @@ 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+ if (type == null ) {
740+ return ;
741+ }
742+ // TODO (GR-64765): We over-approximate member accessibility here because we don't trace
743+ // accesses. Once we trace accesses, it will suffice to register the class for reflection.
744+ switch (mask ) {
745+ case ALL_FIELDS_FLAG -> type .setAllPublicFields (ConfigurationMemberAccessibility .ACCESSED );
746+ case ALL_DECLARED_FIELDS_FLAG -> type .setAllDeclaredFields (ConfigurationMemberAccessibility .ACCESSED );
747+ case ALL_METHODS_FLAG -> type .setAllPublicMethods (ConfigurationMemberAccessibility .ACCESSED );
748+ case ALL_DECLARED_METHODS_FLAG -> type .setAllDeclaredMethods (ConfigurationMemberAccessibility .ACCESSED );
749+ case ALL_CONSTRUCTORS_FLAG -> type .setAllPublicConstructors (ConfigurationMemberAccessibility .ACCESSED );
750+ case ALL_DECLARED_CONSTRUCTORS_FLAG -> type .setAllDeclaredConstructors (ConfigurationMemberAccessibility .ACCESSED );
751+ case ALL_CLASSES_FLAG -> type .setAllPublicClasses ();
752+ case ALL_DECLARED_CLASSES_FLAG -> type .setAllDeclaredClasses ();
753+ case ALL_RECORD_COMPONENTS_FLAG -> type .setAllRecordComponents ();
754+ case ALL_PERMITTED_SUBCLASSES_FLAG -> type .setAllPermittedSubclasses ();
755+ case ALL_NEST_MEMBERS_FLAG -> type .setAllNestMembers ();
756+ case ALL_SIGNERS_FLAG -> type .setAllSigners ();
757+ default -> throw VMError .shouldNotReachHere ("unknown class flag " + mask );
758+ }
759+ }
760+
729761 /** Executed at runtime. */
730762 private static Object initEnumConstantsAtRuntime (Method values ) {
731763 try {
@@ -1282,6 +1314,11 @@ public Field getField(String fieldName) throws NoSuchFieldException, SecurityExc
12821314 private void checkField (String fieldName , Field field , boolean publicOnly ) throws NoSuchFieldException {
12831315 boolean throwMissingErrors = throwMissingRegistrationErrors ();
12841316 Class <?> clazz = DynamicHub .toClass (this );
1317+
1318+ if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1319+ traceFieldLookup (fieldName , field , publicOnly );
1320+ }
1321+
12851322 if (field == null ) {
12861323 if (throwMissingErrors && !allElementsRegistered (publicOnly , ALL_DECLARED_FIELDS_FLAG , ALL_FIELDS_FLAG )) {
12871324 MissingReflectionRegistrationUtils .forField (clazz , fieldName );
@@ -1305,6 +1342,25 @@ private void checkField(String fieldName, Field field, boolean publicOnly) throw
13051342 }
13061343 }
13071344
1345+ private void traceFieldLookup (String fieldName , Field field , boolean publicOnly ) {
1346+ ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration .PRESENT : ConfigurationMemberDeclaration .DECLARED ;
1347+ if (field != null ) {
1348+ // register declaring type and field
1349+ ConfigurationType declaringType = MetadataTracer .singleton ().traceReflectionType (field .getDeclaringClass ().getName ());
1350+ if (declaringType != null ) {
1351+ declaringType .addField (fieldName , declaration , false );
1352+ }
1353+ // register receiver type
1354+ MetadataTracer .singleton ().traceReflectionType (getName ());
1355+ } else {
1356+ // register receiver type and negative field query
1357+ ConfigurationType receiverType = MetadataTracer .singleton ().traceReflectionType (getName ());
1358+ if (receiverType != null ) {
1359+ receiverType .addField (fieldName , declaration , false );
1360+ }
1361+ }
1362+ }
1363+
13081364 @ Substitute
13091365 private Method getMethod (String methodName , Class <?>... parameterTypes ) throws NoSuchMethodException {
13101366 Objects .requireNonNull (methodName );
@@ -1340,6 +1396,11 @@ private void checkConstructor(Class<?>[] parameterTypes, Constructor<?> construc
13401396 private boolean checkExecutableExists (String methodName , Class <?>[] parameterTypes , Executable method , boolean publicOnly ) {
13411397 boolean throwMissingErrors = throwMissingRegistrationErrors ();
13421398 Class <?> clazz = DynamicHub .toClass (this );
1399+
1400+ if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1401+ traceMethodLookup (methodName , parameterTypes , method , publicOnly );
1402+ }
1403+
13431404 if (method == null ) {
13441405 boolean isConstructor = methodName .equals (CONSTRUCTOR_NAME );
13451406 int allDeclaredFlag = isConstructor ? ALL_DECLARED_CONSTRUCTORS_FLAG : ALL_DECLARED_METHODS_FLAG ;
@@ -1366,6 +1427,38 @@ private boolean checkExecutableExists(String methodName, Class<?>[] parameterTyp
13661427 }
13671428 }
13681429
1430+ private void traceMethodLookup (String methodName , Class <?>[] parameterTypes , Executable method , boolean publicOnly ) {
1431+ ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration .PRESENT : ConfigurationMemberDeclaration .DECLARED ;
1432+ if (method != null ) {
1433+ // register declaring type and method
1434+ ConfigurationType declaringType = MetadataTracer .singleton ().traceReflectionType (method .getDeclaringClass ().getName ());
1435+ if (declaringType != null ) {
1436+ declaringType .addMethod (methodName , toInternalSignature (parameterTypes ), declaration );
1437+ }
1438+ // register receiver type
1439+ MetadataTracer .singleton ().traceReflectionType (getName ());
1440+ } else {
1441+ // register receiver type and negative method query
1442+ ConfigurationType receiverType = MetadataTracer .singleton ().traceReflectionType (getName ());
1443+ if (receiverType != null ) {
1444+ receiverType .addMethod (methodName , toInternalSignature (parameterTypes ), declaration , ConfigurationMemberAccessibility .QUERIED );
1445+ }
1446+ }
1447+ }
1448+
1449+ private static String toInternalSignature (Class <?>[] classes ) {
1450+ List <String > names ;
1451+ if (classes == null ) {
1452+ names = List .of ();
1453+ } else {
1454+ names = new ArrayList <>(classes .length );
1455+ for (Class <?> aClass : classes ) {
1456+ names .add (aClass .getName ());
1457+ }
1458+ }
1459+ return SignatureUtil .toInternalSignature (names );
1460+ }
1461+
13691462 private boolean allElementsRegistered (boolean publicOnly , int allDeclaredElementsFlag , int allPublicElementsFlag ) {
13701463 return isClassFlagSet (allDeclaredElementsFlag ) || (publicOnly && isClassFlagSet (allPublicElementsFlag ));
13711464 }
@@ -1882,6 +1975,8 @@ public DynamicHub arrayType() {
18821975 }
18831976 if (companion .arrayHub == null ) {
18841977 MissingReflectionRegistrationUtils .forClass (getTypeName () + "[]" );
1978+ } else if (MetadataTracer .Options .MetadataTracingSupport .getValue () && MetadataTracer .singleton ().enabled ()) {
1979+ MetadataTracer .singleton ().traceReflectionType (companion .arrayHub .getTypeName ());
18851980 }
18861981 return companion .arrayHub ;
18871982 }
0 commit comments