4040import java .util .concurrent .atomic .AtomicReferenceFieldUpdater ;
4141import java .util .function .Consumer ;
4242
43+ import com .oracle .graal .pointsto .util .ConcurrentLightHashMap ;
4344import org .graalvm .compiler .debug .GraalError ;
4445import org .graalvm .compiler .graph .Node ;
4546import org .graalvm .util .GuardedAnnotationAccess ;
@@ -87,6 +88,12 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav
8788 private static final AtomicReferenceFieldUpdater <AnalysisType , Object > INTERCEPTORS_UPDATER = //
8889 AtomicReferenceFieldUpdater .newUpdater (AnalysisType .class , Object .class , "interceptors" );
8990
91+ private static final AtomicReferenceFieldUpdater <AnalysisType , Object > subtypeReachableNotificationsUpdater = AtomicReferenceFieldUpdater
92+ .newUpdater (AnalysisType .class , Object .class , "subtypeReachableNotifications" );
93+
94+ private static final AtomicReferenceFieldUpdater <AnalysisType , Object > overrideReachableNotificationsUpdater = AtomicReferenceFieldUpdater
95+ .newUpdater (AnalysisType .class , Object .class , "overrideReachableNotifications" );
96+
9097 protected final AnalysisUniverse universe ;
9198 private final ResolvedJavaType wrapped ;
9299
@@ -168,14 +175,14 @@ public enum UsageKind {
168175 * Contains reachability handlers that are notified when any of the subtypes are marked as
169176 * reachable. Each handler is notified only once per subtype.
170177 */
171- private final Set < SubtypeReachableNotification > subtypeReachableNotifications = ConcurrentHashMap . newKeySet () ;
178+ @ SuppressWarnings ( "unused" ) private volatile Object subtypeReachableNotifications ;
172179
173180 /**
174181 * Contains reachability handlers that are notified when any of the method override becomes
175182 * reachable *and* the declaring class of the override (or any subtype) is instantiated. Each
176183 * handler is notified only once per method override.
177184 */
178- private final Map < AnalysisMethod , Set < MethodOverrideReachableNotification >> overrideReachableNotifications = new ConcurrentHashMap <>() ;
185+ @ SuppressWarnings ( "unused" ) private volatile Object overrideReachableNotifications ;
179186
180187 AnalysisType (AnalysisUniverse universe , ResolvedJavaType javaType , JavaKind storageKind , AnalysisType objectType , AnalysisType cloneableType ) {
181188 this .universe = universe ;
@@ -476,7 +483,8 @@ private void processMethodOverrides() {
476483 forAllSuperTypes (superType -> {
477484 AtomicUtils .atomicMark (superType .isAnySubtypeInstantiated );
478485 seenSubtypes .add (superType );
479- for (var entry : superType .overrideReachableNotifications .entrySet ()) {
486+ Map <AnalysisMethod , Set <MethodOverrideReachableNotification >> overrides = ConcurrentLightHashMap .getEntries (superType , overrideReachableNotificationsUpdater );
487+ for (var entry : overrides .entrySet ()) {
480488 AnalysisMethod baseMethod = entry .getKey ();
481489 Set <MethodOverrideReachableNotification > overrideNotifications = entry .getValue ();
482490 for (AnalysisType subType : seenSubtypes ) {
@@ -517,7 +525,8 @@ public boolean registerAsReachable() {
517525 @ Override
518526 protected void onReachable () {
519527 notifyReachabilityCallbacks (universe );
520- forAllSuperTypes (type -> type .subtypeReachableNotifications .forEach (n -> n .notifyCallback (universe , this )));
528+ forAllSuperTypes (type -> ConcurrentLightHashSet .forEach (type , subtypeReachableNotificationsUpdater ,
529+ (SubtypeReachableNotification n ) -> n .notifyCallback (universe , this )));
521530 universe .notifyReachableType ();
522531 universe .hostVM .checkForbidden (this , UsageKind .Reachable );
523532 if (isArray ()) {
@@ -533,16 +542,18 @@ protected void onReachable() {
533542 }
534543
535544 public void registerSubtypeReachabilityNotification (SubtypeReachableNotification notification ) {
536- subtypeReachableNotifications . add ( notification );
545+ ConcurrentLightHashSet . addElement ( this , subtypeReachableNotificationsUpdater , notification );
537546 }
538547
539548 public void registerOverrideReachabilityNotification (AnalysisMethod declaredMethod , MethodOverrideReachableNotification notification ) {
540549 assert declaredMethod .getDeclaringClass () == this ;
541- overrideReachableNotifications .computeIfAbsent (declaredMethod , m -> ConcurrentHashMap .newKeySet ()).add (notification );
550+ Set <MethodOverrideReachableNotification > overrideNotifications = ConcurrentLightHashMap .computeIfAbsent (this ,
551+ overrideReachableNotificationsUpdater , declaredMethod , m -> ConcurrentHashMap .newKeySet ());
552+ overrideNotifications .add (notification );
542553 }
543554
544555 public Set <MethodOverrideReachableNotification > getOverrideReachabilityNotifications (AnalysisMethod method ) {
545- return overrideReachableNotifications .getOrDefault (method , Collections .emptySet ());
556+ return ConcurrentLightHashMap .getOrDefault (this , overrideReachableNotificationsUpdater , method , Collections .emptySet ());
546557 }
547558
548559 /**
0 commit comments