Bug 1559275 - Add TransistiveCompileOptions::forceFullParse. r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Wed, 19 Jun 2019 01:43:06 +0000
changeset 479172 960c9f0926e9e5a557e09d1f017e8d5996a4237d
parent 479171 28a43f9cc6b1db6a5e8dea7b71f712f834b7be5f
child 479173 12a473968ffd1f643938c0e5710d257c55cc9847
push id36172
push userrgurzau@mozilla.com
push dateWed, 19 Jun 2019 09:55:37 +0000
treeherdermozilla-central@8bce401b8833 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1559275
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1559275 - Add TransistiveCompileOptions::forceFullParse. r=jandem Check VM and Realm options that may disable syntax parsing up front in the CompileOptions constructor. This is needed to make the frontend closer to a pure-function. Differential Revision: https://phabricator.services.mozilla.com/D35214
js/public/CompileOptions.h
js/src/frontend/BytecodeCompiler.cpp
js/src/jsapi.cpp
--- a/js/public/CompileOptions.h
+++ b/js/public/CompileOptions.h
@@ -93,16 +93,21 @@ class JS_PUBLIC_API TransitiveCompileOpt
    * To counter this attack, HTML5 specifies that script errors should be
    * sanitized ("muted") when the script is not same-origin with the global
    * for which it is loaded. Callers should set this flag for cross-origin
    * scripts, and it will be propagated appropriately to child scripts and
    * passed back in JSErrorReports.
    */
   bool mutedErrors_ = false;
 
+  // Either the Realm configuration or specialized VM operating modes may
+  // disallow syntax-parse (and the LazyScript data type) altogether. These
+  // conditions are checked in the CompileOptions constructor.
+  bool forceFullParse_ = false;
+
   const char* filename_ = nullptr;
   const char* introducerFilename_ = nullptr;
   const char16_t* sourceMapURL_ = nullptr;
 
  public:
   // POD options.
   bool selfHostingMode = false;
   bool canLazilyParse = true;
@@ -135,16 +140,17 @@ class JS_PUBLIC_API TransitiveCompileOpt
   // Set all POD options (those not requiring reference counts, copies,
   // rooting, or other hand-holding) to their values in |rhs|.
   void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
 
  public:
   // Read-only accessors for non-POD options. The proper way to set these
   // depends on the derived type.
   bool mutedErrors() const { return mutedErrors_; }
+  bool forceFullParse() const { return forceFullParse_; }
   const char* filename() const { return filename_; }
   const char* introducerFilename() const { return introducerFilename_; }
   const char16_t* sourceMapURL() const { return sourceMapURL_; }
   virtual JSObject* element() const = 0;
   virtual JSString* elementAttributeName() const = 0;
   virtual JSScript* introductionScript() const = 0;
 
   // For some compilations the spec requires the ScriptOrModule field of the
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -397,24 +397,18 @@ bool BytecodeCompiler::createScriptSourc
     return false;
   }
 
   scriptSource = sourceObject->source();
   return true;
 }
 
 bool BytecodeCompiler::canLazilyParse() const {
-  return options.canLazilyParse &&
-         !cx->realm()->behaviors().disableLazyParsing() &&
-         !options.discardSource && !options.sourceIsLazy &&
-         !coverage::IsLCovEnabled() &&
-         // Disabled during record/replay. The replay debugger requires
-         // scripts to be constructed in a consistent order, which might not
-         // happen with lazy parsing.
-         !mozilla::recordreplay::IsRecordingOrReplaying();
+  return options.canLazilyParse && !options.discardSource &&
+         !options.sourceIsLazy && !options.forceFullParse();
 }
 
 template <typename Unit>
 bool frontend::SourceAwareCompiler<Unit>::createSourceAndParser(
     BytecodeCompiler& info, ParseGoal goal,
     const Maybe<uint32_t>& parameterListEnd /* = Nothing() */) {
   if (!info.createScriptSource(parameterListEnd)) {
     return false;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3455,16 +3455,17 @@ extern JS_PUBLIC_API JSFunction* JS_Defi
   CHECK_THREAD(cx);
   cx->check(obj, id);
   return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 void JS::TransitiveCompileOptions::copyPODTransitiveOptions(
     const TransitiveCompileOptions& rhs) {
   mutedErrors_ = rhs.mutedErrors_;
+  forceFullParse_ = rhs.forceFullParse_;
   selfHostingMode = rhs.selfHostingMode;
   canLazilyParse = rhs.canLazilyParse;
   strictOption = rhs.strictOption;
   extraWarningsOption = rhs.extraWarningsOption;
   werrorOption = rhs.werrorOption;
   asmJSOption = rhs.asmJSOption;
   throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption;
   forceAsync = rhs.forceAsync;
@@ -3569,16 +3570,23 @@ JS::CompileOptions::CompileOptions(JSCon
     asmJSOption = AsmJSOption::DisabledByDebugger;
   } else {
     asmJSOption = AsmJSOption::Enabled;
   }
   throwOnAsmJSValidationFailureOption =
       cx->options().throwOnAsmJSValidationFailure();
   bigIntEnabledOption = cx->realm()->creationOptions().getBigIntEnabled();
   fieldsEnabledOption = cx->realm()->creationOptions().getFieldsEnabled();
+
+  // Certain modes of operation disallow syntax parsing in general. The replay
+  // debugger requires scripts to be constructed in a consistent order, which
+  // might not happen with lazy parsing.
+  forceFullParse_ = cx->realm()->behaviors().disableLazyParsing() ||
+                    coverage::IsLCovEnabled() ||
+                    mozilla::recordreplay::IsRecordingOrReplaying();
 }
 
 CompileOptions& CompileOptions::setIntroductionInfoToCaller(
     JSContext* cx, const char* introductionType) {
   RootedScript maybeScript(cx);
   const char* filename;
   unsigned lineno;
   uint32_t pcOffset;