Bug 1519809 - Replace IsActiveEval/IsCachedEval flags on JSScript with a single IsForEval flag. r=luke
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 14 Jan 2019 15:56:15 +0000
changeset 513886 ffef7bf31900e6bd360017e414338b454bfffa41
parent 513885 89ff2ff6f6f4b1b564df970e519d85323bc83440
child 513887 ae52a3250ebf124caed547e09671af3f29928d20
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1519809
milestone66.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 1519809 - Replace IsActiveEval/IsCachedEval flags on JSScript with a single IsForEval flag. r=luke Differential Revision: https://phabricator.services.mozilla.com/D16449
js/src/builtin/Eval.cpp
js/src/jsapi.cpp
js/src/vm/Debugger.cpp
js/src/vm/Interpreter.cpp
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/Stack-inl.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -100,25 +100,23 @@ class EvalScriptGuard {
     lookupStr_ = str;
     lookup_.str = str;
     lookup_.callerScript = callerScript;
     lookup_.pc = pc;
     p_.emplace(cx_, cx_->caches().evalCache, lookup_);
     if (*p_) {
       script_ = (*p_)->script;
       p_->remove(cx_, cx_->caches().evalCache, lookup_);
-      script_->uncacheForEval();
     }
   }
 
   void setNewScript(JSScript* script) {
     // JSScript::initFromEmitter has already called js_CallNewScriptHook.
     MOZ_ASSERT(!script_ && script);
     script_ = script;
-    script_->setActiveEval();
   }
 
   bool foundScript() { return !!script_; }
 
   HandleScript script() {
     MOZ_ASSERT(script_);
     return script_;
   }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3597,17 +3597,16 @@ JS_PUBLIC_API JSScript* JS::FinishOffThr
     JSContext* cx, JS::OffThreadToken* token) {
   MOZ_ASSERT(cx);
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
   return HelperThreadState().finishBinASTDecodeTask(cx, token);
 }
 #endif
 
 JS_PUBLIC_API JSObject* JS_GetGlobalFromScript(JSScript* script) {
-  MOZ_ASSERT(!script->isCachedEval());
   return &script->global();
 }
 
 JS_PUBLIC_API const char* JS_GetScriptFilename(JSScript* script) {
   // This is called from ThreadStackHelper which can be called from another
   // thread or inside a signal hander, so we need to be careful in case a
   // copmacting GC is currently moving things around.
   return script->maybeForwardedFilename();
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8538,18 +8538,16 @@ static bool EvaluateInEnv(JSContext* cx,
       return false;
     }
 
     frontend::EvalScriptInfo info(cx, options, env, scope);
     script = frontend::CompileEvalScript(info, srcBuf);
     if (!script) {
       return false;
     }
-
-    script->setActiveEval();
   } else {
     // Do not consider executeInGlobal{WithBindings} as an eval, but instead
     // as executing a series of statements at the global level. This is to
     // circumvent the fresh lexical scope that all eval have, so that the
     // users of executeInGlobal, like the web console, may add new bindings to
     // the global scope.
     frontend::GlobalScriptInfo info(cx, options, scopeKind);
     script = frontend::CompileGlobalScript(info, srcBuf);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4616,18 +4616,18 @@ bool js::DefFunOperation(JSContext* cx, 
   }
 
   RootedValue rval(cx, ObjectValue(*fun));
 
   /*
    * ECMA requires functions defined when entering Eval code to be
    * impermanent.
    */
-  unsigned attrs = script->isActiveEval() ? JSPROP_ENUMERATE
-                                          : JSPROP_ENUMERATE | JSPROP_PERMANENT;
+  unsigned attrs = script->isForEval() ? JSPROP_ENUMERATE
+                                       : JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
   /* Steps 5d, 5f. */
   if (!prop || pobj != parent) {
     if (!DefineDataProperty(cx, parent, name, rval, attrs)) {
       return false;
     }
 
     if (parent->is<GlobalObject>()) {
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3425,16 +3425,17 @@ static void InitAtomMap(frontend::AtomIn
   }
 
   script->setFlag(ImmutableFlags::Strict, bce->sc->strict());
   script->setFlag(ImmutableFlags::ExplicitUseStrict,
                   bce->sc->hasExplicitUseStrict());
   script->setFlag(ImmutableFlags::BindingsAccessedDynamically,
                   bce->sc->bindingsAccessedDynamically());
   script->setFlag(ImmutableFlags::HasSingletons, bce->hasSingletons);
+  script->setFlag(ImmutableFlags::IsForEval, bce->sc->isEvalContext());
 
   script->nfixed_ = bce->maxFixedSlots;
   script->nslots_ = nslots;
   script->bodyScopeIndex_ = bce->bodyScopeIndex;
   script->setFlag(ImmutableFlags::HasNonSyntacticScope,
                   bce->outermostScope()->hasOnChain(ScopeKind::NonSyntactic));
 
   // There shouldn't be any fallible operation after initFromFunctionBox,
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1686,16 +1686,19 @@ class JSScript : public js::gc::TenuredC
     // Set if this function is an async function or async generator.
     IsAsync = 1 << 19,
 
     // Set if this function has a rest parameter.
     HasRest = 1 << 20,
 
     // See comments below.
     ArgsHasVarBinding = 1 << 21,
+
+    // Script came from eval().
+    IsForEval = 1 << 22,
   };
   // Note: don't make this a bitfield! It makes it hard to read these flags
   // from JIT code.
   uint32_t immutableFlags_ = 0;
 
   // Mutable flags typically store information about runtime or deoptimization
   // behavior of this script. This is only public for the JITs.
  public:
@@ -1704,21 +1707,17 @@ class JSScript : public js::gc::TenuredC
     WarnedAboutUndefinedProp = 1 << 0,
 
     // If treatAsRunOnce, whether script has executed.
     HasRunOnce = 1 << 1,
 
     // Script has been reused for a clone.
     HasBeenCloned = 1 << 2,
 
-    // Script came from eval(), and is still active.
-    IsActiveEval = 1 << 3,
-
-    // Script came from eval(), and is in eval cache.
-    IsCachedEval = 1 << 4,
+    // (1 << 3) and (1 << 4) are unused.
 
     // Script has an entry in Realm::scriptCountsMap.
     HasScriptCounts = 1 << 5,
 
     // Script has an entry in Realm::debugScriptMap.
     HasDebugScript = 1 << 6,
 
     // Freeze constraints for stack type sets have been generated.
@@ -2033,39 +2032,24 @@ class JSScript : public js::gc::TenuredC
   }
   bool hasRunOnce() const { return hasFlag(MutableFlags::HasRunOnce); }
   bool hasBeenCloned() const { return hasFlag(MutableFlags::HasBeenCloned); }
 
   void setTreatAsRunOnce() { setFlag(ImmutableFlags::TreatAsRunOnce); }
   void setHasRunOnce() { setFlag(MutableFlags::HasRunOnce); }
   void setHasBeenCloned() { setFlag(MutableFlags::HasBeenCloned); }
 
-  bool isActiveEval() const { return hasFlag(MutableFlags::IsActiveEval); }
-  bool isCachedEval() const { return hasFlag(MutableFlags::IsCachedEval); }
-
   void cacheForEval() {
-    MOZ_ASSERT(isActiveEval());
-    MOZ_ASSERT(!isCachedEval());
-    clearFlag(MutableFlags::IsActiveEval);
-    setFlag(MutableFlags::IsCachedEval);
+    MOZ_ASSERT(isForEval());
     // IsEvalCacheCandidate will make sure that there's nothing in this
     // script that would prevent reexecution even if isRunOnce is
     // true.  So just pretend like we never ran this script.
     clearFlag(MutableFlags::HasRunOnce);
   }
 
-  void uncacheForEval() {
-    MOZ_ASSERT(isCachedEval());
-    MOZ_ASSERT(!isActiveEval());
-    clearFlag(MutableFlags::IsCachedEval);
-    setFlag(MutableFlags::IsActiveEval);
-  }
-
-  void setActiveEval() { setFlag(MutableFlags::IsActiveEval); }
-
   bool isLikelyConstructorWrapper() const {
     return hasFlag(ImmutableFlags::IsLikelyConstructorWrapper);
   }
   void setLikelyConstructorWrapper() {
     setFlag(ImmutableFlags::IsLikelyConstructorWrapper);
   }
 
   bool failedBoundsCheck() const {
@@ -2363,19 +2347,19 @@ class JSScript : public js::gc::TenuredC
   // Unique Method ID passed to the VTune profiler. Allows attribution of
   // different jitcode to the same source script.
   uint32_t vtuneMethodID();
 #endif
 
  public:
   /* Return whether this script was compiled for 'eval' */
   bool isForEval() const {
-    MOZ_ASSERT_IF(isCachedEval() || isActiveEval(),
-                  bodyScope()->is<js::EvalScope>());
-    return isCachedEval() || isActiveEval();
+    bool forEval = hasFlag(ImmutableFlags::IsForEval);
+    MOZ_ASSERT_IF(forEval, bodyScope()->is<js::EvalScope>());
+    return forEval;
   }
 
   /* Return whether this is a 'direct eval' script in a function scope. */
   bool isDirectEvalInFunction() const {
     if (!isForEval()) {
       return false;
     }
     return bodyScope()->hasOnChain(js::ScopeKind::Function);
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -919,17 +919,16 @@ InterpreterActivation::InterpreterActiva
       opMask_(0)
 #ifdef DEBUG
       ,
       oldFrameCount_(cx->interpreterStack().frameCount_)
 #endif
 {
   regs_.prepareToRun(*entryFrame, state.script());
   MOZ_ASSERT(regs_.pc == state.script()->code());
-  MOZ_ASSERT_IF(entryFrame_->isEvalFrame(), state.script()->isActiveEval());
 }
 
 InterpreterActivation::~InterpreterActivation() {
   // Pop all inline frames.
   while (regs_.fp() != entryFrame_) {
     popInlineFrame(regs_.fp());
   }