Bug 1593354 - Add BaseScript::IsFunction flag. r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Mon, 04 Nov 2019 07:56:09 +0000
changeset 500452 821b104d357b899ba03415a82066e96db6aa269b
parent 500451 0bc5888755fd271b4053101ce0c58765d3b4e071
child 500453 b3a76c2b11b343f6170ccb599d1af7d8cfd06858
push id114164
push useraiakab@mozilla.com
push dateTue, 05 Nov 2019 10:06:15 +0000
treeherdermozilla-inbound@4d585c7edc76 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1593354
milestone72.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 1593354 - Add BaseScript::IsFunction flag. r=jandem Set this flag for scripts that are for functions. This is equivalent to checking the kind of the bodyScope() but is safe to call in GC contexts such as finalization. Also use an isFunction() accessor instead of checking if JSScript::function() is nullptr throughout the codebase. Similarly, cleanup similar uses of JSScript::module(). Differential Revision: https://phabricator.services.mozilla.com/D51472
js/src/jit/BaselineFrame.h
js/src/jit/BytecodeAnalysis.cpp
js/src/jit/JitFrames.h
js/src/jit/MCallOptimize.cpp
js/src/jit/RematerializedFrame.h
js/src/vm/BytecodeUtil.cpp
js/src/vm/GeckoProfiler.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/Interpreter.cpp
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -334,17 +334,17 @@ class BaselineFrame {
 
   bool isDebuggee() const { return flags_ & DEBUGGEE; }
   void setIsDebuggee() { flags_ |= DEBUGGEE; }
   inline void unsetIsDebuggee();
 
   void trace(JSTracer* trc, const JSJitFrameIter& frame);
 
   bool isGlobalFrame() const { return script()->isGlobalCode(); }
-  bool isModuleFrame() const { return script()->module(); }
+  bool isModuleFrame() const { return script()->isModule(); }
   bool isEvalFrame() const { return script()->isForEval(); }
   bool isStrictEvalFrame() const { return isEvalFrame() && script()->strict(); }
   bool isNonStrictEvalFrame() const {
     return isEvalFrame() && !script()->strict();
   }
   bool isNonGlobalEvalFrame() const;
   bool isNonStrictDirectEvalFrame() const {
     return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
--- a/js/src/jit/BytecodeAnalysis.cpp
+++ b/js/src/jit/BytecodeAnalysis.cpp
@@ -212,17 +212,17 @@ bool BytecodeAnalysis::init(TempAllocato
 
   return true;
 }
 
 IonBytecodeInfo js::jit::AnalyzeBytecodeForIon(JSContext* cx,
                                                JSScript* script) {
   IonBytecodeInfo result;
 
-  if (script->module() || script->initialEnvironmentShape() ||
+  if (script->isModule() || script->initialEnvironmentShape() ||
       (script->function() &&
        script->function()->needsSomeEnvironmentObject())) {
     result.usesEnvironmentChain = true;
   }
 
   jsbytecode const* pcEnd = script->codeEnd();
   for (jsbytecode* pc = script->code(); pc < pcEnd; pc = GetNextPc(pc)) {
     JSOp op = JSOp(*pc);
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -55,17 +55,17 @@ static inline JSFunction* CalleeTokenToF
   return (JSFunction*)(uintptr_t(token) & CalleeTokenMask);
 }
 static inline JSScript* CalleeTokenToScript(CalleeToken token) {
   MOZ_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script);
   return (JSScript*)(uintptr_t(token) & CalleeTokenMask);
 }
 static inline bool CalleeTokenIsModuleScript(CalleeToken token) {
   CalleeTokenTag tag = GetCalleeTokenTag(token);
-  return tag == CalleeToken_Script && CalleeTokenToScript(token)->module();
+  return tag == CalleeToken_Script && CalleeTokenToScript(token)->isModule();
 }
 
 static inline JSScript* ScriptFromCalleeToken(CalleeToken token) {
   switch (GetCalleeTokenTag(token)) {
     case CalleeToken_Script:
       return CalleeTokenToScript(token);
     case CalleeToken_Function:
     case CalleeToken_FunctionConstructing:
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -4127,17 +4127,17 @@ void IonBuilder::atomicsCheckBounds(Call
   *elements = nullptr;
   addTypedArrayLengthAndData(obj, DoBoundsCheck, index, &length, elements);
 }
 
 IonBuilder::InliningResult IonBuilder::inlineIsConstructing(
     CallInfo& callInfo) {
   MOZ_ASSERT(!callInfo.constructing());
   MOZ_ASSERT(callInfo.argc() == 0);
-  MOZ_ASSERT(script()->function(),
+  MOZ_ASSERT(script()->isFunction(),
              "isConstructing() should only be called in function scripts");
 
   if (getInlineReturnType() != MIRType::Boolean) {
     return InliningStatus_NotInlined;
   }
 
   callInfo.setImplicitlyUsedUnchecked();
 
--- a/js/src/jit/RematerializedFrame.h
+++ b/js/src/jit/RematerializedFrame.h
@@ -134,19 +134,19 @@ class RematerializedFrame {
 
   bool hasArgsObj() const { return !!argsObj_; }
   ArgumentsObject& argsObj() const {
     MOZ_ASSERT(hasArgsObj());
     MOZ_ASSERT(script()->needsArgsObj());
     return *argsObj_;
   }
 
-  bool isFunctionFrame() const { return !!script_->function(); }
+  bool isFunctionFrame() const { return script_->isFunction(); }
   bool isGlobalFrame() const { return script_->isGlobalCode(); }
-  bool isModuleFrame() const { return script_->module(); }
+  bool isModuleFrame() const { return script_->isModule(); }
 
   JSScript* script() const { return script_; }
   JSFunction* callee() const {
     MOZ_ASSERT(isFunctionFrame());
     MOZ_ASSERT(callee_);
     return callee_;
   }
   Value calleev() const { return ObjectValue(*callee()); }
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -2186,17 +2186,17 @@ bool ExpressionDecompiler::quote(JSStrin
   return QuoteString(&sprinter, s, quote);
 }
 
 JSAtom* ExpressionDecompiler::loadAtom(jsbytecode* pc) {
   return script->getAtom(pc);
 }
 
 JSAtom* ExpressionDecompiler::getArg(unsigned slot) {
-  MOZ_ASSERT(script->function());
+  MOZ_ASSERT(script->isFunction());
   MOZ_ASSERT(slot < script->numArgs());
 
   for (PositionalFormalParameterIter fi(script); fi; fi++) {
     if (fi.argumentSlot() == slot) {
       if (!fi.isDestructured()) {
         return fi.name();
       }
 
--- a/js/src/vm/GeckoProfiler.cpp
+++ b/js/src/vm/GeckoProfiler.cpp
@@ -295,17 +295,17 @@ UniqueChars GeckoProfilerRuntime::allocP
   constexpr size_t MaxFilenameLength = 200;
   const char* filenameStr = script->filename() ? script->filename() : "(null)";
   size_t filenameLength = js_strnlen(filenameStr, MaxFilenameLength);
 
   // Calculate line + column length.
   bool hasLineAndColumn = false;
   size_t lineAndColumnLength = 0;
   char lineAndColumnStr[30];
-  if (hasName || script->function() || script->isForEval()) {
+  if (hasName || script->isFunction() || script->isForEval()) {
     lineAndColumnLength = SprintfLiteral(lineAndColumnStr, "%u:%u",
                                          script->lineno(), script->column());
     hasLineAndColumn = true;
   }
 
   // Full profile string for scripts with functions is:
   //      FuncName (FileName:Lineno:Column)
   // Full profile string for scripts without functions is:
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -2084,17 +2084,17 @@ bool GlobalHelperThreadState::finishMult
 
 JSObject* GlobalHelperThreadState::finishModuleParseTask(
     JSContext* cx, JS::OffThreadToken* token) {
   JSScript* script = finishSingleParseTask(cx, ParseTaskKind::Module, token);
   if (!script) {
     return nullptr;
   }
 
-  MOZ_ASSERT(script->module());
+  MOZ_ASSERT(script->isModule());
 
   RootedModuleObject module(cx, script->module());
   module->fixEnvironmentsAfterRealmMerge();
   if (!ModuleObject::Freeze(cx, module)) {
     return nullptr;
   }
 
   return module;
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -815,17 +815,17 @@ bool js::ExecuteKernel(JSContext* cx, Ha
 
 bool js::Execute(JSContext* cx, HandleScript script, JSObject& envChainArg,
                  Value* rval) {
   /* The env chain is something we control, so we know it can't
      have any outer objects on it. */
   RootedObject envChain(cx, &envChainArg);
   MOZ_ASSERT(!IsWindowProxy(envChain));
 
-  if (script->module()) {
+  if (script->isModule()) {
     MOZ_RELEASE_ASSERT(
         envChain == script->module()->environment(),
         "Module scripts can only be executed in the module's environment");
   } else {
     MOZ_RELEASE_ASSERT(
         IsGlobalLexicalEnvironment(envChain) || script->hasNonSyntacticScope(),
         "Only global scripts with non-syntactic envs can be executed with "
         "interesting envchains");
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4095,16 +4095,17 @@ bool JSScript::fullyInitFromEmitter(JSCo
 
   // Initialize script flags from BytecodeEmitter
   script->setFlag(ImmutableFlags::Strict, bce->sc->strict());
   script->setFlag(ImmutableFlags::BindingsAccessedDynamically,
                   bce->sc->bindingsAccessedDynamically());
   script->setFlag(ImmutableFlags::HasCallSiteObj, bce->hasCallSiteObj);
   script->setFlag(ImmutableFlags::IsForEval, bce->sc->isEvalContext());
   script->setFlag(ImmutableFlags::IsModule, bce->sc->isModuleContext());
+  script->setFlag(ImmutableFlags::IsFunction, bce->sc->isFunctionBox());
   script->setFlag(ImmutableFlags::HasNonSyntacticScope,
                   bce->outermostScope()->hasOnChain(ScopeKind::NonSyntactic));
   script->setFlag(ImmutableFlags::NeedsFunctionEnvironmentObjects,
                   NeedsFunctionEnvironmentObjects(bce));
 
   // Initialize script flags from FunctionBox
   if (bce->sc->isFunctionBox()) {
     script->initFromFunctionBox(bce->sc->asFunctionBox());
@@ -4665,17 +4666,17 @@ bool PrivateScriptData::Clone(JSContext*
 JSScript* js::detail::CopyScript(JSContext* cx, HandleScript src,
                                  HandleObject functionOrGlobal,
                                  HandleScriptSourceObject sourceObject,
                                  MutableHandle<GCVector<Scope*>> scopes) {
   // We don't copy the HideScriptFromDebugger flag and it's not clear what
   // should happen if it's set on the source script.
   MOZ_ASSERT(!src->hideScriptFromDebugger());
 
-  if (src->treatAsRunOnce() && !src->function()) {
+  if (src->treatAsRunOnce() && !src->isFunction()) {
     JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
     return nullptr;
   }
 
   /* NB: Keep this in sync with XDRScript. */
 
   // Some embeddings are not careful to use ExposeObjectToActiveJS as needed.
   JS::AssertObjectIsNotGray(sourceObject);
@@ -5070,17 +5071,17 @@ void js::SetFrameArgumentsObject(JSConte
     if (IsOptimizedPlaceholderMagicValue(frame.unaliasedLocal(frameSlot))) {
       frame.unaliasedLocal(frameSlot) = ObjectValue(*argsobj);
     }
   }
 }
 
 /* static */
 void JSScript::argumentsOptimizationFailed(JSContext* cx, HandleScript script) {
-  MOZ_ASSERT(script->function());
+  MOZ_ASSERT(script->isFunction());
   MOZ_ASSERT(script->analyzedArgsUsage());
   MOZ_ASSERT(script->argumentsHasVarBinding());
 
   /*
    * It is possible that the arguments optimization has already failed,
    * everything has been fixed up, but there was an outstanding magic value
    * on the stack that has just now flowed into an apply. In this case, there
    * is nothing to do; GuardFunApplySpeculation will patch in the real
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1545,17 +1545,18 @@ class BaseScript : public gc::TenuredCel
     IsModule = 1 << 23,
 
     // Whether this function needs a call object or named lambda environment.
     NeedsFunctionEnvironmentObjects = 1 << 24,
 
     // Whether the Parser declared 'arguments'.
     ShouldDeclareArguments = 1 << 25,
 
-    // (1 << 26) is unused.
+    // Script is for function.
+    IsFunction = 1 << 26,
 
     // Whether this script contains a direct eval statement.
     HasDirectEval = 1 << 27,
   };
 
   // Mutable flags typically store information about runtime or deoptimization
   // behavior of this script. This is only public for the JITs.
   //
@@ -1764,16 +1765,17 @@ setterLevel:                            
   // N.B.: no setter -- custom logic in JSScript.
   IMMUTABLE_FLAG_GETTER(argumentsHasVarBinding, ArgumentsHasVarBinding)
   // IsForEval: custom logic below.
   // IsModule: custom logic below.
   IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects,
                                NeedsFunctionEnvironmentObjects)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(shouldDeclareArguments,
                                       ShouldDeclareArguments)
+  IMMUTABLE_FLAG_GETTER(isFunction, IsFunction)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasDirectEval, HasDirectEval)
 
   MUTABLE_FLAG_GETTER_SETTER(warnedAboutUndefinedProp, WarnedAboutUndefinedProp)
   MUTABLE_FLAG_GETTER_SETTER(hasRunOnce, HasRunOnce)
   MUTABLE_FLAG_GETTER_SETTER(hasBeenCloned, HasBeenCloned)
   MUTABLE_FLAG_GETTER_SETTER(trackRecordReplayProgress,
                              TrackRecordReplayProgress)
   // N.B.: no setter -- custom logic in JSScript.
@@ -2749,26 +2751,22 @@ class JSScript : public js::BaseScript {
   }
 
   bool isModule() const {
     MOZ_ASSERT(hasFlag(ImmutableFlags::IsModule) ==
                bodyScope()->is<js::ModuleScope>());
     return hasFlag(ImmutableFlags::IsModule);
   }
   js::ModuleObject* module() const {
-    if (isModule()) {
+    if (bodyScope()->is<js::ModuleScope>()) {
       return bodyScope()->as<js::ModuleScope>().module();
     }
     return nullptr;
   }
 
-  bool isGlobalOrEvalCode() const {
-    return bodyScope()->is<js::GlobalScope>() ||
-           bodyScope()->is<js::EvalScope>();
-  }
   bool isGlobalCode() const { return bodyScope()->is<js::GlobalScope>(); }
 
   // Returns true if the script may read formal arguments on the stack
   // directly, via lazy arguments or a rest parameter.
   bool mayReadFrameArgsDirectly();
 
   static JSLinearString* sourceData(JSContext* cx, JS::HandleScript script);
 
@@ -2783,19 +2781,19 @@ class JSScript : public js::BaseScript {
   // 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 {
-    bool forEval = hasFlag(ImmutableFlags::IsForEval);
-    MOZ_ASSERT_IF(forEval, bodyScope()->is<js::EvalScope>());
-    return forEval;
+    MOZ_ASSERT(hasFlag(ImmutableFlags::IsForEval) ==
+               bodyScope()->is<js::EvalScope>());
+    return hasFlag(ImmutableFlags::IsForEval);
   }
 
   /* 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);
@@ -2806,17 +2804,17 @@ class JSScript : public js::BaseScript {
    *
    * If we evaluate some code which contains a syntax error, then we might
    * produce a JSScript which has no associated bytecode. Testing with
    * |code()| filters out this kind of scripts.
    *
    * If this script has a function associated to it, then it is not the
    * top-level of a file.
    */
-  bool isTopLevel() { return code() && !function(); }
+  bool isTopLevel() { return code() && !isFunction(); }
 
   /* Ensure the script has a JitScript. */
   inline bool ensureHasJitScript(JSContext* cx, js::jit::AutoKeepJitScripts&);
 
   bool hasJitScript() const { return warmUpData_.isJitScript(); }
 
   js::jit::JitScript* jitScript() const {
     MOZ_ASSERT(hasJitScript());
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -943,17 +943,17 @@ bool FrameIter::isFunctionFrame() const 
       break;
     case INTERP:
       return interpFrame()->isFunctionFrame();
     case JIT:
       if (isJSJit()) {
         if (jsJitFrame().isBaselineJS()) {
           return jsJitFrame().baselineFrame()->isFunctionFrame();
         }
-        return script()->function();
+        return script()->isFunction();
       }
       MOZ_ASSERT(isWasm());
       return false;
   }
   MOZ_CRASH("Unexpected state");
 }
 
 JSAtom* FrameIter::maybeFunctionDisplayAtom() const {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -427,21 +427,21 @@ class InterpreterFrame {
    *  global frame:   execution of global code
    *  function frame: execution of function code
    *  module frame:   execution of a module
    *  eval frame:     execution of eval code
    */
 
   bool isGlobalFrame() const { return script_->isGlobalCode(); }
 
-  bool isModuleFrame() const { return script_->module(); }
+  bool isModuleFrame() const { return script_->isModule(); }
 
   bool isEvalFrame() const { return script_->isForEval(); }
 
-  bool isFunctionFrame() const { return script_->function(); }
+  bool isFunctionFrame() const { return script_->isFunction(); }
 
   inline bool isStrictEvalFrame() const {
     return isEvalFrame() && script()->strict();
   }
 
   bool isNonStrictEvalFrame() const {
     return isEvalFrame() && !script()->strict();
   }