Skip to content

Commit a014e3c

Browse files
committed
[GR-50990] Make options engine.CompilerThreads and engine.CompilationFailureAction available under UNTRUSTED sandbox policy.
PullRequest: graal/16825
2 parents ef48551 + 55ad784 commit a014e3c

File tree

8 files changed

+100
-43
lines changed

8 files changed

+100
-43
lines changed

truffle/docs/Options.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ They are useful to users and language and tool implementers.
5454
- `--engine.DebugCacheCompileUseLastTier=true|false` : If true uses the last tier instead of the first tier compiler. By default the last tier compiler is used (default: true).
5555
- `--engine.BackgroundCompilation=true|false` : Enable asynchronous truffle compilation in background threads (default: true)
5656
- `--engine.Compilation=true|false` : Enable or disable Truffle compilation.
57+
- `--engine.CompilationFailureAction=Silent|Print|Throw|Diagnose|ExitVM` : Specifies the action to take when Truffle compilation fails.
58+
The accepted values are:
59+
Silent - Print nothing to the console.
60+
Print - Print the exception to the console.
61+
Throw - Throw the exception to caller.
62+
Diagnose - Retry compilation with extra diagnostics enabled.
63+
ExitVM - Exit the VM process.
5764
- `--engine.CompilerIdleDelay=<ms>` : Set the time in milliseconds an idle Truffle compiler thread will wait for new tasks before terminating. New compiler threads will be started once new compilation tasks are submitted. Select '0' to never terminate the Truffle compiler thread. The option is not supported by all Truffle runtimes. On the runtime which doesn't support it the option has no effect. default: 10000
5865
- `--engine.CompilerThreads=[1, inf)` : Manually set the number of compiler threads. By default, the number of compiler threads is scaled with the number of available cores on the CPU.
5966
- `--engine.EncodedGraphCachePurgeDelay=<ms>` : Delay, in milliseconds, after which the encoded graph cache is dropped when a Truffle compiler thread becomes idle (default: 10000).
@@ -120,13 +127,6 @@ These are internal options for debugging language implementations and tools.
120127
- `--engine.DebugCacheStore` : Prepares the engine for caching and stores it a static field instead of writing it to disk.
121128
- `--engine.DebugTraceCache` : Enables tracing for the engine cache debug feature.
122129
- `--engine.ArgumentTypeSpeculation=true|false` : Speculate on arguments types at call sites (default: true)
123-
- `--engine.CompilationFailureAction=Silent|Print|Throw|Diagnose|ExitVM` : Specifies the action to take when Truffle compilation fails.
124-
The accepted values are:
125-
Silent - Print nothing to the console.
126-
Print - Print the exception to the console.
127-
Throw - Throw the exception to caller.
128-
Diagnose - Retry compilation with extra diagnostics enabled.
129-
ExitVM - Exit the VM process.
130130
- `--engine.CompilationStatisticDetails` : Print additional more verbose Truffle compilation statistics at the end of a run.
131131
- `--engine.CompilationStatistics` : Print Truffle compilation statistics at the end of a run.
132132
- `--engine.CompileAOTOnCreate` : Compiles created call targets immediately with last tier. Disables background compilation if enabled.

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SandboxPolicyTest.java

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,19 @@
4040
*/
4141
package com.oracle.truffle.api.test.polyglot;
4242

43-
import com.oracle.truffle.api.Option;
44-
import com.oracle.truffle.api.TruffleLanguage;
45-
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
43+
import static org.junit.Assert.assertTrue;
44+
45+
import java.io.IOException;
46+
import java.io.InputStream;
47+
import java.io.OutputStream;
48+
import java.net.URI;
49+
import java.util.Collection;
50+
import java.util.EnumSet;
51+
import java.util.List;
52+
import java.util.Objects;
53+
import java.util.Properties;
54+
import java.util.Set;
55+
4656
import org.graalvm.options.OptionCategory;
4757
import org.graalvm.options.OptionDescriptors;
4858
import org.graalvm.options.OptionKey;
@@ -65,18 +75,11 @@
6575
import org.junit.runner.RunWith;
6676
import org.junit.runners.Parameterized;
6777

