Skip to content

Commit 057d252

Browse files
committed
Clean up resources created by the constant expression analysis after they are no longer needed.
1 parent bc5bec8 commit 057d252

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/strictconstantanalysis/ConstantExpressionRegistry.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,22 @@
3939
import java.util.Map;
4040
import java.util.Optional;
4141
import java.util.concurrent.ConcurrentHashMap;
42+
import java.util.concurrent.atomic.AtomicBoolean;
4243

4344
public class ConstantExpressionRegistry {
4445

4546
private static final Object NULL_MARKER = new Object();
4647

47-
private final Map<Pair<ResolvedJavaMethod, Integer>, AbstractFrame<ConstantExpressionAnalyzer.Value>> registry;
48+
private Map<Pair<ResolvedJavaMethod, Integer>, AbstractFrame<ConstantExpressionAnalyzer.Value>> registry;
49+
private final AtomicBoolean isSealed = new AtomicBoolean();
4850

4951
public ConstantExpressionRegistry() {
5052
registry = new ConcurrentHashMap<>();
53+
isSealed.set(false);
5154
}
5255

5356
public void analyzeAndStore(ConstantExpressionAnalyzer analyzer, ResolvedJavaMethod method, IntrinsicContext intrinsicContext) {
57+
VMError.guarantee(!isSealed(), "Registry is already sealed");
5458
Bytecode bytecode = getBytecode(method, intrinsicContext);
5559
try {
5660
Map<Integer, AbstractFrame<ConstantExpressionAnalyzer.Value>> abstractFrames = analyzer.analyze(bytecode);
@@ -68,6 +72,7 @@ private static Bytecode getBytecode(ResolvedJavaMethod method, IntrinsicContext
6872
}
6973

7074
public Optional<Object> getReceiver(ResolvedJavaMethod callerMethod, int bci, ResolvedJavaMethod targetMethod) {
75+
VMError.guarantee(!isSealed(), "Registry is already sealed");
7176
VMError.guarantee(targetMethod.hasReceiver(), "Receiver requested for static method");
7277
AbstractFrame<ConstantExpressionAnalyzer.Value> frame = registry.get(Pair.create(callerMethod, bci));
7378
if (frame == null) {
@@ -96,6 +101,7 @@ public <T> T getReceiver(ResolvedJavaMethod callerMethod, int bci, ResolvedJavaM
96101
}
97102

98103
public Optional<Object> getArgument(ResolvedJavaMethod callerMethod, int bci, ResolvedJavaMethod targetMethod, int index) {
104+
VMError.guarantee(!isSealed(), "Registry is already sealed");
99105
int numOfParameters = targetMethod.getSignature().getParameterCount(false);
100106
VMError.guarantee(index >= 0 && index < numOfParameters, "Argument index out of bounds");
101107
AbstractFrame<ConstantExpressionAnalyzer.Value> frame = registry.get(Pair.create(callerMethod, bci));
@@ -142,6 +148,15 @@ public <T> T getArgument(ResolvedJavaMethod callerMethod, int bci, ResolvedJavaM
142148
return type.cast(argumentValue);
143149
}
144150

151+
public boolean isSealed() {
152+
return isSealed.get();
153+
}
154+
155+
public void seal() {
156+
isSealed.set(true);
157+
registry = null;
158+
}
159+
145160
public static boolean isNull(Object object) {
146161
return object == NULL_MARKER;
147162
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/strictconstantanalysis/InferredDynamicAccessLoggingFeature.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static class Options {
6060
static final HostedOptionKey<String> InferredDynamicAccessLog = new HostedOptionKey<>(null);
6161
}
6262

63-
private static final Queue<LogEntry> log = new ConcurrentLinkedQueue<>();
63+
private static Queue<LogEntry> log = new ConcurrentLinkedQueue<>();
6464

6565
public static void logConstant(GraphBuilderContext b, ParsingReason reason, ResolvedJavaMethod targetMethod, Object targetReceiver, Object[] targetArguments, Object value) {
6666
logEntry(b, reason, () -> new ConstantLogEntry(b, targetMethod, targetReceiver, targetArguments, value));
@@ -77,6 +77,7 @@ public static void logRegistration(GraphBuilderContext b, ParsingReason reason,
7777

7878
private static void logEntry(GraphBuilderContext b, ParsingReason reason, Supplier<LogEntry> entrySupplier) {
7979
if (reason.duringAnalysis() && reason != ParsingReason.JITCompilation && isEnabled()) {
80+
VMError.guarantee(log != null, "Logging attempt when log has been sealed");
8081
LogEntry entry = entrySupplier.get();
8182
b.add(ReachabilityRegistrationNode.create(() -> log.add(entry), reason));
8283
}
@@ -100,6 +101,12 @@ public void afterAnalysis(AfterAnalysisAccess access) {
100101
if (shouldWarnForNonStrictFolding()) {
101102
warnForNonStrictFolding();
102103
}
104+
/* The log is no longer used after this, so we can clean it up. */
105+
cleanLog();
106+
}
107+
108+
private static void cleanLog() {
109+
log = null;
103110
}
104111

105112
private static void dump(String location) {
@@ -140,13 +147,13 @@ private static boolean registryContainsConstantOperands(ConstantExpressionRegist
140147
Pair<ResolvedJavaMethod, Integer> callLocation = entry.callLocation;
141148
if (entry.targetMethod.hasReceiver()) {
142149
Optional<Object> receiver = registry.getReceiver(callLocation.getLeft(), callLocation.getRight(), entry.targetMethod);
143-
if (entry.targetReceiver != IGNORED_ARGUMENT_MARKER && receiver.isEmpty()) {
150+
if (entry.targetReceiver != ignoredArgument() && receiver.isEmpty()) {
144151
return false;
145152
}
146153
}
147154
for (int i = 0; i < entry.targetArguments.length; i++) {
148155
Optional<Object> argument = registry.getArgument(callLocation.getLeft(), callLocation.getRight(), entry.targetMethod, i);
149-
if (entry.targetArguments[i] != IGNORED_ARGUMENT_MARKER && argument.isEmpty()) {
156+
if (entry.targetArguments[i] != ignoredArgument() && argument.isEmpty()) {
150157
return false;
151158
}
152159
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/strictconstantanalysis/StrictConstantAnalysisFeature.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ public void registerInvocationPlugins(Providers providers, GraphBuilderConfigura
145145
plugins.appendMethodParsingPlugin((method, intrinsicContext) -> registry.analyzeAndStore(analyzer, method, intrinsicContext));
146146
}
147147

148+
@Override
149+
public void afterAnalysis(AfterAnalysisAccess access) {
150+
/*
151+
* No more bytecode parsing should happen after analysis, so we can seal and clean up the
152+
* registry.
153+
*/
154+
ConstantExpressionRegistry registry = ImageSingletons.lookup(ConstantExpressionRegistry.class);
155+
registry.seal();
156+
}
157+
148158
/**
149159
* Utility method which attempts to infer {@code targetMethod} according to the {@code Disable},
150160
* {@code Warn} and {@code Enforce} options of {@code StrictConstantAnalysis}.

0 commit comments

Comments
 (0)