|
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