68-
import java.io.IOException;
69-
import java.io.InputStream;
70-
import java.io.OutputStream;
71-
import java.net.URI;
72-
import java.util.Collection;
73-
import java.util.EnumSet;
74-
import java.util.List;
75-
import java.util.Objects;
76-
import java.util.Properties;
77-
import java.util.Set;
78-
79-
import static org.junit.Assert.assertTrue;
78+
import com.oracle.truffle.api.Option;
79+
import com.oracle.truffle.api.Truffle;
80+
import com.oracle.truffle.api.TruffleLanguage;
81+
import com.oracle.truffle.api.impl.DefaultTruffleRuntime;
82+
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
8083

8184
@RunWith(Parameterized.class)
8285
public class SandboxPolicyTest {
@@ -968,6 +971,36 @@ public void testHostAccess() {
968971
}
969972
}
970973

974+
@Test
975+
@SuppressWarnings("try")
976+
public void testCompilationFailureAction() {
977+
Assume.assumeTrue(configuration.hasIsolateLibrary() || !(Truffle.getRuntime() instanceof DefaultTruffleRuntime));
978+
if (configuration.sandboxPolicy.isStricterOrEqual(SandboxPolicy.CONSTRAINED) &&
979+
(SandboxPolicy.ISOLATED.isStricterThan(configuration.sandboxPolicy) || configuration.hasIsolateLibrary())) {
980+
for (String exceptionAction : new String[]{"Silent", "Print", "Throw", "Diagnose", "ExitVM"}) {
981+
try (Engine engine = newEngineBuilder(UntrustedLanguage.ID).sandbox(configuration.sandboxPolicy).option("engine.CompilationFailureAction",
982+
exceptionAction).build()) {
983+
assertTrue("Silent".equals(exceptionAction) || "Print".equals(exceptionAction));
984+
} catch (IllegalArgumentException iae) {
985+
assertTrue(!"Silent".equals(exceptionAction) && !"Print".equals(exceptionAction));
986+
assertTrue(iae.getMessage().contains("is set to " + exceptionAction + ", but must be set to Silent or Print"));
987+
}
988+
}
989+
}
990+
}
991+
992+
@Test
993+
@SuppressWarnings({"try"})
994+
public void testCompilerThreads() {
995+
Assume.assumeTrue(configuration.hasIsolateLibrary() || !(Truffle.getRuntime() instanceof DefaultTruffleRuntime));
996+
if (configuration.sandboxPolicy.isStricterOrEqual(SandboxPolicy.CONSTRAINED) &&
997+
(SandboxPolicy.ISOLATED.isStricterThan(configuration.sandboxPolicy) || configuration.hasIsolateLibrary())) {
998+
try (Engine engine = newEngineBuilder(UntrustedLanguage.ID).sandbox(configuration.sandboxPolicy).option("engine.CompilerThreads", "1").build()) {
999+
// deliberately empty
1000+
}
1001+
}
1002+
}
1003+
9711004
private Engine.Builder newEngineBuilder(String... permittedLanguages) {
9721005
Engine.Builder builder = Engine.newBuilder(permittedLanguages).out(OutputStream.nullOutputStream()).err(OutputStream.nullOutputStream());
9731006
if (configuration.sandboxPolicy.isStricterOrEqual(SandboxPolicy.ISOLATED) && configuration.supportsIsolatedPolicy) {

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,15 +1213,15 @@ public ThreadLocalHandshake getThreadLocalHandshake() {
12131213

12141214
public abstract void flushCompileQueue(Object runtimeData);
12151215

1216-
public abstract Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory);
1216+
public abstract Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy);
12171217

12181218
public abstract Object tryLoadCachedEngine(OptionValues runtimeData, Function<String, TruffleLogger> logger);
12191219

12201220
public abstract void onEngineCreate(Object engine, Object runtimeData);
12211221

12221222
public abstract boolean isStoreEnabled(OptionValues options);
12231223

1224-
public abstract void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> logSupplier);
1224+
public abstract void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> logSupplier, SandboxPolicy sandboxPolicy);
12251225

