Bug 1619445 - Split strict flag into two distinct flags for input and parse. r=tcampbell
authorcaroline <ccullen@mozilla.com>
Thu, 12 Mar 2020 22:48:33 +0000
changeset 518506 651f6b4c7d7414fc73ea15080e8874bddc5c122b
parent 518505 1a37a40dc640d4b109547a6e8fdae66bdc4030c5
child 518507 2b848bc7334e633db0592c45da598e43a48d9975
push id37211
push usermalexandru@mozilla.com
push dateFri, 13 Mar 2020 09:53:22 +0000
treeherdermozilla-central@b5c4cdbb59c9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1619445
milestone76.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 1619445 - Split strict flag into two distinct flags for input and parse. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D65275
js/src/frontend/Parser.cpp
js/src/frontend/Stencil.h
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/SharedStencil.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1682,17 +1682,17 @@ bool PerHandlerParser<SyntaxParseHandler
   }
 
   FunctionBox* funbox = pc_->functionBox();
   funbox->synchronizeArgCount();
 
   LazyScriptCreationData data(cx_);
   if (!data.init(cx_, pc_->closedOverBindingsForLazy(),
                  std::move(pc_->innerFunctionIndexesForLazy),
-                 pc_->sc()->strict())) {
+                 options().forceStrictMode(), pc_->sc()->strict())) {
     return false;
   }
 
   funbox->functionCreationData().get().lazyScriptData =
       mozilla::Some(std::move(data));
   return true;
 }
 
@@ -1745,16 +1745,19 @@ bool LazyScriptCreationData::create(JSCo
                                         sourceObject, closedOverBindings,
                                         innerFunctionIndexes, funbox->extent);
   if (!lazy) {
     return false;
   }
 
   // Flags that need to be copied into the JSScript when we do the full
   // parse.
+  if (forceStrict) {
+    lazy->setForceStrict();
+  }
   if (strict) {
     lazy->setStrict();
   }
   lazy->setGeneratorKind(funbox->generatorKind());
   lazy->setAsyncKind(funbox->asyncKind());
   if (funbox->hasRest()) {
     lazy->setHasRest();
   }
