8686import com .oracle .graal .pointsto .meta .AnalysisMethod ;
8787import com .oracle .graal .pointsto .meta .AnalysisType ;
8888import com .oracle .graal .pointsto .meta .AnalysisUniverse ;
89- import com .oracle .svm .core .FutureDefaultsOptions ;
9089import com .oracle .svm .core .MissingRegistrationUtils ;
9190import com .oracle .svm .core .configure .ConditionalRuntimeValue ;
9291import com .oracle .svm .core .configure .RuntimeDynamicAccessMetadata ;
@@ -149,12 +148,15 @@ public class ReflectionDataBuilder extends ConditionalConfigurationRegistry impl
149148 */
150149 private final Map <Class <?>, Set <Class <?>>> innerClasses = new ConcurrentHashMap <>();
151150 private final Map <Class <?>, Integer > enabledQueriesFlags = new ConcurrentHashMap <>();
152- private final Map <AnalysisType , Map <AnalysisField , ConditionalRuntimeValue <Field >>> registeredFields = new ConcurrentHashMap <>();
151+ private final Map <AnalysisType , Map <AnalysisField , RegisteredMemberData <Field >>> registeredFields = new ConcurrentHashMap <>();
153152 private final Set <AnalysisField > hidingFields = ConcurrentHashMap .newKeySet ();
154- private final Map <AnalysisType , Map <AnalysisMethod , ConditionalRuntimeValue <Executable >>> registeredMethods = new ConcurrentHashMap <>();
153+ private final Map <AnalysisType , Map <AnalysisMethod , RegisteredMemberData <Executable >>> registeredMethods = new ConcurrentHashMap <>();
155154 private final Map <AnalysisMethod , Object > methodAccessors = new ConcurrentHashMap <>();
156155 private final Set <AnalysisMethod > hidingMethods = ConcurrentHashMap .newKeySet ();
157156
157+ private record RegisteredMemberData <T extends AnnotatedElement >(ConditionalRuntimeValue <T > member , boolean queriedOnly ) {
158+ }
159+
158160 // Heap reflection data
159161 private final Set <DynamicHub > heapDynamicHubs = ConcurrentHashMap .newKeySet ();
160162 private final Map <AnalysisField , Field > heapFields = new ConcurrentHashMap <>();
@@ -221,9 +223,7 @@ public void register(AccessCondition condition, boolean preserved, Class<?> claz
221223 Objects .requireNonNull (clazz , () -> nullErrorMessage ("class" , "reflection" ));
222224 runConditionalInAnalysisTask (condition , (cnd ) -> {
223225 registerClass (cnd , clazz , true , preserved );
224- if (FutureDefaultsOptions .completeReflectionTypes ()) {
225- registerClassMetadata (cnd , clazz );
226- }
226+ registerClassMetadata (cnd , clazz , preserved );
227227 });
228228 }
229229
@@ -245,18 +245,18 @@ public void registerAllClassesQuery(AccessCondition condition, boolean preserved
245245 });
246246 }
247247
248- public void registerClassMetadata (AccessCondition condition , Class <?> clazz ) {
249- registerAllDeclaredFieldsQuery (condition , true , false , clazz );
250- registerAllFieldsQuery (condition , true , false , clazz );
251- registerAllDeclaredMethodsQuery (condition , true , false , clazz );
252- registerAllMethodsQuery (condition , true , false , clazz );
253- registerAllDeclaredConstructorsQuery (condition , true , false , clazz );
254- registerAllConstructorsQuery (condition , true , false , clazz );
255- registerAllDeclaredClassesQuery (condition , false , clazz );
256- registerAllClassesQuery (condition , false , clazz );
248+ public void registerClassMetadata (AccessCondition condition , Class <?> clazz , boolean preserved ) {
249+ registerAllDeclaredFieldsQuery (condition , true , preserved , clazz );
250+ registerAllFieldsQuery (condition , true , preserved , clazz );
251+ registerAllDeclaredMethodsQuery (condition , true , preserved , clazz );
252+ registerAllMethodsQuery (condition , true , preserved , clazz );
253+ registerAllDeclaredConstructorsQuery (condition , true , preserved , clazz );
254+ registerAllConstructorsQuery (condition , true , preserved , clazz );
255+ registerAllDeclaredClassesQuery (condition , preserved , clazz );
256+ registerAllClassesQuery (condition , preserved , clazz );
257257 registerAllRecordComponentsQuery (condition , clazz );
258- registerAllPermittedSubclassesQuery (condition , false , clazz );
259- registerAllNestMembersQuery (condition , false , clazz );
258+ registerAllPermittedSubclassesQuery (condition , preserved , clazz );
259+ registerAllNestMembersQuery (condition , preserved , clazz );
260260 registerAllSignersQuery (condition , clazz );
261261 }
262262
@@ -465,24 +465,30 @@ private void registerMethod(AccessCondition cnd, boolean queriedOnly, boolean pr
465465 var classMethods = registeredMethods .computeIfAbsent (declaringType , _ -> new ConcurrentHashMap <>());
466466 var shouldRegisterReachabilityHandler = classMethods .isEmpty ();
467467
468- boolean registered = false ;
469- ConditionalRuntimeValue <Executable > conditionalValue = classMethods .get (analysisMethod );
470- if (conditionalValue == null ) {
471- var newConditionalValue = new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectExecutable );
472- conditionalValue = classMethods .putIfAbsent (analysisMethod , newConditionalValue );
473- if (conditionalValue == null ) {
474- conditionalValue = newConditionalValue ;
475- registered = true ;
468+ boolean exists = classMethods .containsKey (analysisMethod );
469+ ConditionalRuntimeValue <Executable > conditionalValue = classMethods .compute (analysisMethod , (_ , methodData ) -> {
470+ boolean registeredAsQueriedOnly = methodData != null ? methodData .queriedOnly () : queriedOnly ;
471+ if (methodData == null || (registeredAsQueriedOnly && !queriedOnly )) {
472+ /*
473+ * The dynamic access metadata needs to be reset when registering a queried-only
474+ * element as accessed.
475+ */
476+ return new RegisteredMemberData <>(new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectExecutable ), queriedOnly );
477+ } else {
478+ if (!preserved && registeredAsQueriedOnly == queriedOnly ) {
479+ var value = methodData .member ();
480+ value .getDynamicAccessMetadata ().setNotPreserved ();
481+ }
482+ return methodData ;
476483 }
477- } else if (!preserved ) {
478- conditionalValue .getDynamicAccessMetadata ().setNotPreserved ();
479- }
484+ }).member ();
485+
480486 if (!queriedOnly ) {
481487 /* queryOnly methods are conditioned by the type itself */
482488 conditionalValue .getDynamicAccessMetadata ().addCondition (cnd );
483489 }
484490
485- if (registered ) {
491+ if (! exists ) {
486492 registerTypesForMethod (analysisMethod , reflectExecutable );
487493 Class <?> declaringClass = declaringType .getJavaClass ();
488494
@@ -641,12 +647,25 @@ private void registerField(AccessCondition cnd, boolean queriedOnly, boolean pre
641647 var classFields = registeredFields .computeIfAbsent (declaringClass , _ -> new ConcurrentHashMap <>());
642648 boolean exists = classFields .containsKey (analysisField );
643649 boolean shouldRegisterReachabilityHandler = classFields .isEmpty ();
644- var cndValue = classFields .computeIfAbsent (analysisField , _ -> new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectField ));
645- if (exists ) {
646- if (!preserved ) {
647- cndValue .getDynamicAccessMetadata ().setNotPreserved ();
650+
651+ ConditionalRuntimeValue <Field > cndValue = classFields .compute (analysisField , (_ , fieldData ) -> {
652+ boolean registeredAsQueriedOnly = fieldData != null ? fieldData .queriedOnly () : queriedOnly ;
653+ if (fieldData == null || (registeredAsQueriedOnly && !queriedOnly )) {
654+ /*
655+ * The dynamic access metadata needs to be reset when registering an element as
656+ * accessed
657+ */
658+ return new RegisteredMemberData <>(new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectField ), queriedOnly );
659+ } else {
660+ if (!preserved && registeredAsQueriedOnly == queriedOnly ) {
661+ var value = fieldData .member ();
662+ value .getDynamicAccessMetadata ().setNotPreserved ();
663+ }
664+ return fieldData ;
648665 }
649- } else {
666+ }).member ();
667+
668+ if (!exists ) {
650669 registerTypesForField (analysisField , reflectField , queriedOnly );
651670
652671 /*
@@ -1267,13 +1286,23 @@ public int getEnabledReflectionQueries(Class<?> clazz) {
12671286 @ Override
12681287 public Map <AnalysisType , Map <AnalysisField , ConditionalRuntimeValue <Field >>> getReflectionFields () {
12691288 assert isSealed ();
1270- return Collections . unmodifiableMap (registeredFields );
1289+ return filterRegisteredMemberData (registeredFields );
12711290 }
12721291
12731292 @ Override
12741293 public Map <AnalysisType , Map <AnalysisMethod , ConditionalRuntimeValue <Executable >>> getReflectionExecutables () {
12751294 assert isSealed ();
1276- return Collections .unmodifiableMap (registeredMethods );
1295+ return filterRegisteredMemberData (registeredMethods );
1296+ }
1297+
1298+ private static <A , R extends AnnotatedElement > Map <AnalysisType , Map <A , ConditionalRuntimeValue <R >>> filterRegisteredMemberData (Map <AnalysisType , Map <A , RegisteredMemberData <R >>> map ) {
1299+ /*
1300+ * Return only the ConditionalRuntimeValue, the queriedOnly boolean is not relevant once the
1301+ * builder is sealed.
1302+ */
1303+ return map .entrySet ().stream ().collect (
1304+ Collectors .toUnmodifiableMap (Map .Entry ::getKey , e -> e .getValue ().entrySet ().stream ().collect (
1305+ Collectors .toUnmodifiableMap (Map .Entry ::getKey , e2 -> e2 .getValue ().member ()))));
12771306 }
12781307
12791308 @ Override
0 commit comments