|
27 | 27 |
|
28 | 28 | import java.io.IOException;
|
29 | 29 | import java.util.Arrays;
|
| 30 | +import java.util.Map; |
30 | 31 | import java.util.concurrent.ConcurrentHashMap;
|
31 | 32 | import java.util.concurrent.Semaphore;
|
32 | 33 | import java.util.logging.Level;
|
|
100 | 101 | import com.oracle.truffle.api.object.Shape;
|
101 | 102 | import com.oracle.truffle.api.source.Source;
|
102 | 103 | import com.oracle.truffle.api.source.Source.SourceBuilder;
|
103 |
| -import java.util.Map; |
104 | 104 |
|
105 | 105 | @TruffleLanguage.Registration(id = PythonLanguage.ID, //
|
106 | 106 | name = PythonLanguage.NAME, //
|
@@ -158,6 +158,9 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
|
158 | 158 |
|
159 | 159 | public final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Only a single context is active");
|
160 | 160 |
|
| 161 | + @CompilationFinal public boolean singleContext = true; |
| 162 | + private boolean firstContextInitialized; |
| 163 | + |
161 | 164 | /**
|
162 | 165 | * This assumption will be valid if all contexts are single-threaded. Hence, it will be
|
163 | 166 | * invalidated as soon as at least one context has been initialized for multi-threading.
|
@@ -293,12 +296,16 @@ protected void finalizeContext(PythonContext context) {
|
293 | 296 |
|
294 | 297 | @Override
|
295 | 298 | protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues newOptions) {
|
| 299 | + if (singleContext) { |
| 300 | + return false; |
| 301 | + } |
296 | 302 | return PythonOptions.areOptionsCompatible(firstOptions, newOptions);
|
297 | 303 | }
|
298 | 304 |
|
299 | 305 | @Override
|
300 | 306 | 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())) { |
302 | 309 | Python3Core.writeInfo("Cannot use preinitialized context.");
|
303 | 310 | return false;
|
304 | 311 | }
|
@@ -327,6 +334,7 @@ protected PythonContext createContext(Env env) {
|
327 | 334 | } else {
|
328 | 335 | assert areOptionsCompatible(options, PythonOptions.createEngineOptions(env)) : "invalid engine options";
|
329 | 336 | }
|
| 337 | + firstContextInitialized = true; |
330 | 338 | return context;
|
331 | 339 | }
|
332 | 340 |
|
@@ -738,6 +746,14 @@ private static Source newSource(PythonContext ctxt, SourceBuilder srcBuilder) th
|
738 | 746 | @Override
|
739 | 747 | protected void initializeMultipleContexts() {
|
740 | 748 | 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; |
741 | 757 | singleContextAssumption.invalidate();
|
742 | 758 | }
|
743 | 759 |
|
|
0 commit comments