Bug 1615729 - Move ImmutableFlags for SharedStencil.h. r=mgaudet
authorcaroline <ccullen@mozilla.com>
Fri, 21 Feb 2020 22:25:01 +0000
changeset 2648948 e3fffbd8245fd3867ec06c7c6a4bd0decdcff600
parent 2648947 562749d5a8dc5d5ba14e1730704b310458c6cbbc
child 2648949 3f9b82ed6f7ad498d984199cfb05035867593836
push id490874
push userdvarga@mozilla.com
push dateSat, 22 Feb 2020 10:42:44 +0000
treeherdertry@64a8e247759e [default view] [failures only]
reviewersmgaudet
bugs1615729
milestone75.0a1
Bug 1615729 - Move ImmutableFlags for SharedStencil.h. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D63578
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/SharedStencil.h
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -1238,17 +1238,17 @@ XDRResult js::XDRScript(XDRState<mode>* 
                         toStringEnd, lineno,    column};
     script =
         JSScript::Create(cx, functionOrGlobal, *options, sourceObject, extent);
     if (!script) {
       return xdr->fail(JS::TranscodeResult_Throw);
     }
     scriptp.set(script);
 
-    script->immutableFlags_ = immutableFlags;
+    script->setImmutableFlags(immutableFlags);
 
     if (script->argumentsHasVarBinding()) {
       // Call setArgumentsHasVarBinding to initialize the
       // NeedsArgsAnalysis flag.
       script->setArgumentsHasVarBinding();
     }
 
     // Set the script in its function now so that inner scripts to be
@@ -5029,17 +5029,17 @@ JSScript* js::detail::CopyScript(JSConte
                       src->lineno(),        src->column()};
   RootedScript dst(cx, JSScript::Create(cx, functionOrGlobal, options,
                                         sourceObject, extent));
   if (!dst) {
     return nullptr;
   }
 
   // Copy POD fields
-  dst->immutableFlags_ = src->immutableFlags();
+  dst->setImmutableFlags(src->immutableFlags());
 
   dst->setFlag(JSScript::ImmutableFlags::HasNonSyntacticScope,
                scopes[0]->hasOnChain(ScopeKind::NonSyntactic));
 
   if (src->argumentsHasVarBinding()) {
     dst->setArgumentsHasVarBinding();
   }
 
