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,29 @@ 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+ if (methodData == null || (methodData .queriedOnly () && !queriedOnly )) {
471+ /*
472+ * The dynamic access metadata needs to be reset when registering a queried-only
473+ * element as accessed.
474+ */
475+ return new RegisteredMemberData <>(new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectExecutable ), queriedOnly );
476+ } else {
477+ if (!preserved && methodData .queriedOnly () == queriedOnly ) {
478+ var value = methodData .member ();
479+ value .getDynamicAccessMetadata ().setNotPreserved ();
480+ }
481+ return methodData ;
476482 }
477- } else if (!preserved ) {
478- conditionalValue .getDynamicAccessMetadata ().setNotPreserved ();
479- }
483+ }).member ();
484+
480485 if (!queriedOnly ) {
481486 /* queryOnly methods are conditioned by the type itself */
482487 conditionalValue .getDynamicAccessMetadata ().addCondition (cnd );
483488 }
484489
485- if (registered ) {
490+ if (! exists ) {
486491 registerTypesForMethod (analysisMethod , reflectExecutable );
487492 Class <?> declaringClass = declaringType .getJavaClass ();
488493
@@ -641,12 +646,24 @@ private void registerField(AccessCondition cnd, boolean queriedOnly, boolean pre
641646 var classFields = registeredFields .computeIfAbsent (declaringClass , _ -> new ConcurrentHashMap <>());
642647 boolean exists = classFields .containsKey (analysisField );
643648 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 ();
649+
650+ ConditionalRuntimeValue <Field > cndValue = classFields .compute (analysisField , (_ , fieldData ) -> {
651+ if (fieldData == null || (fieldData .queriedOnly () && !queriedOnly )) {
652+ /*
653+ * The dynamic access metadata needs to be reset when registering an element as
654+ * accessed
655+ */
656+ return new RegisteredMemberData <>(new ConditionalRuntimeValue <>(RuntimeDynamicAccessMetadata .emptySet (preserved ), reflectField ), queriedOnly );
657+ } else {
658+ if (!preserved && fieldData .queriedOnly () == queriedOnly ) {
659+ var value = fieldData .member ();
660+ value .getDynamicAccessMetadata ().setNotPreserved ();
661+ }
662+ return fieldData ;
648663 }
649- } else {
664+ }).member ();
665+
666+ if (!exists ) {
650667 registerTypesForField (analysisField , reflectField , queriedOnly );
651668
652669 /*
@@ -1267,13 +1284,23 @@ public int getEnabledReflectionQueries(Class<?> clazz) {
12671284 @ Override
12681285 public Map <AnalysisType , Map <AnalysisField , ConditionalRuntimeValue <Field >>> getReflectionFields () {
12691286 assert isSealed ();
1270- return Collections . unmodifiableMap (registeredFields );
1287+ return filterRegisteredMemberData (registeredFields );
12711288 }
12721289
12731290 @ Override
12741291 public Map <AnalysisType , Map <AnalysisMethod , ConditionalRuntimeValue <Executable >>> getReflectionExecutables () {
12751292 assert isSealed ();
1276- return Collections .unmodifiableMap (registeredMethods );
1293+ return filterRegisteredMemberData (registeredMethods );
1294+ }
1295+
1296+ private static <A , R extends AnnotatedElement > Map <AnalysisType , Map <A , ConditionalRuntimeValue <R >>> filterRegisteredMemberData (Map <AnalysisType , Map <A , RegisteredMemberData <R >>> map ) {
1297+ /*
1298+ * Return only the ConditionalRuntimeValue, the queriedOnly boolean is not relevant once the
1299+ * builder is sealed.
1300+ */
1301+ return map .entrySet ().stream ().collect (
1302+ Collectors .toUnmodifiableMap (Map .Entry ::getKey , e -> e .getValue ().entrySet ().stream ().collect (
1303+ Collectors .toUnmodifiableMap (Map .Entry ::getKey , e2 -> e2 .getValue ().member ()))));
12771304 }
12781305
12791306 @ Override
0 commit comments