12261226
public abstract boolean onEngineClosing(Object runtimeData);
12271227

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultRuntimeAccessor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
import org.graalvm.options.OptionDescriptors;
4848
import org.graalvm.options.OptionValues;
49+
import org.graalvm.polyglot.SandboxPolicy;
4950

5051
import com.oracle.truffle.api.Assumption;
5152
import com.oracle.truffle.api.CallTarget;
@@ -205,7 +206,7 @@ public void reportPolymorphicSpecialize(Node source) {
205206
}
206207

207208
@Override
208-
public Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory) {
209+
public Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy) {
209210
return null;
210211
}
211212

@@ -225,7 +226,7 @@ public boolean isStoreEnabled(OptionValues options) {
225226
}
226227

227228
@Override
228-
public void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory) {
229+
public void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy) {
229230

230231
}
231232

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ final class PolyglotEngineImpl implements com.oracle.truffle.polyglot.PolyglotIm
335335
this.specializationStatistics = null;
336336
}
337337

338-
this.runtimeData = RUNTIME.createRuntimeData(this, engineOptions, engineLogger);
338+
this.runtimeData = RUNTIME.createRuntimeData(this, engineOptions, engineLogger, sandboxPolicy);
339339
notifyCreated();
340340

341341
if (!preInitialization) {
@@ -583,7 +583,7 @@ void notifyCreated() {
583583
}
584584
this.api = getAPIAccess().newEngine(impl.engineDispatch, this, true);
585585

586-
this.runtimeData = RUNTIME.createRuntimeData(this, prototype.engineOptionValues, prototype.engineLoggerSupplier);
586+
this.runtimeData = RUNTIME.createRuntimeData(this, prototype.engineOptionValues, prototype.engineLoggerSupplier, sandboxPolicy);
587587
ensureInstrumentsCreated(instrumentsToCreate);
588588
notifyCreated();
589589
}
@@ -702,7 +702,7 @@ void patch(SandboxPolicy newSandboxPolicy,
702702
Map<PolyglotInstrument, Map<String, String>> instrumentsOptions = new HashMap<>();
703703
parseOptions(newOptions, languagesOptions, instrumentsOptions);
704704

705-
RUNTIME.onEnginePatch(this.runtimeData, engineOptions, logSupplier);
705+
RUNTIME.onEnginePatch(this.runtimeData, engineOptions, logSupplier, sandboxPolicy);
706706

707707
List<OptionDescriptor> deprecatedDescriptors = new ArrayList<>();
708708
for (PolyglotLanguage language : languagesOptions.keySet()) {

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/EngineData.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
*/
4141
package com.oracle.truffle.runtime;
4242

43-
import static com.oracle.truffle.runtime.OptimizedTruffleRuntime.getRuntime;
4443
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.ArgumentTypeSpeculation;
4544
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.BackgroundCompilation;
4645
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.Compilation;
@@ -78,6 +77,7 @@
7877
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.TraversingQueueFirstTierBonus;
7978
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.TraversingQueueFirstTierPriority;
8079
import static com.oracle.truffle.runtime.OptimizedRuntimeOptions.TraversingQueueWeightingBothTiers;
80+
import static com.oracle.truffle.runtime.OptimizedTruffleRuntime.getRuntime;
8181

8282
import java.util.ArrayList;
8383
import java.util.Collection;
@@ -91,6 +91,7 @@
9191

9292
import org.graalvm.collections.Pair;
9393
import org.graalvm.options.OptionValues;
94+
import org.graalvm.polyglot.SandboxPolicy;
9495

9596
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
9697
import com.oracle.truffle.api.TruffleLanguage;
@@ -176,18 +177,33 @@ public final class EngineData {
176177
*/
177178
private volatile Map<Class<?>, Object> engineLocals;
178179

179-
EngineData(Object polyglotEngine, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory) {
180+
EngineData(Object polyglotEngine, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy) {
180181
Objects.requireNonNull(polyglotEngine);
181182
Objects.requireNonNull(runtimeOptions);
182183
this.polyglotEngine = polyglotEngine;
183184
this.id = engineCounter.incrementAndGet();
184185
this.loggerFactory = loggerFactory;
185-
this.loadOptions(runtimeOptions);
186+
this.loadOptions(runtimeOptions, sandboxPolicy);
186187

187188
// the splittingStatistics requires options to be initialized
188189
this.splittingStatistics = new TruffleSplittingStrategy.SplitStatisticsData();
189190
}
190191

192+
public static IllegalArgumentException sandboxPolicyException(SandboxPolicy sandboxPolicy, String reason, String fix) {
193+
Objects.requireNonNull(sandboxPolicy);
194+
Objects.requireNonNull(reason);
195+
Objects.requireNonNull(fix);
196+
String spawnIsolateHelp;
197+
if (sandboxPolicy.isStricterOrEqual(SandboxPolicy.ISOLATED)) {
198+
spawnIsolateHelp = " If you switch to a less strict sandbox policy you can still spawn an isolate with an isolated heap using Builder.option(\"engine.SpawnIsolate\",\"true\").";
199+
} else {
200+
spawnIsolateHelp = "";
201+
}
202+
String message = String.format("The validation for the given sandbox policy %s failed. %s " +
203+
"In order to resolve this %s or switch to a less strict sandbox policy using Builder.sandbox(SandboxPolicy).%s", sandboxPolicy, reason, fix, spawnIsolateHelp);
204+
return new IllegalArgumentException(message);
205+
}
206+
191207
public void preinitializeContext() {
192208
OptimizedRuntimeAccessor.ENGINE.preinitializeContext(this.polyglotEngine);
193209
}
@@ -242,9 +258,9 @@ void onEngineCreated(Object engine) {
242258
getRuntime().getEngineCacheSupport().onEngineCreated(this);
243259
}
244260

245-
void onEnginePatch(OptionValues newRuntimeOptions, Function<String, TruffleLogger> newLoggerFactory) {
261+
void onEnginePatch(OptionValues newRuntimeOptions, Function<String, TruffleLogger> newLoggerFactory, SandboxPolicy sandboxPolicy) {
246262
this.loggerFactory = newLoggerFactory;
247-
loadOptions(newRuntimeOptions);
263+
loadOptions(newRuntimeOptions, sandboxPolicy);
248264
getRuntime().getEngineCacheSupport().onEnginePatch(this);
249265
}
250266

@@ -266,7 +282,7 @@ void onEngineClosed() {
266282
this.polyglotEngine = null;
267283
}
268284

269-
private void loadOptions(OptionValues options) {
285+
private void loadOptions(OptionValues options, SandboxPolicy sandboxPolicy) {
270286
this.engineOptions = options;
271287

272288
// splitting options
@@ -313,7 +329,7 @@ private void loadOptions(OptionValues options) {
313329
this.traceTransferToInterpreter = options.get(TraceTransferToInterpreter);
314330
this.traceDeoptimizeFrame = options.get(TraceDeoptimizeFrame);
315331
this.compilationFailureAction = options.get(CompilationFailureAction);
316-
validateOptions();
332+
validateOptions(sandboxPolicy);
317333
parsedCompileOnly = null;
318334

319335
Map<String, String> compilerOptionValues = OptimizedTruffleRuntime.CompilerOptionsDescriptors.extractOptions(engineOptions);
@@ -421,7 +437,12 @@ public Collection<OptimizedCallTarget> getCallTargets() {
421437
return (Collection<OptimizedCallTarget>) OptimizedRuntimeAccessor.ENGINE.findCallTargets(polyglotEngine);
422438
}
423439

424-
private void validateOptions() {
440+
private void validateOptions(SandboxPolicy sandboxPolicy) {
441+
if (sandboxPolicy.isStricterOrEqual(SandboxPolicy.CONSTRAINED) && compilationFailureAction != ExceptionAction.Silent && compilationFailureAction != ExceptionAction.Print) {
442+
throw OptimizedRuntimeAccessor.ENGINE.createPolyglotEngineException(
443+
sandboxPolicyException(sandboxPolicy, "The engine.CompilationFailureAction option is set to " + compilationFailureAction.name() + ", but must be set to Silent or Print.",
444+
"use the default value (Silent) by removing Builder.option(\"engine.CompilationFailureAction\", ...) or set it to Print"));
445+
}
425446
if (compilationFailureAction == ExceptionAction.Throw && backgroundCompilation) {
426447
getEngineLogger().log(Level.WARNING, "The 'Throw' value of the 'engine.CompilationFailureAction' option requires the 'engine.BackgroundCompilation' option to be set to 'false'.");
427448
}

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedRuntimeOptions.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public ExceptionAction apply(String s) {
133133
}
134134
});
135135

136-
@Option(help = ExceptionAction.HELP, usageSyntax = "Silent|Print|Throw|Diagnose|ExitVM", category = OptionCategory.INTERNAL) //
136+
@Option(help = ExceptionAction.HELP, usageSyntax = "Silent|Print|Throw|Diagnose|ExitVM", category = OptionCategory.EXPERT, stability = OptionStability.STABLE, sandbox = SandboxPolicy.UNTRUSTED) //
137137
public static final OptionKey<ExceptionAction> CompilationFailureAction = new OptionKey<>(ExceptionAction.Silent, EXCEPTION_ACTION_TYPE);
138138

139139
@Option(help = "Print additional more verbose Truffle compilation statistics at the end of a run.", category = OptionCategory.INTERNAL) //
@@ -158,7 +158,8 @@ public ExceptionAction apply(String s) {
158158
// TODO: GR-29949
159159
public static final OptionKey<Long> CompilerIdleDelay = new OptionKey<>(10000L);
160160

161-
@Option(help = "Manually set the number of compiler threads. By default, the number of compiler threads is scaled with the number of available cores on the CPU.", usageSyntax = "[1, inf)", category = OptionCategory.EXPERT) //
161+
@Option(help = "Manually set the number of compiler threads. By default, the number of compiler threads is scaled with the number of available cores on the CPU.", usageSyntax = "[1, inf)", category = OptionCategory.EXPERT, //
162+
stability = OptionStability.STABLE, sandbox = SandboxPolicy.UNTRUSTED) //
162163
public static final OptionKey<Integer> CompilerThreads = new OptionKey<>(-1);
163164

164165
@Option(help = "Reduce or increase the compilation threshold depending on the size of the compilation queue (default: true).", usageSyntax = "true|false", category = OptionCategory.INTERNAL) //

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedRuntimeSupport.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
import org.graalvm.options.OptionDescriptors;
4848
import org.graalvm.options.OptionValues;
49+
import org.graalvm.polyglot.SandboxPolicy;
4950

5051
import com.oracle.truffle.api.Assumption;
5152
import com.oracle.truffle.api.CallTarget;
@@ -300,8 +301,8 @@ public boolean isStoreEnabled(OptionValues options) {
300301
}
301302

302303
@Override
303-
public Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory) {
304-
return new EngineData(engine, engineOptions, loggerFactory);
304+
public Object createRuntimeData(Object engine, OptionValues engineOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy) {
305+
return new EngineData(engine, engineOptions, loggerFactory, sandboxPolicy);
305306
}
306307

307308
@Override
@@ -310,8 +311,8 @@ public void onEngineCreate(Object engine, Object runtimeData) {
310311
}
311312

312313
@Override
313-
public void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory) {
314-
((EngineData) runtimeData).onEnginePatch(runtimeOptions, loggerFactory);
314+
public void onEnginePatch(Object runtimeData, OptionValues runtimeOptions, Function<String, TruffleLogger> loggerFactory, SandboxPolicy sandboxPolicy) {
315+
((EngineData) runtimeData).onEnginePatch(runtimeOptions, loggerFactory, sandboxPolicy);
315316
}
316317

317318
@Override

0 commit comments

Comments
 (0)