Skip to content

Commit df40e10

Browse files
author
Christian Wimmer
committed
Remove deprecated support for RunReachabilityHandlersConcurrently
1 parent a09c789 commit df40e10

File tree

8 files changed

+81
-441
lines changed

8 files changed

+81
-441
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,8 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String ol
10531053
@Option(help = "Verify type states computed by the static analysis at run time. This is useful when diagnosing problems in the static analysis, but reduces peak performance significantly.", type = OptionType.Debug)//
10541054
public static final HostedOptionKey<Boolean> VerifyTypes = new HostedOptionKey<>(false);
10551055

1056-
@Option(help = "Run reachability handlers concurrently during analysis.", type = Expert, deprecated = true, deprecationMessage = "This option was introduced to simplify migration to GraalVM 22.2 and will be removed in a future release")//
1057-
public static final HostedOptionKey<Boolean> RunReachabilityHandlersConcurrently = new HostedOptionKey<>(true);
1056+
@Option(help = "Deprecated, has no effect.", deprecated = true)//
1057+
static final HostedOptionKey<Boolean> RunReachabilityHandlersConcurrently = new HostedOptionKey<>(true);
10581058

10591059
@Option(help = "Deprecated, has no effect.", deprecated = true)//
10601060
static final HostedOptionKey<Boolean> PlatformInterfaceCompatibilityMode = new HostedOptionKey<>(false);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ConcurrentReachabilityHandler.java

