Bug 1840996 - Add PrefableCompileOptions and use it in ContextOptions and CompileOptions. r=bthrall

Differential Revision: https://phabricator.services.mozilla.com/D182458
This commit is contained in:
Tooru Fujisawa
2023-07-06 21:19:11 +00:00
parent 20a9510430
commit b78d6837dc
6 changed files with 151 additions and 61 deletions

View File

@@ -117,6 +117,93 @@ enum class DelazificationOption : uint8_t {
class JS_PUBLIC_API InstantiateOptions;
class JS_PUBLIC_API DecodeOptions;
// Compilation-specific part of JS::ContextOptions which is supposed to be
// configured by user prefs.
class JS_PUBLIC_API PrefableCompileOptions {
public:
PrefableCompileOptions()
: importAssertions_(false),
sourcePragmas_(true),
throwOnAsmJSValidationFailure_(false) {}
bool importAssertions() const { return importAssertions_; }
PrefableCompileOptions& setImportAssertions(bool enabled) {
importAssertions_ = enabled;
return *this;
}
// Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas.
bool sourcePragmas() const { return sourcePragmas_; }
PrefableCompileOptions& setSourcePragmas(bool flag) {
sourcePragmas_ = flag;
return *this;
}
AsmJSOption asmJSOption() const { return asmJSOption_; }
PrefableCompileOptions& setAsmJS(bool flag) {
asmJSOption_ =
flag ? AsmJSOption::Enabled : AsmJSOption::DisabledByAsmJSPref;
return *this;
}
PrefableCompileOptions& setAsmJSOption(AsmJSOption option) {
asmJSOption_ = option;
return *this;
}
bool throwOnAsmJSValidationFailure() const {
return throwOnAsmJSValidationFailure_;
}
PrefableCompileOptions& setThrowOnAsmJSValidationFailure(bool flag) {
throwOnAsmJSValidationFailure_ = flag;
return *this;
}
PrefableCompileOptions& toggleThrowOnAsmJSValidationFailure() {
throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
return *this;
}
#if defined(DEBUG) || defined(JS_JITSPEW)
template <typename Printer>
void dumpWith(Printer& print) const {
# define PrintFields_(Name) print(#Name, Name)
PrintFields_(importAssertions_);
PrintFields_(sourcePragmas_);
PrintFields_(throwOnAsmJSValidationFailure_);
# undef PrintFields_
switch (asmJSOption_) {
case AsmJSOption::Enabled:
print("asmJSOption_", "AsmJSOption::Enabled");
break;
case AsmJSOption::DisabledByAsmJSPref:
print("asmJSOption_", "AsmJSOption::DisabledByAsmJSPref");
break;
case AsmJSOption::DisabledByLinker:
print("asmJSOption_", "AsmJSOption::DisabledByLinker");
break;
case AsmJSOption::DisabledByNoWasmCompiler:
print("asmJSOption_", "AsmJSOption::DisabledByNoWasmCompiler");
break;
case AsmJSOption::DisabledByDebugger:
print("asmJSOption_", "AsmJSOption::DisabledByDebugger");
break;
}
}
#endif // defined(DEBUG) || defined(JS_JITSPEW)
private:
// ==== Syntax-related options. ====
bool importAssertions_ : 1;
// The context has specified that source pragmas should be parsed.
bool sourcePragmas_ : 1;
// ==== asm.js options. ====
bool throwOnAsmJSValidationFailure_ : 1;
AsmJSOption asmJSOption_ = AsmJSOption::DisabledByAsmJSPref;
};
/**
* The common base class for the CompileOptions hierarchy.
*
@@ -161,9 +248,6 @@ class JS_PUBLIC_API TransitiveCompileOptions {
// The Realm of this script is configured to use fdlibm math library.
bool alwaysUseFdlibm_ = false;
// The context has specified that source pragmas should be parsed.
bool sourcePragmas_ = true;
// Flag used to bypass the filename validation callback.
// See also SetFilenameValidationCallback.
bool skipFilenameValidation_ = false;
@@ -187,8 +271,6 @@ class JS_PUBLIC_API TransitiveCompileOptions {
public:
bool selfHostingMode = false;
AsmJSOption asmJSOption = AsmJSOption::DisabledByAsmJSPref;
bool throwOnAsmJSValidationFailureOption = false;
bool forceAsync = false;
bool discardSource = false;
bool sourceIsLazy = false;
@@ -199,8 +281,6 @@ class JS_PUBLIC_API TransitiveCompileOptions {
// modules loaded with ChromeUtils.importModule.
bool topLevelAwait = true;
bool importAssertions = false;
// When decoding from XDR into a Stencil, directly reference data in the
// buffer (where possible) instead of copying it. This is an optional
// performance optimization, and may also reduce memory if the buffer is going
@@ -240,6 +320,8 @@ class JS_PUBLIC_API TransitiveCompileOptions {
// WARNING: This option will eventually be removed.
bool deoptimizeModuleGlobalVars = false;
PrefableCompileOptions prefableOptions_;
/**
* |introductionType| is a statically allocated C string. See JSScript.h
* for more information.
@@ -301,7 +383,17 @@ class JS_PUBLIC_API TransitiveCompileOptions {
DelazificationOption eagerDelazificationStrategy() const {
return eagerDelazificationStrategy_;
}
bool sourcePragmas() const { return sourcePragmas_; }
bool importAssertions() const { return prefableOptions_.importAssertions(); }
bool sourcePragmas() const { return prefableOptions_.sourcePragmas(); }
bool throwOnAsmJSValidationFailure() const {
return prefableOptions_.throwOnAsmJSValidationFailure();
}
AsmJSOption asmJSOption() const { return prefableOptions_.asmJSOption(); }
void setAsmJSOption(AsmJSOption option) {
prefableOptions_.setAsmJSOption(option);
}
JS::ConstUTF8CharsZ filename() const { return filename_; }
JS::ConstUTF8CharsZ introducerFilename() const { return introducerFilename_; }
const char16_t* sourceMapURL() const { return sourceMapURL_; }
@@ -319,21 +411,17 @@ class JS_PUBLIC_API TransitiveCompileOptions {
PrintFields_(mutedErrors_);
PrintFields_(forceStrictMode_);
PrintFields_(alwaysUseFdlibm_);
PrintFields_(sourcePragmas_);
PrintFields_(skipFilenameValidation_);
PrintFields_(hideScriptFromDebugger_);
PrintFields_(deferDebugMetadata_);
PrintFields_(eagerDelazificationStrategy_);
PrintFields_(selfHostingMode);
PrintFields_(asmJSOption);
PrintFields_(throwOnAsmJSValidationFailureOption);
PrintFields_(forceAsync);
PrintFields_(discardSource);
PrintFields_(sourceIsLazy);
PrintFields_(allowHTMLComments);
PrintFields_(nonSyntacticScope);
PrintFields_(topLevelAwait);
PrintFields_(importAssertions);
PrintFields_(borrowBuffer);
PrintFields_(usePinnedBytecode);
PrintFields_(allocateInstantiationStorage);
@@ -343,6 +431,8 @@ class JS_PUBLIC_API TransitiveCompileOptions {
PrintFields_(introductionOffset);
PrintFields_(hasIntroductionInfo);
# undef PrintFields_
prefableOptions_.dumpWith(print);
}
#endif // defined(DEBUG) || defined(JS_JITSPEW)
};

View File

@@ -11,6 +11,7 @@
#include "jstypes.h" // JS_PUBLIC_API
#include "js/CompileOptions.h" // PrefableCompileOptions
#include "js/WasmFeatures.h"
struct JS_PUBLIC_API JSContext;
@@ -21,8 +22,7 @@ class JS_PUBLIC_API ContextOptions {
public:
// clang-format off
ContextOptions()
: asmJS_(true),
wasm_(true),
: wasm_(true),
wasmForTrustedPrinciples_(true),
wasmVerbose_(false),
wasmBaseline_(true),
@@ -33,12 +33,10 @@ class JS_PUBLIC_API ContextOptions {
#undef WASM_DEFAULT_FEATURE
#undef WASM_EXPERIMENTAL_FEATURE
testWasmAwaitTier2_(false),
throwOnAsmJSValidationFailure_(false),
disableIon_(false),
disableEvalSecurityChecks_(false),
asyncStack_(true),
asyncStackCaptureDebuggeeOnly_(false),
sourcePragmas_(true),
throwOnDebuggeeWouldRun_(true),
dumpStackOnDebuggeeWouldRun_(false),
strictMode_(false),
@@ -46,18 +44,20 @@ class JS_PUBLIC_API ContextOptions {
trackNotImplemented_(false),
trySmoosh_(false),
#endif
fuzzing_(false),
importAssertions_(false) {
fuzzing_(false) {
}
// clang-format on
bool asmJS() const { return asmJS_; }
bool asmJS() const {
return compileOptions_.asmJSOption() == AsmJSOption::Enabled;
}
AsmJSOption asmJSOption() const { return compileOptions_.asmJSOption(); }
ContextOptions& setAsmJS(bool flag) {
asmJS_ = flag;
compileOptions_.setAsmJS(flag);
return *this;
}
ContextOptions& toggleAsmJS() {
asmJS_ = !asmJS_;
ContextOptions& setAsmJSOption(AsmJSOption option) {
compileOptions_.setAsmJSOption(option);
return *this;
}
@@ -111,14 +111,14 @@ class JS_PUBLIC_API ContextOptions {
#undef WASM_FEATURE
bool throwOnAsmJSValidationFailure() const {
return throwOnAsmJSValidationFailure_;
return compileOptions_.throwOnAsmJSValidationFailure();
}
ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
throwOnAsmJSValidationFailure_ = flag;
compileOptions_.setThrowOnAsmJSValidationFailure(flag);
return *this;
}
ContextOptions& toggleThrowOnAsmJSValidationFailure() {
throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
compileOptions_.toggleThrowOnAsmJSValidationFailure();
return *this;
}
@@ -131,9 +131,9 @@ class JS_PUBLIC_API ContextOptions {
return *this;
}
bool importAssertions() const { return importAssertions_; }
bool importAssertions() const { return compileOptions_.importAssertions(); }
ContextOptions& setImportAssertions(bool enabled) {
importAssertions_ = enabled;
compileOptions_.setImportAssertions(enabled);
return *this;
}
@@ -160,9 +160,9 @@ class JS_PUBLIC_API ContextOptions {
}
// Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas.
bool sourcePragmas() const { return sourcePragmas_; }
bool sourcePragmas() const { return compileOptions_.sourcePragmas(); }
ContextOptions& setSourcePragmas(bool flag) {
sourcePragmas_ = flag;
compileOptions_.setSourcePragmas(flag);
return *this;
}
@@ -213,12 +213,17 @@ class JS_PUBLIC_API ContextOptions {
ContextOptions& setFuzzing(bool flag);
void disableOptionsForSafeMode() {
setAsmJS(false);
setAsmJSOption(AsmJSOption::DisabledByAsmJSPref);
setWasmBaseline(false);
}
PrefableCompileOptions& compileOptions() { return compileOptions_; }
const PrefableCompileOptions& compileOptions() const {
return compileOptions_;
}
private:
bool asmJS_ : 1;
// WASM options.
bool wasm_ : 1;
bool wasmForTrustedPrinciples_ : 1;
bool wasmVerbose_ : 1;
@@ -228,12 +233,14 @@ class JS_PUBLIC_API ContextOptions {
JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE, WASM_FEATURE)
#undef WASM_FEATURE
bool testWasmAwaitTier2_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
// JIT options.
bool disableIon_ : 1;
bool disableEvalSecurityChecks_ : 1;
// Runtime options.
bool asyncStack_ : 1;
bool asyncStackCaptureDebuggeeOnly_ : 1;
bool sourcePragmas_ : 1;
bool throwOnDebuggeeWouldRun_ : 1;
bool dumpStackOnDebuggeeWouldRun_ : 1;
bool strictMode_ : 1;
@@ -242,7 +249,9 @@ class JS_PUBLIC_API ContextOptions {
bool trySmoosh_ : 1;
#endif
bool fuzzing_ : 1;
bool importAssertions_ : 1;
// Compile options.
PrefableCompileOptions compileOptions_;
};
JS_PUBLIC_API ContextOptions& ContextOptionsRef(JSContext* cx);

View File

@@ -4966,7 +4966,7 @@ bool GeneralParser<ParseHandler, Unit>::assertClause(
ListNodeType assertionsSet) {
MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assert));
if (!options().importAssertions) {
if (!options().importAssertions()) {
error(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED);
return false;
}
@@ -12792,7 +12792,7 @@ GeneralParser<ParseHandler, Unit>::importExpr(YieldHandling yieldHandling,
}
Node optionalArg;
if (options().importAssertions) {
if (options().importAssertions()) {
if (next == TokenKind::Comma) {
tokenStream.consumeKnownToken(TokenKind::Comma,
TokenStream::SlashIsRegExp);

View File

@@ -28,7 +28,7 @@ FRAGMENT(asmjs, segfault) {
JS::CompileOptions opts(cx);
opts.setFileAndLine(__FILE__, line0 + 1);
opts.asmJSOption = JS::AsmJSOption::Enabled;
opts.setAsmJSOption(JS::AsmJSOption::Enabled);
JS::SourceText<mozilla::Utf8Unit> srcBuf;
JS::Rooted<JS::Value> rval(cx);

View File

@@ -2302,15 +2302,12 @@ void JS::TransitiveCompileOptions::copyPODTransitiveOptions(
mutedErrors_ = rhs.mutedErrors_;
forceStrictMode_ = rhs.forceStrictMode_;
alwaysUseFdlibm_ = rhs.alwaysUseFdlibm_;
sourcePragmas_ = rhs.sourcePragmas_;
skipFilenameValidation_ = rhs.skipFilenameValidation_;
hideScriptFromDebugger_ = rhs.hideScriptFromDebugger_;
deferDebugMetadata_ = rhs.deferDebugMetadata_;
eagerDelazificationStrategy_ = rhs.eagerDelazificationStrategy_;
selfHostingMode = rhs.selfHostingMode;
asmJSOption = rhs.asmJSOption;
throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption;
forceAsync = rhs.forceAsync;
discardSource = rhs.discardSource;
sourceIsLazy = rhs.sourceIsLazy;
@@ -2318,13 +2315,14 @@ void JS::TransitiveCompileOptions::copyPODTransitiveOptions(
nonSyntacticScope = rhs.nonSyntacticScope;
topLevelAwait = rhs.topLevelAwait;
importAssertions = rhs.importAssertions;
borrowBuffer = rhs.borrowBuffer;
usePinnedBytecode = rhs.usePinnedBytecode;
allocateInstantiationStorage = rhs.allocateInstantiationStorage;
deoptimizeModuleGlobalVars = rhs.deoptimizeModuleGlobalVars;
prefableOptions_ = rhs.prefableOptions_;
introductionType = rhs.introductionType;
introductionLineno = rhs.introductionLineno;
introductionOffset = rhs.introductionOffset;
@@ -2409,23 +2407,16 @@ bool JS::OwningCompileOptions::copy(JS::FrontendContext* fc,
}
JS::CompileOptions::CompileOptions(JSContext* cx) : ReadOnlyCompileOptions() {
if (!js::IsAsmJSCompilationAvailable(cx)) {
// Distinguishing the cases is just for error reporting.
asmJSOption = !cx->options().asmJS()
? AsmJSOption::DisabledByAsmJSPref
: AsmJSOption::DisabledByNoWasmCompiler;
} else if (cx->realm() && (cx->realm()->debuggerObservesWasm() ||
cx->realm()->debuggerObservesAsmJS())) {
asmJSOption = AsmJSOption::DisabledByDebugger;
} else {
asmJSOption = AsmJSOption::Enabled;
prefableOptions_ = cx->options().compileOptions();
if (cx->options().asmJSOption() == AsmJSOption::Enabled) {
if (!js::IsAsmJSCompilationAvailable(cx)) {
prefableOptions_.setAsmJSOption(AsmJSOption::DisabledByNoWasmCompiler);
} else if (cx->realm() && (cx->realm()->debuggerObservesWasm() ||
cx->realm()->debuggerObservesAsmJS())) {
prefableOptions_.setAsmJSOption(AsmJSOption::DisabledByDebugger);
}
}
throwOnAsmJSValidationFailureOption =
cx->options().throwOnAsmJSValidationFailure();
importAssertions = cx->options().importAssertions();
sourcePragmas_ = cx->options().sourcePragmas();
// Certain modes of operation force strict-mode in general.
forceStrictMode_ = cx->options().strictMode();

View File

@@ -1955,7 +1955,7 @@ class MOZ_STACK_CLASS ModuleValidator : public ModuleValidatorShared {
auto& ts = tokenStream();
ErrorMetadata metadata;
if (ts.computeErrorMetadata(&metadata, AsVariant(offset))) {
if (ts.anyCharsAccess().options().throwOnAsmJSValidationFailureOption) {
if (ts.anyCharsAccess().options().throwOnAsmJSValidationFailure()) {
ReportCompileErrorLatin1(fc_, std::move(metadata), nullptr,
JSMSG_USE_ASM_TYPE_FAIL, &args);
} else {
@@ -7010,7 +7010,7 @@ static bool HandleInstantiationFailure(JSContext* cx, CallArgs args,
options.setMutedErrors(source->mutedErrors())
.setFile(source->filename())
.setNoScriptRval(false);
options.asmJSOption = AsmJSOption::DisabledByLinker;
options.setAsmJSOption(AsmJSOption::DisabledByLinker);
// The exported function inherits an implicit strict context if the module
// also inherited it somehow.
@@ -7090,7 +7090,7 @@ static bool SuccessfulValidation(frontend::ParserBase& parser,
}
static bool TypeFailureWarning(frontend::ParserBase& parser, const char* str) {
if (parser.options().throwOnAsmJSValidationFailureOption) {
if (parser.options().throwOnAsmJSValidationFailure()) {
parser.errorNoOffset(JSMSG_USE_ASM_TYPE_FAIL, str ? str : "");
return false;
}
@@ -7109,7 +7109,7 @@ static bool IsAsmJSCompilerAvailable(JSContext* cx) {
}
static bool EstablishPreconditions(frontend::ParserBase& parser) {
switch (parser.options().asmJSOption) {
switch (parser.options().asmJSOption()) {
case AsmJSOption::DisabledByAsmJSPref:
return TypeFailureWarning(
parser, "Asm.js optimizer disabled by 'asmjs' runtime option");