@@ -5587,17 +5587,17 @@ LazyScript* LazyScript::CreateForXDR(
   SourceExtent extent{sourceStart, sourceEnd, toStringStart,
                       toStringEnd, lineno,    column};
   LazyScript* lazy =
       LazyScript::CreateRaw(cx, ngcthings, fun, sourceObject, extent);
   if (!lazy) {
     return nullptr;
   }
 
-  lazy->immutableFlags_ = immutableFlags;
+  lazy->setImmutableFlags(immutableFlags);
 
   // Set the enclosing scope of the lazy function. This value should only be
   // set if we have a non-lazy enclosing script at this point.
   // LazyScript::enclosingScriptHasEverBeenCompiled relies on the enclosing
   // scope being non-null if we have ever been nested inside non-lazy
   // function.
   if (enclosingScope) {
     lazy->setEnclosingScope(enclosingScope);
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -40,16 +40,17 @@
 #include "vm/BytecodeIterator.h"
 #include "vm/BytecodeLocation.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/JSAtom.h"
 #include "vm/NativeObject.h"
 #include "vm/Scope.h"
 #include "vm/Shape.h"
 #include "vm/SharedImmutableStringsCache.h"
+#include "vm/SharedStencil.h"
 #include "vm/Time.h"
 
 namespace JS {
 struct ScriptSourceInfo;
 template <typename UnitT>
 class SourceText;
 }  // namespace JS
 
@@ -1994,16 +1995,19 @@ struct SourceExtent {
   uint32_t column = 0;  // Count of Code Points
 };
 
 // This class contains fields and accessors that are common to both lazy and
 // non-lazy interpreted scripts. This must be located at offset +0 of any
 // derived classes in order for the 'jitCodeRaw' mechanism to work with the
 // JITs.
 class BaseScript : public gc::TenuredCell {
+ public:
+  using ImmutableFlags = frontend::ImmutableScriptFlags;
+
  protected:
   // Pointer to baseline->method()->raw(), ion->method()->raw(), a wasm jit
   // entry, the JIT's EnterInterpreter stub, or the lazy link stub. Must be
   // non-null (except on no-jit builds).
   uint8_t* jitCodeRaw_ = nullptr;
 
   // Object that determines what Realm this script is compiled for. In general
   // this refers to the realm's GlobalObject, but for a lazy-script we instead
@@ -2021,20 +2025,28 @@ class BaseScript : public gc::TenuredCel
 
   // Shareable script data. This includes runtime-wide atom pointers, bytecode,
   // and various script note structures. If the script is currently lazy, this
   // will not point to anything.
   RefPtr<js::RuntimeScriptData> sharedData_ = {};
 
   SourceExtent extent_;
 
-  // See ImmutableFlags / MutableFlags below for definitions. These are stored
+  // Immutable flags should not be modified after this script has been
+  // initialized. These flags should likely be preserved when serializing
+  // (XDR) or copying (CopyScript) this script. This is only public for the
+  // JITs.
+  //
+  // Specific accessors for flag values are defined with
+  // IMMUTABLE_FLAG_* macros below.
+  ImmutableFlags immutableScriptFlags_;
+
+  // See MutableFlags below for definitions. This is stored
   // as uint32_t instead of bitfields to make it more predictable to access
   // from JIT code.
-  uint32_t immutableFlags_ = 0;
   uint32_t mutableFlags_ = 0;
 
   ScriptWarmUpData warmUpData_ = {};
 
   union TwinPointer {
     // Information used to re-lazify a lazily-parsed interpreted function.
     js::LazyScript* lazyScript;
 
@@ -2061,112 +2073,16 @@ class BaseScript : public gc::TenuredCel
         extent_(extent) {
     MOZ_ASSERT(functionOrGlobal->compartment() == sourceObject->compartment());
     MOZ_ASSERT(extent_.toStringStart <= extent_.sourceStart);
     MOZ_ASSERT(extent_.sourceStart <= extent_.sourceEnd);
     MOZ_ASSERT(extent_.sourceEnd <= extent_.toStringEnd);
   }
 
  public:
-  // Immutable flags should not be modified after this script has been
-  // initialized. These flags should likely be preserved when serializing
-  // (XDR) or copying (CopyScript) this script. This is only public for the
-  // JITs.
-  //
-  // Specific accessors for flag values are defined with
-  // IMMUTABLE_FLAG_* macros below.
-  enum class ImmutableFlags : uint32_t {
-    // No need for result value of last expression statement.
-    NoScriptRval = 1 << 0,
-
-    // Code is in strict mode.
-    Strict = 1 << 1,
-
-    // (1 << 2) is unused.
-
-    // 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 << 3,
-
-    // See Parser::selfHostingMode.
-    SelfHosted = 1 << 4,
-
-    // See FunctionBox.
-    BindingsAccessedDynamically = 1 << 5,
-    FunHasExtensibleScope = 1 << 6,
-
-    // Bytecode contains JSOp::CallSiteObj
-    // (We don't relazify functions with template strings, due to observability)
-    HasCallSiteObj = 1 << 7,
-
-    // Script is parsed with a top-level goal of Module. This may be a top-level
-    // or an inner-function script.
-    HasModuleGoal = 1 << 8,
-
-    FunctionHasThisBinding = 1 << 9,
-    FunctionHasExtraBodyVarScope = 1 << 10,
-
-    // Whether the arguments object for this script, if it needs one, should be
-    // mapped (alias formal parameters).
-    HasMappedArgsObj = 1 << 11,
-
-    // Script contains inner functions. Used to check if we can relazify the
-    // script.
-    HasInnerFunctions = 1 << 12,
-
-    NeedsHomeObject = 1 << 13,
-
-    IsDerivedClassConstructor = 1 << 14,
-    IsDefaultClassConstructor = 1 << 15,
-
-    // 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 << 16,
-
-    // 'this', 'arguments' and f.apply() are used. This is likely to be a
-    // wrapper.
-    IsLikelyConstructorWrapper = 1 << 17,
-
-    // Set if this function is a generator function or async generator.
-    IsGenerator = 1 << 18,
-
-    // 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.
-    ArgumentsHasVarBinding = 1 << 21,
-
-    // Script came from eval().
-    IsForEval = 1 << 22,
-
-    // Whether this is a top-level module script.
-    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,
-
-    // Script is for function.
-    IsFunction = 1 << 26,
-
-    // Whether this script contains a direct eval statement.
-    HasDirectEval = 1 << 27,
-
-    // Whether this BaseScript is a LazyScript. This flag will be removed after
-    // LazyScript and JSScript are merged in Bug 1529456.
-    IsLazyScript = 1 << 28,
-  };
-
   // Mutable flags typically store information about runtime or deoptimization
   // behavior of this script. This is only public for the JITs.
   //
   // Specific accessors for flag values are defined with
   // MUTABLE_FLAG_* macros below.
   enum class MutableFlags : uint32_t {
     // Number of times the |warmUpCount| was forcibly discarded. The counter is
     // reset when a script is successfully jit-compiled.
@@ -2310,34 +2226,41 @@ class BaseScript : public gc::TenuredCel
     MOZ_ASSERT(extent_.toStringStart <= toStringEnd);
     MOZ_ASSERT(extent_.toStringEnd >= extent_.sourceEnd);
     extent_.toStringEnd = toStringEnd;
   }
 
   uint32_t lineno() const { return extent_.lineno; }
   uint32_t column() const { return extent_.column; }
 
+ public:
+  ImmutableFlags immutableFlags() const { return immutableScriptFlags_; }
+
+  void setImmutableFlags(ImmutableFlags flags) {
+    immutableScriptFlags_ = flags;
+  }
+
   // ImmutableFlags accessors.
   MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const {
-    return immutableFlags_ & uint32_t(flag);
+    return immutableScriptFlags_ & flag;
   }
-  uint32_t immutableFlags() const { return immutableFlags_; }
-
- protected:
-  void setFlag(ImmutableFlags flag) { immutableFlags_ |= uint32_t(flag); }
+  void setFlag(ImmutableFlags flag) {
+    immutableScriptFlags_.scriptFlags_ |= flag;
+  }
   void setFlag(ImmutableFlags flag, bool b) {
     if (b) {
       setFlag(flag);
     } else {
       clearFlag(flag);
     }
   }
-  void clearFlag(ImmutableFlags flag) { immutableFlags_ &= ~uint32_t(flag); }
-
- public:
+  void clearFlag(ImmutableFlags flag) {
+    immutableScriptFlags_.scriptFlags_ &= ~flag;
+  }
+
   // MutableFlags accessors.
   MOZ_MUST_USE bool hasFlag(MutableFlags flag) const {
     return mutableFlags_ & uint32_t(flag);
   }
   void setFlag(MutableFlags flag) { mutableFlags_ |= uint32_t(flag); }
   void setFlag(MutableFlags flag, bool b) {
     if (b) {
       setFlag(flag);
@@ -2367,36 +2290,36 @@ setterLevel:                            
 #define IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(lowerName, name) \
   FLAG_GETTER_SETTER(ImmutableFlags, name, public, lowerName, name)
 #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(strict, Strict)
   IMMUTABLE_FLAG_GETTER(hasNonSyntacticScope, HasNonSyntacticScope)
-  IMMUTABLE_FLAG_GETTER(selfHosted, SelfHosted)
   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)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(functionHasThisBinding,
                                       FunctionHasThisBinding)
   // FunctionHasExtraBodyVarScope: custom logic below.
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasMappedArgsObj, HasMappedArgsObj)
   IMMUTABLE_FLAG_GETTER(hasInnerFunctions, HasInnerFunctions)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(needsHomeObject, NeedsHomeObject)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(isDerivedClassConstructor,
                                       IsDerivedClassConstructor)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(isDefaultClassConstructor,
                                       IsDefaultClassConstructor)
-  IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(treatAsRunOnce, TreatAsRunOnce)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(isLikelyConstructorWrapper,
                                       IsLikelyConstructorWrapper)
   IMMUTABLE_FLAG_GETTER(isGenerator, IsGenerator)
   IMMUTABLE_FLAG_GETTER(isAsync, IsAsync)
   IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasRest, HasRest)
   // See FunctionBox::argumentsHasLocalBinding_ comment.
   // N.B.: no setter -- custom logic in JSScript.
   IMMUTABLE_FLAG_GETTER(argumentsHasVarBinding, ArgumentsHasVarBinding)
@@ -2550,17 +2473,19 @@ setterLevel:                            
   }
   static constexpr size_t offsetOfPrivateData() {
     return offsetof(BaseScript, data_);
   }
   static constexpr size_t offsetOfSharedData() {
     return offsetof(BaseScript, sharedData_);
   }
   static size_t offsetOfImmutableFlags() {
-    return offsetof(BaseScript, immutableFlags_);
+    static_assert(offsetof(ImmutableFlags, scriptFlags_) == 0,
+                  "Required for JIT flag access");
+    return offsetof(BaseScript, immutableScriptFlags_);
   }
   static constexpr size_t offsetOfMutableFlags() {
     return offsetof(BaseScript, mutableFlags_);
   }
   static constexpr size_t offsetOfWarmUpData() {
     return offsetof(BaseScript, warmUpData_);
   }
 };
new file mode 100644
--- /dev/null
+++ b/js/src/vm/SharedStencil.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef vm_SharedStencil_h
+#define vm_SharedStencil_h
+
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint32_t
+
+#include "jstypes.h"
+
+/*
+ * Data shared between the vm and stencil structures.
+ */
+
+namespace js {
+namespace frontend {
+
+class ImmutableScriptFlags {
+ public:
+  enum ScriptFlags : uint32_t {
+    // Input Flags
+    //
+    // Flags that come from CompileOptions.
+    // ----
+
+    // No need for result value of last expression statement.
+    NoScriptRval = 1 << 0,
+
+    // 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 is in strict mode.
+    Strict = 1 << 3,
+
+    // 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,
+
+    // See FunctionBox.
+    BindingsAccessedDynamically = 1 << 5,
+    FunHasExtensibleScope = 1 << 6,
+
+    // Bytecode contains JSOp::CallSiteObj
+    // (We don't relazify functions with template strings, due to observability)
+    HasCallSiteObj = 1 << 7,
+
+    // Script is parsed with a top-level goal of Module. This may be a top-level
+    // or an inner-function script.
+    HasModuleGoal = 1 << 8,
+
+    FunctionHasThisBinding = 1 << 9,
+    FunctionHasExtraBodyVarScope = 1 << 10,
+
+    // Whether the arguments object for this script, if it needs one, should be
+    // mapped (alias formal parameters).
+    HasMappedArgsObj = 1 << 11,
+
+    // Script contains inner functions. Used to check if we can relazify the
+    // script.
+    HasInnerFunctions = 1 << 12,
+
+    NeedsHomeObject = 1 << 13,
+
+    IsDerivedClassConstructor = 1 << 14,
+    IsDefaultClassConstructor = 1 << 15,
+
+    // 'this', 'arguments' and f.apply() are used. This is likely to be a
+    // wrapper.
+    IsLikelyConstructorWrapper = 1 << 16,
+
+    // Set if this function is a generator function or async generator.
+    IsGenerator = 1 << 17,
+
+    // Set if this function is an async function or async generator.
+    IsAsync = 1 << 18,
+
+    // Set if this function has a rest parameter.
+    HasRest = 1 << 19,
+
+    // See comments below.
+    ArgumentsHasVarBinding = 1 << 20,
+
+    // Script came from eval().
+    IsForEval = 1 << 21,
+
+    // Whether this is a top-level module script.
+    IsModule = 1 << 22,
+
+    // Whether this function needs a call object or named lambda environment.
+    NeedsFunctionEnvironmentObjects = 1 << 23,
+
+    // Whether the Parser declared 'arguments'.
+    ShouldDeclareArguments = 1 << 24,
+
+    // Script is for function.
+    IsFunction = 1 << 25,
+
+    // Whether this script contains a direct eval statement.
+    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 << 27,
+  };
+
+  // This is stored as uint32_t instead of bitfields to make it more
+  // predictable to access from JIT code.
+  uint32_t scriptFlags_ = 0;
+
+ public:
+  ImmutableScriptFlags() : scriptFlags_() {
+    static_assert(sizeof(ImmutableScriptFlags) == sizeof(scriptFlags_),
+                  "No extra members allowed");
+    static_assert(offsetof(ImmutableScriptFlags, scriptFlags_) == 0,
+                  "Required for JIT flag access");
+  }
+
+  MOZ_IMPLICIT ImmutableScriptFlags(ScriptFlags sf) : scriptFlags_(sf) {}
+  MOZ_IMPLICIT ImmutableScriptFlags(int32_t flags)
+      : scriptFlags_(ScriptFlags(flags)) {}
+
+  operator uint32_t() const { return scriptFlags_; }
+
+  void operator=(uint32_t flag) { scriptFlags_ = flag; }
+
+  uint32_t toRaw() const { return scriptFlags_; }
+};
+
+}  // namespace frontend
+}  // namespace js
+
+#endif /* vm_SharedStencil_h */