--- a/js/src/frontend/Stencil.h
+++ b/js/src/frontend/Stencil.h
@@ -73,24 +73,27 @@ class FunctionIndex : public TypedIndex<
 };
 
 // Data used to instantiate the lazy script before script emission.
 struct LazyScriptCreationData {
   frontend::AtomVector closedOverBindings;
 
   // This is traced by the functionbox which owns this LazyScriptCreationData
   Vector<FunctionIndex> innerFunctionIndexes;
+  bool forceStrict = false;
   bool strict = false;
 
   mozilla::Maybe<FieldInitializers> fieldInitializers;
 
   explicit LazyScriptCreationData(JSContext* cx) : innerFunctionIndexes(cx) {}
 
   bool init(JSContext* cx, const frontend::AtomVector& COB,
-            Vector<FunctionIndex>&& innerIndexes, bool isStrict) {
+            Vector<FunctionIndex>&& innerIndexes, bool isForceStrict,
+            bool isStrict) {
+    forceStrict = isForceStrict;
     strict = isStrict;
     innerFunctionIndexes = std::move(innerIndexes);
 
     if (!closedOverBindings.appendAll(COB)) {
       ReportOutOfMemory(cx);  // closedOverBindings uses SystemAllocPolicy.
       return false;
     }
     return true;
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4318,16 +4318,19 @@ JSScript* JSScript::Create(JSContext* cx
   RootedScriptSourceObject sourceObject(cx, lazy->sourceObject());
   RootedObject fun(cx, lazy->function());
   RootedScript script(cx, JSScript::New(cx, fun, sourceObject, lazy->extent()));
   if (!script) {
     return nullptr;
   }
 
   // Propagate flags.
+  if (lazy->forceStrict()) {
+    script->setForceStrict();
+  }
   if (lazy->isLikelyConstructorWrapper()) {
     script->setIsLikelyConstructorWrapper();
   }
   if (lazy->hasBeenCloned()) {
     script->setHasBeenCloned();
   }
 
   return script;
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2208,16 +2208,17 @@ setterLevel:                            
 #define MUTABLE_FLAG_GETTER(lowerName, name) \
   FLAG_GETTER(MutableFlags, name, lowerName)
 #define MUTABLE_FLAG_GETTER_SETTER(lowerName, name) \
   FLAG_GETTER_SETTER(MutableFlags, name, public, lowerName, name)
 
   IMMUTABLE_FLAG_GETTER(noScriptRval, NoScriptRval)
   IMMUTABLE_FLAG_GETTER(selfHosted, SelfHosted)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(treatAsRunOnce, TreatAsRunOnce)
+  IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(forceStrict, ForceStrict)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(strict, Strict)
   IMMUTABLE_FLAG_GETTER(hasNonSyntacticScope, HasNonSyntacticScope)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(bindingsAccessedDynamically,
                                       BindingsAccessedDynamically)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(funHasExtensibleScope,
                                       FunHasExtensibleScope)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasCallSiteObj, HasCallSiteObj)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasModuleGoal, HasModuleGoal)
--- a/js/src/vm/SharedStencil.h
+++ b/js/src/vm/SharedStencil.h
@@ -58,90 +58,93 @@ enum class ImmutableScriptFlagsEnum : ui
 
   // See Parser::selfHostingMode.
   SelfHosted = 1 << 1,
 
   // Script is a lambda to treat as running once or a global or eval script
   // that will only run once.  Which one it is can be disambiguated by
   // checking whether function() is null.
   TreatAsRunOnce = 1 << 2,
+
+  // Code was forced into strict mode using CompileOptions.
+  ForceStrict = 1 << 3,
   // ----
 
   // Code is in strict mode.
-  Strict = 1 << 3,
+  Strict = 1 << 4,
 
   // True if the script has a non-syntactic scope on its dynamic scope chain.
   // That is, there are objects about which we know nothing between the
   // outermost syntactic scope and the global.
-  HasNonSyntacticScope = 1 << 4,
+  HasNonSyntacticScope = 1 << 5,
 
   // See FunctionBox.
-  BindingsAccessedDynamically = 1 << 5,
-  FunHasExtensibleScope = 1 << 6,
+  BindingsAccessedDynamically = 1 << 6,
+  FunHasExtensibleScope = 1 << 7,
 
   // Bytecode contains JSOp::CallSiteObj
   // (We don't relazify functions with template strings, due to observability)
-  HasCallSiteObj = 1 << 7,
+  HasCallSiteObj = 1 << 8,
 
   // Script is parsed with a top-level goal of Module. This may be a top-level
   // or an inner-function script.
-  HasModuleGoal = 1 << 8,
+  HasModuleGoal = 1 << 9,
 
-  FunctionHasThisBinding = 1 << 9,
-  FunctionHasExtraBodyVarScope = 1 << 10,
+  FunctionHasThisBinding = 1 << 10,
+  FunctionHasExtraBodyVarScope = 1 << 11,
 
   // Whether the arguments object for this script, if it needs one, should be
   // mapped (alias formal parameters).
-  HasMappedArgsObj = 1 << 11,
+  HasMappedArgsObj = 1 << 12,
 
   // Script contains inner functions. Used to check if we can relazify the
   // script.
-  HasInnerFunctions = 1 << 12,
+  HasInnerFunctions = 1 << 13,
 
-  NeedsHomeObject = 1 << 13,
+  NeedsHomeObject = 1 << 14,
 
-  IsDerivedClassConstructor = 1 << 14,
+  IsDerivedClassConstructor = 1 << 15,
 
   // 'this', 'arguments' and f.apply() are used. This is likely to be a
   // wrapper.
-  IsLikelyConstructorWrapper = 1 << 15,
+  IsLikelyConstructorWrapper = 1 << 16,
 
   // Set if this function is a generator function or async generator.
-  IsGenerator = 1 << 16,
+  IsGenerator = 1 << 17,
 
   // Set if this function is an async function or async generator.
-  IsAsync = 1 << 17,
+  IsAsync = 1 << 18,
 
   // Set if this function has a rest parameter.
-  HasRest = 1 << 18,
+  HasRest = 1 << 19,
 
   // See comments below.
-  ArgumentsHasVarBinding = 1 << 19,
+  ArgumentsHasVarBinding = 1 << 20,
 
   // Script came from eval().
-  IsForEval = 1 << 20,
+  IsForEval = 1 << 21,
 
   // Whether this is a top-level module script.
-  IsModule = 1 << 21,
+  IsModule = 1 << 22,
 
   // Whether this function needs a call object or named lambda environment.
-  NeedsFunctionEnvironmentObjects = 1 << 22,
+  NeedsFunctionEnvironmentObjects = 1 << 23,
 
   // Whether the Parser declared 'arguments'.
-  ShouldDeclareArguments = 1 << 23,
+  ShouldDeclareArguments = 1 << 24,
 
   // Script is for function.
-  IsFunction = 1 << 24,
+  IsFunction = 1 << 25,
 
   // Whether this script contains a direct eval statement.
-  HasDirectEval = 1 << 25,
+  HasDirectEval = 1 << 26,
 
   // Whether this BaseScript is a LazyScript. This flag will be removed after
   // LazyScript and JSScript are merged in Bug 1529456.
-  IsLazyScript = 1 << 26,
+  IsLazyScript = 1 << 27,
 };
 
 class ImmutableScriptFlags : public ScriptFlagBase<ImmutableScriptFlagsEnum> {
   // Immutable flags should not be modified after the JSScript that contains
   // them has been initialized. These flags should likely be preserved when
   // serializing (XDR) or copying (CopyScript) the script. This is only public
   // for the JITs.
   //
@@ -160,27 +163,31 @@ class ImmutableScriptFlags : public Scri
   void operator=(uint32_t flag) { flags_ = flag; }
 
   static ImmutableScriptFlags fromCompileOptions(
       const JS::ReadOnlyCompileOptions& options) {
     ImmutableScriptFlags isf;
     isf.setFlag(ImmutableScriptFlagsEnum::NoScriptRval, options.noScriptRval);
     isf.setFlag(ImmutableScriptFlagsEnum::SelfHosted, options.selfHostingMode);
     isf.setFlag(ImmutableScriptFlagsEnum::TreatAsRunOnce, options.isRunOnce);
+    isf.setFlag(ImmutableScriptFlagsEnum::ForceStrict,
+                options.forceStrictMode());
     return isf;
   };
 
   static ImmutableScriptFlags fromCompileOptions(
       const JS::TransitiveCompileOptions& options) {
     ImmutableScriptFlags isf;
     isf.setFlag(ImmutableScriptFlagsEnum::NoScriptRval,
                 /* noScriptRval (non-transitive compile option) = */ false);
     isf.setFlag(ImmutableScriptFlagsEnum::SelfHosted, options.selfHostingMode);
     isf.setFlag(ImmutableScriptFlagsEnum::TreatAsRunOnce,
                 /* isRunOnce (non-transitive compile option) = */ false);
+    isf.setFlag(ImmutableScriptFlagsEnum::ForceStrict,
+                options.forceStrictMode());
     return isf;
   };
 };
 
 enum class MutableScriptFlagsEnum : uint32_t {
   // Number of times the |warmUpCount| was forcibly discarded. The counter is
   // reset when a script is successfully jit-compiled.
   WarmupResets_MASK = 0xFF,