Lines changed: 0 additions & 143 deletions
This file was deleted.

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.Map;
4040
import java.util.Objects;
4141
import java.util.Set;
42+
import java.util.concurrent.ConcurrentHashMap;
4243
import java.util.function.BiConsumer;
4344
import java.util.function.Consumer;
4445
import java.util.function.Function;
@@ -56,6 +57,7 @@
5657
import com.oracle.graal.pointsto.ObjectScanner;
5758
import com.oracle.graal.pointsto.api.DefaultUnsafePartition;
5859
import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor;
60+
import com.oracle.graal.pointsto.meta.AnalysisElement;
5961
import com.oracle.graal.pointsto.meta.AnalysisField;
6062
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
6163
import com.oracle.graal.pointsto.meta.AnalysisMethod;
@@ -64,13 +66,12 @@
6466
import com.oracle.graal.pointsto.meta.ObjectReachableCallback;
6567
import com.oracle.svm.common.meta.MultiMethod;
6668
import com.oracle.svm.core.LinkerInvocation;
67-
import com.oracle.svm.core.SubstrateOptions;
6869
import com.oracle.svm.core.annotate.Delete;
6970
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
7071
import com.oracle.svm.core.meta.SharedField;
7172
import com.oracle.svm.core.meta.SharedMethod;
7273
import com.oracle.svm.core.meta.SharedType;
73-
import com.oracle.svm.core.option.SubstrateOptionsParser;
74+
import com.oracle.svm.core.util.UserError;
7475
import com.oracle.svm.core.util.VMError;
7576
import com.oracle.svm.hosted.ameta.FieldValueInterceptionSupport;
7677
import com.oracle.svm.hosted.analysis.Inflation;
@@ -336,14 +337,11 @@ public SVMHost getHostVM() {
336337
public static class BeforeAnalysisAccessImpl extends AnalysisAccessBase implements Feature.BeforeAnalysisAccess {
337338

338339
private final NativeLibraries nativeLibraries;
339-
private final boolean concurrentReachabilityHandlers;
340-
private final ReachabilityHandler reachabilityHandler;
340+
private final Map<Consumer<DuringAnalysisAccess>, AnalysisElement.ElementNotification> reachabilityNotifications = new ConcurrentHashMap<>();
341341

342342
public BeforeAnalysisAccessImpl(FeatureHandler featureHandler, ImageClassLoader imageClassLoader, Inflation bb, NativeLibraries nativeLibraries, DebugContext debugContext) {
343343
super(featureHandler, imageClassLoader, bb, debugContext);
344344
this.nativeLibraries = nativeLibraries;
345-
this.concurrentReachabilityHandlers = SubstrateOptions.RunReachabilityHandlersConcurrently.getValue(bb.getOptions());
346-
this.reachabilityHandler = concurrentReachabilityHandlers ? ConcurrentReachabilityHandler.singleton() : ReachabilityHandlerFeature.singleton();
347345
}
348346

349347
public NativeLibraries getNativeLibraries() {
@@ -450,26 +448,89 @@ public void registerHierarchyForReflectiveInstantiation(Class<?> c) {
450448

451449
@Override
452450
public void registerReachabilityHandler(Consumer<DuringAnalysisAccess> callback, Object... elements) {
453-
reachabilityHandler.registerReachabilityHandler(this, callback, elements);
451+
AnalysisMetaAccess metaAccess = getMetaAccess();
452+
453+
/*
454+
* All callback->notification pairs are tracked by the reachabilityNotifications map to
455+
* prevent registering the same callback multiple times. The notifications are also
456+
* tracked by each AnalysisElement, i.e., each trigger, and are removed as soon as they
457+
* are notified.
458+
*/
459+
AnalysisElement.ElementNotification notification = reachabilityNotifications.computeIfAbsent(callback, AnalysisElement.ElementNotification::new);
460+
461+
if (notification.isNotified()) {
462+
/* Already notified from an earlier registration, nothing to do. */
463+
return;
464+
}
465+
466+
for (Object trigger : elements) {
467+
AnalysisElement analysisElement;
468+
if (trigger instanceof Class) {
469+
analysisElement = metaAccess.lookupJavaType((Class<?>) trigger);
470+
} else if (trigger instanceof Field) {
471+
analysisElement = metaAccess.lookupJavaField((Field) trigger);
472+
} else if (trigger instanceof Executable) {
473+
analysisElement = metaAccess.lookupJavaMethod((Executable) trigger);
474+
} else {
475+
throw UserError.abort("'registerReachabilityHandler' called with an element that is not a Class, Field, or Executable: %s", trigger.getClass().getTypeName());
476+
}
477+
478+
analysisElement.registerReachabilityNotification(notification);
479+
if (analysisElement.isTriggered()) {
480+
/*
481+
* Element already triggered, just notify the callback. At this point we could
482+
* just notify the callback and bail out, but, for debugging, it may be useful
483+
* to execute the notification for each trigger. Note that although the
484+
* notification can be shared between multiple triggers the notification
485+
* mechanism ensures that the callback itself is only executed once.
486+
*/
487+
analysisElement.notifyReachabilityCallback(getUniverse(), notification);
488+
}
489+
}
454490
}
455491

456492
@Override
457493
public void registerMethodOverrideReachabilityHandler(BiConsumer<DuringAnalysisAccess, Executable> callback, Executable baseMethod) {
458-
reachabilityHandler.registerMethodOverrideReachabilityHandler(this, callback, baseMethod);
494+
AnalysisMetaAccess metaAccess = getMetaAccess();
495+
AnalysisMethod baseAnalysisMethod = metaAccess.lookupJavaMethod(baseMethod);
496+
497+
AnalysisElement.MethodOverrideReachableNotification notification = new AnalysisElement.MethodOverrideReachableNotification(callback);
498+
baseAnalysisMethod.registerOverrideReachabilityNotification(notification);
499+
500+
/*
501+
* Notify for already reachable overrides. When a new override becomes reachable all
502+
* installed reachability callbacks in the supertypes declaring the method are
503+
* triggered.
504+
*/
505+
for (AnalysisMethod override : reachableMethodOverrides(baseAnalysisMethod)) {
506+
notification.notifyCallback(metaAccess.getUniverse(), override);
507+
}
459508
}
460509

461510
@Override
462511
public void registerSubtypeReachabilityHandler(BiConsumer<DuringAnalysisAccess, Class<?>> callback, Class<?> baseClass) {
463-
reachabilityHandler.registerSubtypeReachabilityHandler(this, callback, baseClass);
512+
AnalysisMetaAccess metaAccess = getMetaAccess();
513+
AnalysisType baseType = metaAccess.lookupJavaType(baseClass);
514+
515+
AnalysisElement.SubtypeReachableNotification notification = new AnalysisElement.SubtypeReachableNotification(callback);
516+
baseType.registerSubtypeReachabilityNotification(notification);
517+
518+
/*
519+
* Notify for already reachable subtypes. When a new type becomes reachable all
520+
* installed reachability callbacks in the supertypes are triggered.
521+
*/
522+
for (AnalysisType subtype : reachableSubtypes(baseType)) {
523+
notification.notifyCallback(metaAccess.getUniverse(), subtype);
524+
}
464525
}
465526

466527
@Override
467528
public void registerClassInitializerReachabilityHandler(Consumer<DuringAnalysisAccess> callback, Class<?> clazz) {
468-
reachabilityHandler.registerClassInitializerReachabilityHandler(this, callback, clazz);
469-
}
470-
471-
public boolean concurrentReachabilityHandlers() {
472-
return concurrentReachabilityHandlers;
529+
/*
530+
* In our current static analysis implementations, there is no difference between the
531+
* reachability of a class and the reachability of its class initializer.
532+
*/
533+
registerReachabilityHandler(callback, clazz);
473534
}
474535

475536
@Override
@@ -516,19 +577,14 @@ public boolean getAndResetRequireAnalysisIteration() {
516577

517578
public static class ConcurrentAnalysisAccessImpl extends DuringAnalysisAccessImpl {
518579

519-
private static final String concurrentReachabilityOption = SubstrateOptionsParser.commandArgument(SubstrateOptions.RunReachabilityHandlersConcurrently, "-");
520-
521580
public ConcurrentAnalysisAccessImpl(FeatureHandler featureHandler, ImageClassLoader imageClassLoader, Inflation bb, NativeLibraries nativeLibraries, DebugContext debugContext) {
522581
super(featureHandler, imageClassLoader, bb, nativeLibraries, debugContext);
523582
}
524583

525584
@Override
526585
public void requireAnalysisIteration() {
527586
if (bb.executorIsStarted()) {
528-
String msg = "Calling DuringAnalysisAccessImpl.requireAnalysisIteration() is not necessary when running the reachability handlers concurrently during analysis. " +
529-
"To fallback to running the reachability handlers sequentially, i.e., from Feature.duringAnalysis(), you can add the " + concurrentReachabilityOption +
530-
" option to the native-image command. Note that the fallback option is deprecated and it will be removed in a future release.";
531-
throw VMError.shouldNotReachHere(msg);
587+
throw VMError.shouldNotReachHere("Calling DuringAnalysisAccessImpl.requireAnalysisIteration() is not necessary because reachability handlers run concurrently during analysis.");
532588
}
533589
super.requireAnalysisIteration();
534590
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProtectionDomainFeature.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
import org.graalvm.nativeimage.Platform;
3232
import org.graalvm.nativeimage.Platforms;
3333

34+
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3435
import com.oracle.svm.core.feature.InternalFeature;
3536
import com.oracle.svm.core.jdk.ProtectionDomainSupport;
36-
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3737
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
3838
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
3939
import com.oracle.svm.util.ReflectionUtil;
@@ -75,9 +75,6 @@ void enableCodeSource(DuringAnalysisAccess a) {
7575
ProtectionDomainSupport.enableCodeSource();
7676
if (access != null) {
7777
access.rescanField(ImageSingletons.lookup(ProtectionDomainSupport.class), executableURLSupplierField);
78-
if (!access.concurrentReachabilityHandlers()) {
79-
access.requireAnalysisIteration();
80-
}
8178
}
8279
}
8380
}

0 commit comments

Comments
 (0)