Skip to content

Commit d5ff071

Browse files
committed
Force inner contexts to have their own language instance
This ensures that the singleContext assumption gets invalidated either at the beginning before any AST is executed or never. This commit also adds assertions that check this assumption. Followup work will replace the singleContextAssumption with just the singleContext field, which is enough and can be checked only once, e.g., only when activating a specialization on the slow path.
1 parent f7f7ff5 commit d5ff071

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.io.IOException;
2929
import java.util.Arrays;
30+
import java.util.Map;
3031
import java.util.concurrent.ConcurrentHashMap;
3132
import java.util.concurrent.Semaphore;
3233
import java.util.logging.Level;
@@ -100,7 +101,6 @@
100101
import com.oracle.truffle.api.object.Shape;
101102
import com.oracle.truffle.api.source.Source;
102103
import com.oracle.truffle.api.source.Source.SourceBuilder;
103-
import java.util.Map;
104104

105105
@TruffleLanguage.Registration(id = PythonLanguage.ID, //
106106
name = PythonLanguage.NAME, //
@@ -158,6 +158,9 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
158158

159159
public final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Only a single context is active");
160160

161+
@CompilationFinal public boolean singleContext = true;
162+
private boolean firstContextInitialized;
163+
161164
/**
162165
* This assumption will be valid if all contexts are single-threaded. Hence, it will be
163166
* invalidated as soon as at least one context has been initialized for multi-threading.
@@ -293,12 +296,16 @@ protected void finalizeContext(PythonContext context) {
293296

294297
@Override
295298
protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues newOptions) {
299+
if (singleContext) {
300+
return false;
301+
}
296302
return PythonOptions.areOptionsCompatible(firstOptions, newOptions);
297303
}
298304

299305
@Override
300306
protected boolean patchContext(PythonContext context, Env newEnv) {
301-
if (!areOptionsCompatible(context.getEnv().getOptions(), newEnv.getOptions())) {
307+
// We intentionally bypass the singleContext check in PythonLanguage#areOptionsCompatible
308+
if (!PythonOptions.areOptionsCompatible(context.getEnv().getOptions(), newEnv.getOptions())) {
302309
Python3Core.writeInfo("Cannot use preinitialized context.");
303310
return false;
304311
}
@@ -327,6 +334,7 @@ protected PythonContext createContext(Env env) {
327334
} else {
328335
assert areOptionsCompatible(options, PythonOptions.createEngineOptions(env)) : "invalid engine options";
329336
}
337+
firstContextInitialized = true;
330338
return context;
331339
}
332340

@@ -738,6 +746,14 @@ private static Source newSource(PythonContext ctxt, SourceBuilder srcBuilder) th
738746
@Override
739747
protected void initializeMultipleContexts() {
740748
super.initializeMultipleContexts();
749+
// We want to make sure that initializeMultipleContexts is always called before the first
750+
// context is created.
751+
// This would not be the case with inner contexts, but we achieve that by returning false
752+
// from areOptionsCompatible when it is invoked for the first inner context, then Truffle
753+
// creates a new PythonLanguage instance, calls initializeMultipleContexts on it, and only
754+
// then uses it to create the inner contexts.
755+
assert !firstContextInitialized;
756+
singleContext = false;
741757
singleContextAssumption.invalidate();
742758
}
743759

0 commit comments

Comments
 (0)