LCOV - code coverage report
Current view: top level - js/src/vm - Scope.h (source / functions) Hit Total Coverage
Test: output.info Lines: 159 274 58.0 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_Scope_h
       8             : #define vm_Scope_h
       9             : 
      10             : #include "mozilla/Maybe.h"
      11             : #include "mozilla/TypeTraits.h"
      12             : #include "mozilla/Variant.h"
      13             : 
      14             : #include <stddef.h>
      15             : 
      16             : #include "jsutil.h"
      17             : 
      18             : #include "gc/DeletePolicy.h"
      19             : #include "gc/Heap.h"
      20             : #include "gc/Policy.h"
      21             : #include "js/UbiNode.h"
      22             : #include "js/UniquePtr.h"
      23             : #include "vm/BytecodeUtil.h"
      24             : #include "vm/JSObject.h"
      25             : #include "vm/Xdr.h"
      26             : 
      27             : namespace js {
      28             : 
      29             : class ModuleObject;
      30             : class Scope;
      31             : 
      32             : enum class BindingKind : uint8_t
      33             : {
      34             :     Import,
      35             :     FormalParameter,
      36             :     Var,
      37             :     Let,
      38             :     Const,
      39             : 
      40             :     // So you think named lambda callee names are consts? Nope! They don't
      41             :     // throw when being assigned to in sloppy mode.
      42             :     NamedLambdaCallee
      43             : };
      44             : 
      45           0 : static inline bool
      46             : BindingKindIsLexical(BindingKind kind)
      47             : {
      48             :     return kind == BindingKind::Let || kind == BindingKind::Const;
      49             : }
      50             : 
      51             : enum class ScopeKind : uint8_t
      52             : {
      53             :     // FunctionScope
      54             :     Function,
      55             : 
      56             :     // VarScope
      57             :     FunctionBodyVar,
      58             :     ParameterExpressionVar,
      59             : 
      60             :     // LexicalScope
      61             :     Lexical,
      62             :     SimpleCatch,
      63             :     Catch,
      64             :     NamedLambda,
      65             :     StrictNamedLambda,
      66             : 
      67             :     // WithScope
      68             :     With,
      69             : 
      70             :     // EvalScope
      71             :     Eval,
      72             :     StrictEval,
      73             : 
      74             :     // GlobalScope
      75             :     Global,
      76             :     NonSyntactic,
      77             : 
      78             :     // ModuleScope
      79             :     Module,
      80             : 
      81             :     // WasmInstanceScope
      82             :     WasmInstance,
      83             : 
      84             :     // WasmFunctionScope
      85             :     WasmFunction
      86             : };
      87             : 
      88           0 : static inline bool
      89             : ScopeKindIsCatch(ScopeKind kind)
      90             : {
      91             :     return kind == ScopeKind::SimpleCatch || kind == ScopeKind::Catch;
      92             : }
      93             : 
      94             : static inline bool
      95           0 : ScopeKindIsInBody(ScopeKind kind)
      96           0 : {
      97           0 :     return kind == ScopeKind::Lexical ||
      98           0 :            kind == ScopeKind::SimpleCatch ||
      99             :            kind == ScopeKind::Catch ||
     100             :            kind == ScopeKind::With ||
     101             :            kind == ScopeKind::FunctionBodyVar ||
     102             :            kind == ScopeKind::ParameterExpressionVar;
     103             : }
     104             : 
     105             : const char* BindingKindString(BindingKind kind);
     106             : const char* ScopeKindString(ScopeKind kind);
     107             : 
     108             : class BindingName
     109             : {
     110             :     // A JSAtom* with its low bit used as a tag for the:
     111             :     //  * whether it is closed over (i.e., exists in the environment shape)
     112             :     //  * whether it is a top-level function binding in global or eval scope,
     113             :     //    instead of var binding (both are in the same range in Scope data)
     114             :     uintptr_t bits_;
     115             : 
     116             :     static const uintptr_t ClosedOverFlag = 0x1;
     117             :     // TODO: We should reuse this bit for let vs class distinction to
     118             :     //       show the better redeclaration error message (bug 1428672).
     119             :     static const uintptr_t TopLevelFunctionFlag = 0x2;
     120             :     static const uintptr_t FlagMask = 0x3;
     121       13507 : 
     122             :   public:
     123             :     BindingName()
     124             :       : bits_(0)
     125      158886 :     { }
     126       87315 : 
     127       74060 :     BindingName(JSAtom* name, bool closedOver, bool isTopLevelFunction = false)
     128             :       : bits_(uintptr_t(name) |
     129             :               (closedOver ? ClosedOverFlag : 0x0) |
     130             :               (isTopLevelFunction? TopLevelFunctionFlag : 0x0))
     131      320488 :     { }
     132             : 
     133             :   private:
     134             :     // For fromXDR.
     135      327211 :     BindingName(JSAtom* name, uint8_t flags)
     136             :       : bits_(uintptr_t(name) | flags)
     137             :     {
     138             :         static_assert(FlagMask < alignof(JSAtom),
     139             :                       "Flags should fit into unused bits of JSAtom pointer");
     140             :         MOZ_ASSERT((flags & FlagMask) == flags);
     141             :     }
     142             : 
     143        3855 :   public:
     144             :     static BindingName fromXDR(JSAtom* name, uint8_t flags) {
     145             :         return BindingName(name, flags);
     146             :     }
     147             : 
     148             :     uint8_t flagsForXDR() const {
     149             :         return static_cast<uint8_t>(bits_ & FlagMask);
     150             :     }
     151             : 
     152             :     JSAtom* name() const {
     153             :         return reinterpret_cast<JSAtom*>(bits_ & ~FlagMask);
     154             :     }
     155             : 
     156             :     bool closedOver() const {
     157             :         return bits_ & ClosedOverFlag;
     158             :     }
     159             : 
     160             :   private:
     161             :     friend class BindingIter;
     162             :     // This method should be called only for binding names in `vars` range in
     163             :     // BindingIter.
     164             :     bool isTopLevelFunction() const {
     165             :         return bits_ & TopLevelFunctionFlag;
     166             :     }
     167             : 
     168             :   public:
     169             :     void trace(JSTracer* trc);
     170             : };
     171             : 
     172             : /**
     173             :  * The various {Global,Module,...}Scope::Data classes consist of always-present
     174      252784 :  * bits, then a trailing array of BindingNames.  The various Data classes all
     175             :  * end in a TrailingNamesArray that contains sized/aligned space for *one*
     176             :  * BindingName.  Data instances that contain N BindingNames, are then allocated
     177             :  * in sizeof(Data) + (space for (N - 1) BindingNames).  Because this class's
     178             :  * |data_| field is properly sized/aligned, the N-BindingName array can start
     179             :  * at |data_|.
     180             :  *
     181             :  * This is concededly a very low-level representation, but we want to only
     182       23319 :  * allocate once for data+bindings both, and this does so approximately as
     183       23319 :  * elegantly as C++ allows.
     184       21171 :  */
     185             : class TrailingNamesArray
     186             : {
     187      254975 :   private:
     188             :     alignas(BindingName) unsigned char data_[sizeof(BindingName)];
     189       70051 : 
     190             :   private:
     191             :     // Some versions of GCC treat it as a -Wstrict-aliasing violation (ergo a
     192             :     // -Werror compile error) to reinterpret_cast<> |data_| to |T*|, even
     193             :     // through |void*|.  Placing the latter cast in these separate functions
     194             :     // breaks the chain such that affected GCC versions no longer warn/error.
     195             :     void* ptr() {
     196             :         return data_;
     197             :     }
     198             : 
     199             :   public:
     200             :     // Explicitly ensure no one accidentally allocates scope data without
     201             :     // poisoning its trailing names.
     202             :     TrailingNamesArray() = delete;
     203             : 
     204             :     explicit TrailingNamesArray(size_t nameCount) {
     205             :         if (nameCount)
     206             :             JS_POISON(&data_, 0xCC, sizeof(BindingName) * nameCount, MemCheckKind::MakeUndefined);
     207             :     }
     208             : 
     209             :     BindingName* start() { return reinterpret_cast<BindingName*>(ptr()); }
     210             : 
     211             :     BindingName& operator[](size_t i) { return start()[i]; }
     212             : };
     213             : 
     214             : class BindingLocation
     215        3455 : {
     216             :   public:
     217             :     enum class Kind {
     218             :         Global,
     219       11155 :         Argument,
     220             :         Frame,
     221             :         Environment,
     222       24678 :         Import,
     223       24678 :         NamedLambdaCallee
     224       24678 :     };
     225             : 
     226             :   private:
     227       33049 :     Kind kind_;
     228       33049 :     uint32_t slot_;
     229       33049 : 
     230             :     BindingLocation(Kind kind, uint32_t slot)
     231             :       : kind_(kind),
     232             :         slot_(slot)
     233           0 :     { }
     234             : 
     235             :   public:
     236             :     static BindingLocation Global() {
     237           0 :         return BindingLocation(Kind::Global, UINT32_MAX);
     238             :     }
     239             : 
     240             :     static BindingLocation Argument(uint16_t slot) {
     241             :         return BindingLocation(Kind::Argument, slot);
     242             :     }
     243             : 
     244             :     static BindingLocation Frame(uint32_t slot) {
     245             :         MOZ_ASSERT(slot < LOCALNO_LIMIT);
     246             :         return BindingLocation(Kind::Frame, slot);
     247             :     }
     248             : 
     249             :     static BindingLocation Environment(uint32_t slot) {
     250             :         MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
     251             :         return BindingLocation(Kind::Environment, slot);
     252       45134 :     }
     253       45134 : 
     254       45134 :     static BindingLocation Import() {
     255             :         return BindingLocation(Kind::Import, UINT32_MAX);
     256             :     }
     257           0 : 
     258           0 :     static BindingLocation NamedLambdaCallee() {
     259       10518 :         return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
     260             :     }
     261             : 
     262             :     bool operator==(const BindingLocation& other) const {
     263             :         return kind_ == other.kind_ && slot_ == other.slot_;
     264             :     }
     265             : 
     266             :     bool operator!=(const BindingLocation& other) const {
     267             :         return !operator==(other);
     268             :     }
     269             : 
     270             :     Kind kind() const {
     271       39950 :         return kind_;
     272       39950 :     }
     273       97441 : 
     274       79900 :     uint32_t slot() const {
     275             :         MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
     276             :         return slot_;
     277             :     }
     278             : 
     279             :     uint16_t argumentSlot() const {
     280             :         MOZ_ASSERT(kind_ == Kind::Argument);
     281             :         return mozilla::AssertedCast<uint16_t>(slot_);
     282             :     }
     283             : };
     284             : 
     285             : //
     286             : // Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
     287             : //
     288             : template <typename Wrapper>
     289             : class WrappedPtrOperations<Scope*, Wrapper>
     290             : {
     291             :   public:
     292             :     template <class U>
     293             :     JS::Handle<U*> as() const {
     294             :         const Wrapper& self = *static_cast<const Wrapper*>(this);
     295             :         MOZ_ASSERT_IF(self, self->template is<U>());
     296             :         return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
     297             :     }
     298             : };
     299             : 
     300             : //
     301             : // The base class of all Scopes.
     302             : //
     303             : class Scope : public js::gc::TenuredCell
     304             : {
     305             :     friend class GCMarker;
     306       26139 : 
     307             :     // The kind determines data_.
     308       78417 :     //
     309             :     // The memory here must be fully initialized, since otherwise the magic_
     310       26139 :     // value for gc::RelocationOverlay will land in the padding and may be
     311       26139 :     // stale.
     312             :     union {
     313             :         ScopeKind kind_;
     314             :         uintptr_t paddedKind_;
     315             :     };
     316             : 
     317             :     // The enclosing scope or nullptr.
     318             :     GCPtrScope enclosing_;
     319             : 
     320             :     // If there are any aliased bindings, the shape for the
     321             :     // EnvironmentObject. Otherwise nullptr.
     322             :     GCPtrShape environmentShape_;
     323             : 
     324             :   protected:
     325             :     uintptr_t data_;
     326             : 
     327             :     Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
     328           0 :       : enclosing_(enclosing),
     329       26139 :         environmentShape_(environmentShape),
     330       26139 :         data_(0)
     331       26139 :     {
     332             :         paddedKind_ = 0;
     333             :         kind_ = kind;
     334             :     }
     335             : 
     336             :     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
     337             :                          HandleShape envShape);
     338           0 : 
     339             :     template <typename T, typename D>
     340             :     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
     341             :                          HandleShape envShape, mozilla::UniquePtr<T, D> data);
     342           0 : 
     343      973775 :     template <typename ConcreteScope, XDRMode mode>
     344      911394 :     static XDRResult XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
     345             :                                           MutableHandle<typename ConcreteScope::Data*> data);
     346             : 
     347             :     Shape* maybeCloneEnvironmentShape(JSContext* cx);
     348             : 
     349             :     template <typename T, typename D>
     350             :     void initData(mozilla::UniquePtr<T, D> data) {
     351             :         MOZ_ASSERT(!data_);
     352             :         data_ = reinterpret_cast<uintptr_t>(data.release());
     353             :     }
     354             : 
     355             :   public:
     356             :     static const JS::TraceKind TraceKind = JS::TraceKind::Scope;
     357             : 
     358      424144 :     template <typename T>
     359             :     bool is() const {
     360             :         return kind_ == T::classScopeKind_;
     361             :     }
     362      165270 : 
     363             :     template <typename T>
     364             :     T& as() {
     365             :         MOZ_ASSERT(this->is<T>());
     366      136122 :         return *static_cast<T*>(this);
     367             :     }
     368             : 
     369             :     template <typename T>
     370             :     const T& as() const {
     371             :         MOZ_ASSERT(this->is<T>());
     372             :         return *static_cast<const T*>(this);
     373      366782 :     }
     374             : 
     375             :     ScopeKind kind() const {
     376             :         return kind_;
     377             :     }
     378             : 
     379             :     Scope* enclosing() const {
     380             :         return enclosing_;
     381             :     }
     382             : 
     383             :     Shape* environmentShape() const {
     384             :         return environmentShape_;
     385             :     }
     386             : 
     387             :     bool hasEnvironment() const {
     388             :         switch (kind()) {
     389             :           case ScopeKind::With:
     390       79586 :           case ScopeKind::Global:
     391       41506 :           case ScopeKind::NonSyntactic:
     392             :             return true;
     393             :           default:
     394             :             // If there's a shape, an environment must be created for this scope.
     395             :             return environmentShape_ != nullptr;
     396             :         }
     397             :     }
     398             : 
     399             :     uint32_t chainLength() const;
     400             :     uint32_t environmentChainLength() const;
     401             : 
     402             :     template <typename T>
     403             :     bool hasOnChain() const {
     404             :         for (const Scope* it = this; it; it = it->enclosing()) {
     405             :             if (it->is<T>())
     406             :                 return true;
     407             :         }
     408             :         return false;
     409             :     }
     410             : 
     411             :     bool hasOnChain(ScopeKind kind) const {
     412             :         for (const Scope* it = this; it; it = it->enclosing()) {
     413             :             if (it->kind() == kind)
     414             :                 return true;
     415             :         }
     416             :         return false;
     417             :     }
     418             : 
     419             :     static Scope* clone(JSContext* cx, HandleScope scope, HandleScope enclosing);
     420             : 
     421             :     void traceChildren(JSTracer* trc);
     422             :     void finalize(FreeOp* fop);
     423             : 
     424             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     425             : 
     426             :     void dump();
     427             : };
     428             : 
     429             : /** Empty base class for scope Data classes to inherit from. */
     430             : class BaseScopeData
     431             : {};
     432             : 
     433             : template<class Data>
     434             : inline size_t
     435             : SizeOfData(uint32_t numBindings)
     436             : {
     437             :     static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
     438             :                   "Data must be the correct sort of data, i.e. it must "
     439             :                   "inherit from BaseScopeData");
     440             :     return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
     441             : }
     442             : 
     443             : //
     444             : // A lexical scope that holds let and const bindings. There are 4 kinds of
     445             : // LexicalScopes.
     446             : //
     447             : // Lexical
     448             : //   A plain lexical scope.
     449             : //
     450             : // SimpleCatch
     451             : //   Holds the single catch parameter of a catch block.
     452             : //
     453        9615 : // Catch
     454             : //   Holds the catch parameters (and only the catch parameters) of a catch
     455             : //   block.
     456             : //
     457             : // NamedLambda
     458             : // StrictNamedLambda
     459             : //   Holds the single name of the callee for a named lambda expression.
     460       20068 : //
     461             : // All kinds of LexicalScopes correspond to LexicalEnvironmentObjects on the
     462             : // environment chain.
     463             : //
     464       20906 : class LexicalScope : public Scope
     465           0 : {
     466             :     friend class Scope;
     467             :     friend class BindingIter;
     468             : 
     469             :   public:
     470             :     // Data is public because it is created by the frontend. See
     471             :     // Parser<FullParseHandler>::newLexicalScopeData.
     472             :     struct Data : BaseScopeData
     473             :     {
     474             :         // Bindings are sorted by kind in both frames and environments.
     475             :         //
     476             :         //   lets - [0, constStart)
     477             :         // consts - [constStart, length)
     478             :         uint32_t constStart = 0;
     479             :         uint32_t length = 0;
     480             : 
     481       32293 :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     482             :         // scope.
     483             :         uint32_t nextFrameSlot = 0;
     484             : 
     485       11461 :         // The array of tagged JSAtom* names, allocated beyond the end of the
     486             :         // struct.
     487             :         TrailingNamesArray trailingNames;
     488             : 
     489             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     490             :         Data() = delete;
     491             : 
     492             :         void trace(JSTracer* trc);
     493             :     };
     494       22922 : 
     495             :     static LexicalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     496             :                                 uint32_t firstFrameSlot, HandleScope enclosing);
     497             : 
     498             :     template <XDRMode mode>
     499             :     static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     500             :                     MutableHandleScope scope);
     501             : 
     502             :   private:
     503             :     static LexicalScope* createWithData(JSContext* cx, ScopeKind kind,
     504             :                                         MutableHandle<UniquePtr<Data>> data,
     505             :                                         uint32_t firstFrameSlot, HandleScope enclosing);
     506             : 
     507             :     Data& data() {
     508             :         return *reinterpret_cast<Data*>(data_);
     509       90643 :     }
     510             : 
     511             :     const Data& data() const {
     512             :         return *reinterpret_cast<Data*>(data_);
     513             :     }
     514             : 
     515             :     static uint32_t nextFrameSlot(Scope* start);
     516             : 
     517             :   public:
     518             :     uint32_t firstFrameSlot() const;
     519             : 
     520             :     uint32_t nextFrameSlot() const {
     521             :         return data().nextFrameSlot;
     522             :     }
     523             : 
     524             :     // Returns an empty shape for extensible global and non-syntactic lexical
     525             :     // scopes.
     526             :     static Shape* getEmptyExtensibleEnvironmentShape(JSContext* cx);
     527             : };
     528             : 
     529             : template <>
     530             : inline bool
     531             : Scope::is<LexicalScope>() const
     532             : {
     533             :     return kind_ == ScopeKind::Lexical ||
     534             :            kind_ == ScopeKind::SimpleCatch ||
     535             :            kind_ == ScopeKind::Catch ||
     536             :            kind_ == ScopeKind::NamedLambda ||
     537             :            kind_ == ScopeKind::StrictNamedLambda;
     538             : }
     539             : 
     540             : //
     541             : // Scope corresponding to a function. Holds formal parameter names, special
     542       26334 : // internal names (see FunctionScope::isSpecialName), and, if the function
     543             : // parameters contain no expressions that might possibly be evaluated, the
     544             : // function's var bindings. For example, in these functions, the FunctionScope
     545             : // will store a/b/c bindings but not d/e/f bindings:
     546             : //
     547             : //   function f1(a, b) {
     548             : //     var c;
     549             : //     let e;
     550             : //     const f = 3;
     551             : //   }
     552             : //   function f2([a], b = 4, ...c) {
     553             : //     var d, e, f; // stored in VarScope
     554             : //   }
     555             : //
     556             : // Corresponds to CallObject on environment chain.
     557             : //
     558             : class FunctionScope : public Scope
     559             : {
     560             :     friend class GCMarker;
     561             :     friend class BindingIter;
     562             :     friend class PositionalFormalParameterIter;
     563             :     friend class Scope;
     564             :     static const ScopeKind classScopeKind_ = ScopeKind::Function;
     565             : 
     566             :   public:
     567             :     // Data is public because it is created by the
     568             :     // frontend. See Parser<FullParseHandler>::newFunctionScopeData.
     569             :     struct Data : BaseScopeData
     570             :     {
     571             :         // The canonical function of the scope, as during a scope walk we
     572             :         // often query properties of the JSFunction (e.g., is the function an
     573             :         // arrow).
     574             :         GCPtrFunction canonicalFunction = {};
     575             : 
     576             :         // If parameter expressions are present, parameters act like lexical
     577             :         // bindings.
     578       39249 :         bool hasParameterExprs = false;
     579             : 
     580             :         // Bindings are sorted by kind in both frames and environments.
     581             :         //
     582             :         // Positional formal parameter names are those that are not
     583             :         // destructured. They may be referred to by argument slots if
     584             :         // !script()->hasParameterExprs().
     585             :         //
     586       26250 :         // An argument slot that needs to be skipped due to being destructured
     587             :         // or having defaults will have a nullptr name in the name array to
     588             :         // advance the argument slot.
     589             :         //
     590       26334 :         // positional formals - [0, nonPositionalFormalStart)
     591       13167 :         //      other formals - [nonPositionalParamStart, varStart)
     592             :         //               vars - [varStart, length)
     593             :         uint16_t nonPositionalFormalStart = 0;
     594             :         uint16_t varStart = 0;
     595             :         uint32_t length = 0;
     596             : 
     597             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     598             :         // scope.
     599             :         uint32_t nextFrameSlot = 0;
     600             : 
     601             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     602             :         // struct.
     603             :         TrailingNamesArray trailingNames;
     604             : 
     605             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     606             :         Data() = delete;
     607             : 
     608             :         void trace(JSTracer* trc);
     609             :         Zone* zone() const;
     610             :     };
     611      137225 : 
     612             :     static FunctionScope* create(JSContext* cx, Handle<Data*> data,
     613             :                                  bool hasParameterExprs, bool needsEnvironment,
     614             :                                  HandleFunction fun, HandleScope enclosing);
     615      739670 : 
     616             :     static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun,
     617             :                                 HandleScope enclosing);
     618             : 
     619             :     template <XDRMode mode>
     620       30888 :     static XDRResult XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
     621             :                     MutableHandleScope scope);
     622             : 
     623             :   private:
     624     1888491 :     static FunctionScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
     625             :                                          bool hasParameterExprs, bool needsEnvironment,
     626             :                                          HandleFunction fun, HandleScope enclosing);
     627             : 
     628             :     Data& data() {
     629             :         return *reinterpret_cast<Data*>(data_);
     630      189456 :     }
     631             : 
     632             :     const Data& data() const {
     633             :         return *reinterpret_cast<Data*>(data_);
     634           2 :     }
     635             : 
     636             :   public:
     637             :     uint32_t nextFrameSlot() const {
     638             :         return data().nextFrameSlot;
     639             :     }
     640             : 
     641             :     JSFunction* canonicalFunction() const {
     642             :         return data().canonicalFunction;
     643             :     }
     644             : 
     645             :     JSScript* script() const;
     646             : 
     647             :     bool hasParameterExprs() const {
     648             :         return data().hasParameterExprs;
     649             :     }
     650             : 
     651             :     uint32_t numPositionalFormalParameters() const {
     652             :         return data().nonPositionalFormalStart;
     653             :     }
     654             : 
     655             :     static bool isSpecialName(JSContext* cx, JSAtom* name);
     656             : 
     657             :     static Shape* getEmptyEnvironmentShape(JSContext* cx, bool hasParameterExprs);
     658             : };
     659             : 
     660             : //
     661             : // Scope holding only vars. There are 2 kinds of VarScopes.
     662             : //
     663             : // FunctionBodyVar
     664             : //   Corresponds to the extra var scope present in functions with parameter
     665             : //   expressions. See examples in comment above FunctionScope.
     666             : //
     667             : // ParameterExpressionVar
     668             : //   Each parameter expression is evaluated in its own var environment. For
     669             : //   example, f() below will print 'fml', then 'global'. That's right.
     670             : //
     671             : //     var a = 'global';
     672             : //     function f(x = (eval(`var a = 'fml'`), a), y = a) {
     673             : //       print(x);
     674             : //       print(y);
     675             : //     };
     676             : //
     677             : // Corresponds to VarEnvironmentObject on environment chain.
     678             : //
     679             : class VarScope : public Scope
     680             : {
     681             :     friend class GCMarker;
     682             :     friend class BindingIter;
     683          59 :     friend class Scope;
     684             : 
     685             :   public:
     686             :     // Data is public because it is created by the
     687             :     // frontend. See Parser<FullParseHandler>::newVarScopeData.
     688             :     struct Data : BaseScopeData
     689             :     {
     690          97 :         // All bindings are vars.
     691             :         uint32_t length = 0;
     692             : 
     693             :         // Frame slots [firstFrameSlot(), nextFrameSlot) are live when this is
     694          76 :         // the innermost scope.
     695          38 :         uint32_t nextFrameSlot = 0;
     696             : 
     697             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     698             :         // struct.
     699             :         TrailingNamesArray trailingNames;
     700             : 
     701             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     702             :         Data() = delete;
     703             : 
     704             :         void trace(JSTracer* trc);
     705             :     };
     706             : 
     707             :     static VarScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     708             :                             uint32_t firstFrameSlot, bool needsEnvironment,
     709             :                             HandleScope enclosing);
     710             : 
     711             :     template <XDRMode mode>
     712         164 :     static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     713             :                     MutableHandleScope scope);
     714             : 
     715             :   private:
     716         121 :     static VarScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     717             :                                     uint32_t firstFrameSlot, bool needsEnvironment,
     718             :                                     HandleScope enclosing);
     719             : 
     720             :     Data& data() {
     721             :         return *reinterpret_cast<Data*>(data_);
     722             :     }
     723         242 : 
     724             :     const Data& data() const {
     725             :         return *reinterpret_cast<Data*>(data_);
     726             :     }
     727             : 
     728             :   public:
     729             :     uint32_t firstFrameSlot() const;
     730             : 
     731             :     uint32_t nextFrameSlot() const {
     732             :         return data().nextFrameSlot;
     733        5746 :     }
     734             : 
     735             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
     736             : };
     737             : 
     738             : template <>
     739             : inline bool
     740             : Scope::is<VarScope>() const
     741             : {
     742             :     return kind_ == ScopeKind::FunctionBodyVar || kind_ == ScopeKind::ParameterExpressionVar;
     743             : }
     744             : 
     745             : //
     746             : // Scope corresponding to both the global object scope and the global lexical
     747             : // scope.
     748             : //
     749             : // Both are extensible and are singletons across <script> tags, so these
     750             : // scopes are a fragment of the names in global scope. In other words, two
     751             : // global scripts may have two different GlobalScopes despite having the same
     752             : // GlobalObject.
     753             : //
     754             : // There are 2 kinds of GlobalScopes.
     755             : //
     756             : // Global
     757             : //   Corresponds to a GlobalObject and its global LexicalEnvironmentObject on
     758             : //   the environment chain.
     759             : //
     760             : // NonSyntactic
     761             : //   Corresponds to a non-GlobalObject created by the embedding on the
     762             : //   environment chain. This distinction is important for optimizations.
     763             : //
     764             : class GlobalScope : public Scope
     765             : {
     766             :     friend class Scope;
     767             :     friend class BindingIter;
     768             : 
     769             :   public:
     770             :     // Data is public because it is created by the frontend. See
     771             :     // Parser<FullParseHandler>::newGlobalScopeData.
     772             :     struct Data : BaseScopeData
     773             :     {
     774             :         // Bindings are sorted by kind.
     775             :         // `vars` includes top-level functions which is distinguished by a bit
     776             :         // on the BindingName.
     777             :         //
     778             :         //            vars - [0, letStart)
     779             :         //            lets - [letStart, constStart)
     780         544 :         //          consts - [constStart, length)
     781             :         uint32_t letStart = 0;
     782             :         uint32_t constStart = 0;
     783             :         uint32_t length = 0;
     784             : 
     785             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     786             :         // struct.
     787         862 :         TrailingNamesArray trailingNames;
     788             : 
     789             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     790             :         Data() = delete;
     791         636 : 
     792         318 :         void trace(JSTracer* trc);
     793             :     };
     794             : 
     795             :     static GlobalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data);
     796             : 
     797             :     static GlobalScope* createEmpty(JSContext* cx, ScopeKind kind) {
     798         154 :         return create(cx, kind, nullptr);
     799             :     }
     800             : 
     801             :     static GlobalScope* clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind);
     802             : 
     803             :     template <XDRMode mode>
     804             :     static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope);
     805             : 
     806             :   private:
     807             :     static GlobalScope* createWithData(JSContext* cx, ScopeKind kind,
     808             :                                        MutableHandle<UniquePtr<Data>> data);
     809             : 
     810             :     Data& data() {
     811        1999 :         return *reinterpret_cast<Data*>(data_);
     812             :     }
     813             : 
     814             :     const Data& data() const {
     815           0 :         return *reinterpret_cast<Data*>(data_);
     816             :     }
     817             : 
     818             :   public:
     819             :     bool isSyntactic() const {
     820           0 :         return kind() != ScopeKind::NonSyntactic;
     821             :     }
     822             : 
     823             :     bool hasBindings() const {
     824           0 :         return data().length > 0;
     825             :     }
     826             : };
     827             : 
     828             : template <>
     829             : inline bool
     830             : Scope::is<GlobalScope>() const
     831             : {
     832       48123 :     return kind_ == ScopeKind::Global || kind_ == ScopeKind::NonSyntactic;
     833             : }
     834             : 
     835             : //
     836             : // Scope of a 'with' statement. Has no bindings.
     837             : //
     838             : // Corresponds to a WithEnvironmentObject on the environment chain.
     839             : class WithScope : public Scope
     840             : {
     841             :     friend class Scope;
     842             :     static const ScopeKind classScopeKind_ = ScopeKind::With;
     843             : 
     844             :   public:
     845             :     static WithScope* create(JSContext* cx, HandleScope enclosing);
     846             : };
     847             : 
     848             : //
     849             : // Scope of an eval. Holds var bindings. There are 2 kinds of EvalScopes.
     850             : //
     851             : // StrictEval
     852             : //   A strict eval. Corresponds to a VarEnvironmentObject, where its var
     853             : //   bindings lives.
     854             : //
     855             : // Eval
     856             : //   A sloppy eval. This is an empty scope, used only in the frontend, to
     857             : //   detect redeclaration errors. It has no Environment. Any `var`s declared
     858             : //   in the eval code are bound on the nearest enclosing var environment.
     859             : //
     860             : class EvalScope : public Scope
     861             : {
     862             :     friend class Scope;
     863             :     friend class BindingIter;
     864             : 
     865             :   public:
     866             :     // Data is public because it is created by the frontend. See
     867             :     // Parser<FullParseHandler>::newEvalScopeData.
     868             :     struct Data : BaseScopeData
     869             :     {
     870             :         // All bindings in an eval script are 'var' bindings. The implicit
     871             :         // lexical scope around the eval is present regardless of strictness
     872             :         // and is its own LexicalScope.
     873             :         // `vars` includes top-level functions which is distinguished by a bit
     874             :         // on the BindingName.
     875             :         //
     876             :         //            vars - [0, length)
     877             :         uint32_t varStart = 0;
     878             :         uint32_t length = 0;
     879             : 
     880             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     881             :         // scope.
     882             :         uint32_t nextFrameSlot = 0;
     883             : 
     884             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     885             :         // struct.
     886             :         TrailingNamesArray trailingNames;
     887             : 
     888          18 :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     889             :         Data() = delete;
     890             : 
     891             :         void trace(JSTracer* trc);
     892             :     };
     893             : 
     894             :     static EvalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     895          33 :                              HandleScope enclosing);
     896             : 
     897             :     template <XDRMode mode>
     898             :     static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     899           0 :                     MutableHandleScope scope);
     900          15 : 
     901             :   private:
     902             :     static EvalScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     903             :                                      HandleScope enclosing);
     904             : 
     905             :     Data& data() {
     906             :         return *reinterpret_cast<Data*>(data_);
     907             :     }
     908             : 
     909             :     const Data& data() const {
     910             :         return *reinterpret_cast<Data*>(data_);
     911             :     }
     912             : 
     913             :   public:
     914             :     // Starting a scope, the nearest var scope that a direct eval can
     915           0 :     // introduce vars on.
     916             :     static Scope* nearestVarScopeForDirectEval(Scope* scope);
     917             : 
     918             :     uint32_t nextFrameSlot() const {
     919          19 :         return data().nextFrameSlot;
     920             :     }
     921             : 
     922             :     bool strict() const {
     923             :         return kind() == ScopeKind::StrictEval;
     924             :     }
     925             : 
     926             :     bool hasBindings() const {
     927             :         return data().length > 0;
     928          38 :     }
     929             : 
     930             :     bool isNonGlobal() const {
     931             :         if (strict())
     932           0 :             return true;
     933             :         return !nearestVarScopeForDirectEval(enclosing())->is<GlobalScope>();
     934             :     }
     935             : 
     936           0 :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
     937             : };
     938             : 
     939             : template <>
     940           0 : inline bool
     941             : Scope::is<EvalScope>() const
     942           0 : {
     943             :     return kind_ == ScopeKind::Eval || kind_ == ScopeKind::StrictEval;
     944             : }
     945             : 
     946             : //
     947             : // Scope corresponding to the toplevel script in an ES module.
     948             : //
     949             : // Like GlobalScopes, these scopes contain both vars and lexical bindings, as
     950             : // the treating of imports and exports requires putting them in one scope.
     951             : //
     952        7451 : // Corresponds to a ModuleEnvironmentObject on the environment chain.
     953             : //
     954             : class ModuleScope : public Scope
     955             : {
     956             :     friend class GCMarker;
     957             :     friend class BindingIter;
     958             :     friend class Scope;
     959             :     static const ScopeKind classScopeKind_ = ScopeKind::Module;
     960             : 
     961             :   public:
     962             :     // Data is public because it is created by the frontend. See
     963             :     // Parser<FullParseHandler>::newModuleScopeData.
     964             :     struct Data : BaseScopeData
     965             :     {
     966             :         // The module of the scope.
     967             :         GCPtr<ModuleObject*> module = {};
     968             : 
     969             :         // Bindings are sorted by kind.
     970             :         //
     971             :         // imports - [0, varStart)
     972             :         //    vars - [varStart, letStart)
     973           0 :         //    lets - [letStart, constStart)
     974             :         //  consts - [constStart, length)
     975             :         uint32_t varStart = 0;
     976             :         uint32_t letStart = 0;
     977             :         uint32_t constStart = 0;
     978             :         uint32_t length = 0;
     979             : 
     980             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     981             :         // scope.
     982             :         uint32_t nextFrameSlot = 0;
     983             : 
     984             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     985             :         // struct.
     986             :         TrailingNamesArray trailingNames;
     987             : 
     988             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
     989             :         Data() = delete;
     990             : 
     991             :         void trace(JSTracer* trc);
     992             :         Zone* zone() const;
     993             :     };
     994             : 
     995             :     static ModuleScope* create(JSContext* cx, Handle<Data*> data,
     996             :                                Handle<ModuleObject*> module, HandleScope enclosing);
     997           0 : 
     998             :   private:
     999             :     static ModuleScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
    1000             :                                        Handle<ModuleObject*> module, HandleScope enclosing);
    1001             : 
    1002             :     Data& data() {
    1003             :         return *reinterpret_cast<Data*>(data_);
    1004             :     }
    1005           0 : 
    1006             :     const Data& data() const {
    1007             :         return *reinterpret_cast<Data*>(data_);
    1008             :     }
    1009           0 : 
    1010           0 :   public:
    1011             :     uint32_t nextFrameSlot() const {
    1012             :         return data().nextFrameSlot;
    1013             :     }
    1014             : 
    1015             :     ModuleObject* module() const {
    1016             :         return data().module;
    1017             :     }
    1018             : 
    1019             :     JSScript* script() const;
    1020             : 
    1021           0 :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
    1022             : };
    1023             : 
    1024             : class WasmInstanceScope : public Scope
    1025           0 : {
    1026             :     friend class BindingIter;
    1027             :     friend class Scope;
    1028             :     static const ScopeKind classScopeKind_ = ScopeKind::WasmInstance;
    1029             : 
    1030           0 :   public:
    1031             :     struct Data : BaseScopeData
    1032             :     {
    1033             :         uint32_t memoriesStart = 0;
    1034           0 :         uint32_t globalsStart = 0;
    1035             :         uint32_t length = 0;
    1036             :         uint32_t nextFrameSlot = 0;
    1037             : 
    1038             :         // The wasm instance of the scope.
    1039             :         GCPtr<WasmInstanceObject*> instance = {};
    1040             : 
    1041             :         TrailingNamesArray trailingNames;
    1042             : 
    1043             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
    1044             :         Data() = delete;
    1045             : 
    1046             :         void trace(JSTracer* trc);
    1047             :     };
    1048             : 
    1049           0 :     static WasmInstanceScope* create(JSContext* cx, WasmInstanceObject* instance);
    1050             : 
    1051             :   private:
    1052             :     Data& data() {
    1053             :         return *reinterpret_cast<Data*>(data_);
    1054             :     }
    1055             : 
    1056             :     const Data& data() const {
    1057             :         return *reinterpret_cast<Data*>(data_);
    1058             :     }
    1059             : 
    1060             :   public:
    1061           0 :     WasmInstanceObject* instance() const {
    1062             :         return data().instance;
    1063             :     }
    1064             : 
    1065             :     uint32_t memoriesStart() const {
    1066             :         return data().memoriesStart;
    1067             :     }
    1068             : 
    1069             :     uint32_t globalsStart() const {
    1070           0 :         return data().globalsStart;
    1071             :     }
    1072             : 
    1073             :     uint32_t namesCount() const {
    1074             :         return data().length;
    1075           0 :     }
    1076             : 
    1077             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
    1078             : };
    1079           0 : 
    1080             : // Scope corresponding to the wasm function. A WasmFunctionScope is used by
    1081             : // Debugger only, and not for wasm execution.
    1082             : //
    1083             : class WasmFunctionScope : public Scope
    1084           0 : {
    1085             :     friend class BindingIter;
    1086             :     friend class Scope;
    1087             :     static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
    1088           0 : 
    1089             :   public:
    1090             :     struct Data : BaseScopeData
    1091             :     {
    1092           0 :         uint32_t length = 0;
    1093             :         uint32_t nextFrameSlot = 0;
    1094             :         uint32_t funcIndex = 0;
    1095             : 
    1096           0 :         TrailingNamesArray trailingNames;
    1097             : 
    1098             :         explicit Data(size_t nameCount) : trailingNames(nameCount) {}
    1099             :         Data() = delete;
    1100             : 
    1101             :         void trace(JSTracer* trc);
    1102             :     };
    1103             : 
    1104             :     static WasmFunctionScope* create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex);
    1105             : 
    1106             :   private:
    1107             :     Data& data() {
    1108             :         return *reinterpret_cast<Data*>(data_);
    1109             :     }
    1110             : 
    1111             :     const Data& data() const {
    1112             :         return *reinterpret_cast<Data*>(data_);
    1113             :     }
    1114             : 
    1115             :   public:
    1116             :     uint32_t funcIndex() const {
    1117             :         return data().funcIndex;
    1118             :     }
    1119             : 
    1120           0 :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
    1121             : };
    1122             : 
    1123             : //
    1124             : // An iterator for a Scope's bindings. This is the source of truth for frame
    1125             : // and environment object layout.
    1126             : //
    1127             : // It may be placed in GC containers; for example:
    1128             : //
    1129           0 : //   for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
    1130             : //     use(bi);
    1131             : //     SomeMayGCOperation();
    1132             : //     use(bi);
    1133             : //   }
    1134           0 : //
    1135             : class BindingIter
    1136             : {
    1137             :   protected:
    1138             :     // Bindings are sorted by kind. Because different Scopes have differently
    1139             :     // laid out Data for packing, BindingIter must handle all binding kinds.
    1140             :     //
    1141             :     // Kind ranges:
    1142             :     //
    1143             :     //            imports - [0, positionalFormalStart)
    1144             :     // positional formals - [positionalFormalStart, nonPositionalFormalStart)
    1145             :     //      other formals - [nonPositionalParamStart, varStart)
    1146             :     //               vars - [varStart, letStart)
    1147             :     //               lets - [letStart, constStart)
    1148             :     //             consts - [constStart, length)
    1149             :     //
    1150             :     // Access method when not closed over:
    1151             :     //
    1152             :     //            imports - name
    1153             :     // positional formals - argument slot
    1154             :     //      other formals - frame slot
    1155             :     //               vars - frame slot
    1156             :     //               lets - frame slot
    1157             :     //             consts - frame slot
    1158             :     //
    1159             :     // Access method when closed over:
    1160             :     //
    1161             :     //            imports - name
    1162             :     // positional formals - environment slot or name
    1163             :     //      other formals - environment slot or name
    1164             :     //               vars - environment slot or name
    1165             :     //               lets - environment slot or name
    1166             :     //             consts - environment slot or name
    1167             :     MOZ_INIT_OUTSIDE_CTOR uint32_t positionalFormalStart_;
    1168             :     MOZ_INIT_OUTSIDE_CTOR uint32_t nonPositionalFormalStart_;
    1169             :     MOZ_INIT_OUTSIDE_CTOR uint32_t varStart_;
    1170             :     MOZ_INIT_OUTSIDE_CTOR uint32_t letStart_;
    1171             :     MOZ_INIT_OUTSIDE_CTOR uint32_t constStart_;
    1172             :     MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
    1173             : 
    1174             :     MOZ_INIT_OUTSIDE_CTOR uint32_t index_;
    1175             : 
    1176             :     enum Flags : uint8_t {
    1177             :         CannotHaveSlots = 0,
    1178             :         CanHaveArgumentSlots = 1 << 0,
    1179             :         CanHaveFrameSlots = 1 << 1,
    1180             :         CanHaveEnvironmentSlots = 1 << 2,
    1181             : 
    1182             :         // See comment in settle below.
    1183             :         HasFormalParameterExprs = 1 << 3,
    1184             :         IgnoreDestructuredFormalParameters = 1 << 4,
    1185             : 
    1186             :         // Truly I hate named lambdas.
    1187             :         IsNamedLambda = 1 << 5
    1188             :     };
    1189             : 
    1190             :     static const uint8_t CanHaveSlotsMask = 0x7;
    1191             : 
    1192             :     MOZ_INIT_OUTSIDE_CTOR uint8_t flags_;
    1193             :     MOZ_INIT_OUTSIDE_CTOR uint16_t argumentSlot_;
    1194             :     MOZ_INIT_OUTSIDE_CTOR uint32_t frameSlot_;
    1195             :     MOZ_INIT_OUTSIDE_CTOR uint32_t environmentSlot_;
    1196             : 
    1197             :     MOZ_INIT_OUTSIDE_CTOR BindingName* names_;
    1198             : 
    1199             :     void init(uint32_t positionalFormalStart, uint32_t nonPositionalFormalStart,
    1200             :               uint32_t varStart, uint32_t letStart, uint32_t constStart,
    1201             :               uint8_t flags, uint32_t firstFrameSlot, uint32_t firstEnvironmentSlot,
    1202             :               BindingName* names, uint32_t length)
    1203             :     {
    1204             :         positionalFormalStart_ = positionalFormalStart;
    1205             :         nonPositionalFormalStart_ = nonPositionalFormalStart;
    1206             :         varStart_ = varStart;
    1207             :         letStart_ = letStart;
    1208             :         constStart_ = constStart;
    1209             :         length_ = length;
    1210             :         index_ = 0;
    1211             :         flags_ = flags;
    1212             :         argumentSlot_ = 0;
    1213             :         frameSlot_ = firstFrameSlot;
    1214             :         environmentSlot_ = firstEnvironmentSlot;
    1215             :         names_ = names;
    1216             : 
    1217             :         settle();
    1218             :     }
    1219             : 
    1220             :     void init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t flags);
    1221             :     void init(FunctionScope::Data& data, uint8_t flags);
    1222             :     void init(VarScope::Data& data, uint32_t firstFrameSlot);
    1223             :     void init(GlobalScope::Data& data);
    1224             :     void init(EvalScope::Data& data, bool strict);
    1225             :     void init(ModuleScope::Data& data);
    1226             :     void init(WasmInstanceScope::Data& data);
    1227             :     void init(WasmFunctionScope::Data& data);
    1228             : 
    1229             :     bool hasFormalParameterExprs() const {
    1230           0 :         return flags_ & HasFormalParameterExprs;
    1231           0 :     }
    1232      139764 : 
    1233           0 :     bool ignoreDestructuredFormalParameters() const {
    1234      139764 :         return flags_ & IgnoreDestructuredFormalParameters;
    1235      139764 :     }
    1236      139764 : 
    1237      139764 :     bool isNamedLambda() const {
    1238      139764 :         return flags_ & IsNamedLambda;
    1239      139764 :     }
    1240      139764 : 
    1241      139764 :     void increment() {
    1242             :         MOZ_ASSERT(!done());
    1243      139764 :         if (flags_ & CanHaveSlotsMask) {
    1244             :             if (canHaveArgumentSlots()) {
    1245             :                 if (index_ < nonPositionalFormalStart_) {
    1246             :                     MOZ_ASSERT(index_ >= positionalFormalStart_);
    1247             :                     argumentSlot_++;
    1248             :                 }
    1249             :             }
    1250             :             if (closedOver()) {
    1251             :                 // Imports must not be given known slots. They are
    1252             :                 // indirect bindings.
    1253             :                 MOZ_ASSERT(kind() != BindingKind::Import);
    1254             :                 MOZ_ASSERT(canHaveEnvironmentSlots());
    1255             :                 environmentSlot_++;
    1256             :             } else if (canHaveFrameSlots()) {
    1257             :                 // Usually positional formal parameters don't have frame
    1258             :                 // slots, except when there are parameter expressions, in
    1259             :                 // which case they act like lets.
    1260             :                 if (index_ >= nonPositionalFormalStart_ || (hasFormalParameterExprs() && name()))
    1261             :                     frameSlot_++;
    1262             :             }
    1263             :         }
    1264             :         index_++;
    1265             :     }
    1266             : 
    1267      144325 :     void settle() {
    1268      288650 :         if (ignoreDestructuredFormalParameters()) {
    1269           0 :             while (!done() && !name())
    1270           0 :                 increment();
    1271           0 :         }
    1272           0 :     }
    1273       71652 : 
    1274             :   public:
    1275             :     explicit BindingIter(Scope* scope);
    1276           0 :     explicit BindingIter(JSScript* script);
    1277             : 
    1278             :     BindingIter(LexicalScope::Data& data, uint32_t firstFrameSlot, bool isNamedLambda) {
    1279       32919 :         init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0);
    1280           0 :     }
    1281           0 : 
    1282      104442 :     BindingIter(FunctionScope::Data& data, bool hasParameterExprs) {
    1283             :         init(data,
    1284             :              IgnoreDestructuredFormalParameters |
    1285             :              (hasParameterExprs ? HasFormalParameterExprs : 0));
    1286           0 :     }
    1287       44446 : 
    1288             :     BindingIter(VarScope::Data& data, uint32_t firstFrameSlot) {
    1289             :         init(data, firstFrameSlot);
    1290      144326 :     }
    1291      144326 : 
    1292             :     explicit BindingIter(GlobalScope::Data& data) {
    1293      283661 :         init(data);
    1294           0 :     }
    1295           0 : 
    1296         417 :     explicit BindingIter(ModuleScope::Data& data) {
    1297             :         init(data);
    1298           0 :     }
    1299             : 
    1300             :     explicit BindingIter(WasmFunctionScope::Data& data) {
    1301             :         init(data);
    1302             :     }
    1303             : 
    1304           0 :     BindingIter(EvalScope::Data& data, bool strict) {
    1305           0 :         init(data, strict);
    1306             :     }
    1307             : 
    1308           0 :     explicit BindingIter(const BindingIter& bi) = default;
    1309           0 : 
    1310             :     bool done() const {
    1311       24754 :         return index_ == length_;
    1312             :     }
    1313             : 
    1314          85 :     explicit operator bool() const {
    1315          85 :         return !done();
    1316             :     }
    1317             : 
    1318         277 :     void operator++(int) {
    1319         277 :         increment();
    1320             :         settle();
    1321             :     }
    1322           0 : 
    1323           0 :     bool isLast() const {
    1324             :         MOZ_ASSERT(!done());
    1325             :         return index_ + 1 == length_;
    1326             :     }
    1327             : 
    1328             :     bool canHaveArgumentSlots() const {
    1329             :         return flags_ & CanHaveArgumentSlots;
    1330          18 :     }
    1331           0 : 
    1332             :     bool canHaveFrameSlots() const {
    1333             :         return flags_ & CanHaveFrameSlots;
    1334             :     }
    1335             : 
    1336             :     bool canHaveEnvironmentSlots() const {
    1337      781937 :         return flags_ & CanHaveEnvironmentSlots;
    1338             :     }
    1339             : 
    1340             :     JSAtom* name() const {
    1341           0 :         MOZ_ASSERT(!done());
    1342             :         return names_[index_].name();
    1343             :     }
    1344             : 
    1345      143914 :     bool closedOver() const {
    1346      143914 :         MOZ_ASSERT(!done());
    1347             :         return names_[index_].closedOver();
    1348             :     }
    1349           0 : 
    1350           0 :     BindingLocation location() const {
    1351           0 :         MOZ_ASSERT(!done());
    1352             :         if (!(flags_ & CanHaveSlotsMask))
    1353             :             return BindingLocation::Global();
    1354             :         if (index_ < positionalFormalStart_)
    1355             :             return BindingLocation::Import();
    1356             :         if (closedOver()) {
    1357             :             MOZ_ASSERT(canHaveEnvironmentSlots());
    1358             :             return BindingLocation::Environment(environmentSlot_);
    1359             :         }
    1360             :         if (index_ < nonPositionalFormalStart_ && canHaveArgumentSlots())
    1361             :             return BindingLocation::Argument(argumentSlot_);
    1362             :         if (canHaveFrameSlots())
    1363             :             return BindingLocation::Frame(frameSlot_);
    1364             :         MOZ_ASSERT(isNamedLambda());
    1365             :         return BindingLocation::NamedLambdaCallee();
    1366           0 :     }
    1367           0 : 
    1368           0 :     BindingKind kind() const {
    1369             :         MOZ_ASSERT(!done());
    1370             :         if (index_ < positionalFormalStart_)
    1371      261577 :             return BindingKind::Import;
    1372           0 :         if (index_ < varStart_) {
    1373           0 :             // When the parameter list has expressions, the parameters act
    1374             :             // like lexical bindings and have TDZ.
    1375             :             if (hasFormalParameterExprs())
    1376           0 :                 return BindingKind::Let;
    1377           0 :             return BindingKind::FormalParameter;
    1378           0 :         }
    1379             :         if (index_ < letStart_)
    1380           0 :             return BindingKind::Var;
    1381             :         if (index_ < constStart_)
    1382       70088 :             return BindingKind::Let;
    1383       33049 :         if (isNamedLambda())
    1384           0 :             return BindingKind::NamedLambdaCallee;
    1385             :         return BindingKind::Const;
    1386           0 :     }
    1387       11155 : 
    1388           0 :     bool isTopLevelFunction() const {
    1389       24678 :         MOZ_ASSERT(!done());
    1390        1207 :         bool result = names_[index_].isTopLevelFunction();
    1391             :         MOZ_ASSERT_IF(result, kind() == BindingKind::Var);
    1392             :         return result;
    1393             :     }
    1394       93744 : 
    1395           0 :     bool hasArgumentSlot() const {
    1396       93744 :         MOZ_ASSERT(!done());
    1397             :         if (hasFormalParameterExprs())
    1398       93746 :             return false;
    1399             :         return index_ >= positionalFormalStart_ && index_ < nonPositionalFormalStart_;
    1400             :     }
    1401           0 : 
    1402             :     uint16_t argumentSlot() const {
    1403       28664 :         MOZ_ASSERT(canHaveArgumentSlots());
    1404             :         return mozilla::AssertedCast<uint16_t>(index_);
    1405           0 :     }
    1406             : 
    1407       32835 :     uint32_t nextFrameSlot() const {
    1408             :         MOZ_ASSERT(canHaveFrameSlots());
    1409           0 :         return frameSlot_;
    1410             :     }
    1411           0 : 
    1412             :     uint32_t nextEnvironmentSlot() const {
    1413             :         MOZ_ASSERT(canHaveEnvironmentSlots());
    1414        3855 :         return environmentSlot_;
    1415        7710 :     }
    1416           0 : 
    1417           0 :     void trace(JSTracer* trc);
    1418           0 : };
    1419             : 
    1420             : void DumpBindings(JSContext* cx, Scope* scope);
    1421           0 : JSAtom* FrameSlotName(JSScript* script, jsbytecode* pc);
    1422           0 : 
    1423           0 : //
    1424             : // A refinement BindingIter that only iterates over positional formal
    1425           0 : // parameters of a function.
    1426             : //
    1427             : class PositionalFormalParameterIter : public BindingIter
    1428           0 : {
    1429       48858 :     void settle() {
    1430       48858 :         if (index_ >= nonPositionalFormalStart_)
    1431             :             index_ = length_;
    1432             :     }
    1433       78523 : 
    1434       78523 :   public:
    1435       78523 :     explicit PositionalFormalParameterIter(JSScript* script);
    1436             : 
    1437             :     void operator++(int) {
    1438       63989 :         BindingIter::operator++(1);
    1439       63989 :         settle();
    1440       63989 :     }
    1441             : 
    1442             :     bool isDestructured() const {
    1443             :         return !name();
    1444             :     }
    1445             : };
    1446             : 
    1447             : //
    1448             : // Iterator for walking the scope chain.
    1449             : //
    1450             : // It may be placed in GC containers; for example:
    1451             : //
    1452             : //   for (Rooted<ScopeIter> si(cx, ScopeIter(scope)); si; si++) {
    1453             : //     use(si);
    1454             : //     SomeMayGCOperation();
    1455             : //     use(si);
    1456       90619 : //   }
    1457           0 : //
    1458             : class MOZ_STACK_CLASS ScopeIter
    1459             : {
    1460             :     Scope* scope_;
    1461             : 
    1462             :   public:
    1463       44181 :     explicit ScopeIter(Scope* scope)
    1464       88362 :       : scope_(scope)
    1465       44181 :     { }
    1466       44181 : 
    1467             :     explicit ScopeIter(JSScript* script);
    1468             : 
    1469           1 :     explicit ScopeIter(const ScopeIter& si)
    1470             :       : scope_(si.scope_)
    1471             :     { }
    1472             : 
    1473             :     bool done() const {
    1474             :         return !scope_;
    1475             :     }
    1476             : 
    1477             :     explicit operator bool() const {
    1478             :         return !done();
    1479             :     }
    1480             : 
    1481             :     void operator++(int) {
    1482             :         MOZ_ASSERT(!done());
    1483             :         scope_ = scope_->enclosing();
    1484             :     }
    1485             : 
    1486             :     Scope* scope() const {
    1487             :         MOZ_ASSERT(!done());
    1488             :         return scope_;
    1489             :     }
    1490       66019 : 
    1491             :     ScopeKind kind() const {
    1492             :         MOZ_ASSERT(!done());
    1493             :         return scope_->kind();
    1494             :     }
    1495             : 
    1496           0 :     // Returns the shape of the environment if it is known. It is possible to
    1497             :     // hasSyntacticEnvironment and to have no known shape, e.g., eval.
    1498             :     Shape* environmentShape() const {
    1499             :         return scope()->environmentShape();
    1500           0 :     }
    1501             : 
    1502             :     // Returns whether this scope has a syntactic environment (i.e., an
    1503             :     // Environment that isn't a non-syntactic With or NonSyntacticVariables)
    1504       81284 :     // on the environment chain.
    1505             :     bool hasSyntacticEnvironment() const;
    1506             : 
    1507           0 :     void trace(JSTracer* trc) {
    1508       54662 :         if (scope_)
    1509      109324 :             TraceRoot(trc, &scope_, "scope iter scope");
    1510       54662 :     }
    1511             : };
    1512      267753 : 
    1513           0 : //
    1514      267753 : // Specializations of Rooted containers for the iterators.
    1515             : //
    1516             : 
    1517      118359 : template <typename Wrapper>
    1518      118359 : class WrappedPtrOperations<BindingIter, Wrapper>
    1519      118359 : {
    1520             :     const BindingIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
    1521             : 
    1522             :   public:
    1523             :     bool done() const { return iter().done(); }
    1524             :     explicit operator bool() const { return !done(); }
    1525        5200 :     bool isLast() const { return iter().isLast(); }
    1526             :     bool canHaveArgumentSlots() const { return iter().canHaveArgumentSlots(); }
    1527             :     bool canHaveFrameSlots() const { return iter().canHaveFrameSlots(); }
    1528             :     bool canHaveEnvironmentSlots() const { return iter().canHaveEnvironmentSlots(); }
    1529             :     JSAtom* name() const { return iter().name(); }
    1530             :     bool closedOver() const { return iter().closedOver(); }
    1531             :     BindingLocation location() const { return iter().location(); }
    1532             :     BindingKind kind() const { return iter().kind(); }
    1533           0 :     bool isTopLevelFunction() const { return iter().isTopLevelFunction(); }
    1534           0 :     bool hasArgumentSlot() const { return iter().hasArgumentSlot(); }
    1535           0 :     uint16_t argumentSlot() const { return iter().argumentSlot(); }
    1536           0 :     uint32_t nextFrameSlot() const { return iter().nextFrameSlot(); }
    1537             :     uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); }
    1538             : };
    1539             : 
    1540             : template <typename Wrapper>
    1541             : class MutableWrappedPtrOperations<BindingIter, Wrapper>
    1542             :   : public WrappedPtrOperations<BindingIter, Wrapper>
    1543             : {
    1544             :     BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); }
    1545             : 
    1546           0 :   public:
    1547             :     void operator++(int) { iter().operator++(1); }
    1548             : };
    1549        4320 : 
    1550        4320 : template <typename Wrapper>
    1551           0 : class WrappedPtrOperations<ScopeIter, Wrapper>
    1552             : {
    1553             :     const ScopeIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
    1554             : 
    1555           0 :   public:
    1556           0 :     bool done() const { return iter().done(); }
    1557           0 :     explicit operator bool() const { return !done(); }
    1558           0 :     Scope* scope() const { return iter().scope(); }
    1559         400 :     ScopeKind kind() const { return iter().kind(); }
    1560             :     Shape* environmentShape() const { return iter().environmentShape(); }
    1561             :     bool hasSyntacticEnvironment() const { return iter().hasSyntacticEnvironment(); }
    1562             : };
    1563             : 
    1564             : template <typename Wrapper>
    1565             : class MutableWrappedPtrOperations<ScopeIter, Wrapper>
    1566             :   : public WrappedPtrOperations<ScopeIter, Wrapper>
    1567           0 : {
    1568             :     ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); }
    1569             : 
    1570           0 :   public:
    1571             :     void operator++(int) { iter().operator++(1); }
    1572             : };
    1573           0 : 
    1574             : } // namespace js
    1575             : 
    1576             : namespace JS {
    1577             : 
    1578             : template <>
    1579           0 : struct GCPolicy<js::ScopeKind> : public IgnoreGCPolicy<js::ScopeKind>
    1580             : { };
    1581             : 
    1582           0 : template <typename T>
    1583       67976 : struct ScopeDataGCPolicy : public NonGCPointerPolicy<T> {};
    1584       99312 : 
    1585           0 : #define DEFINE_SCOPE_DATA_GCPOLICY(Data)                        \
    1586             :     template <>                                                 \
    1587       51739 :     struct MapTypeToRootKind<Data*> {                           \
    1588             :         static const RootKind kind = RootKind::Traceable;       \
    1589             :     };                                                          \
    1590             :     template <>                                                 \
    1591       15636 :     struct GCPolicy<Data*> : public ScopeDataGCPolicy<Data*>    \
    1592             :     { }
    1593             : 
    1594       17334 : DEFINE_SCOPE_DATA_GCPOLICY(js::LexicalScope::Data);
    1595             : DEFINE_SCOPE_DATA_GCPOLICY(js::FunctionScope::Data);
    1596             : DEFINE_SCOPE_DATA_GCPOLICY(js::VarScope::Data);
    1597       17334 : DEFINE_SCOPE_DATA_GCPOLICY(js::GlobalScope::Data);
    1598             : DEFINE_SCOPE_DATA_GCPOLICY(js::EvalScope::Data);
    1599             : DEFINE_SCOPE_DATA_GCPOLICY(js::ModuleScope::Data);
    1600             : DEFINE_SCOPE_DATA_GCPOLICY(js::WasmFunctionScope::Data);
    1601             : 
    1602             : #undef DEFINE_SCOPE_DATA_GCPOLICY
    1603             : 
    1604             : // Scope data that contain GCPtrs must use the correct DeletePolicy.
    1605             : 
    1606             : template <>
    1607             : struct DeletePolicy<js::FunctionScope::Data>
    1608             :   : public js::GCManagedDeletePolicy<js::FunctionScope::Data>
    1609             : {};
    1610             : 
    1611             : template <>
    1612             : struct DeletePolicy<js::ModuleScope::Data>
    1613             :   : public js::GCManagedDeletePolicy<js::ModuleScope::Data>
    1614             : {};
    1615             : 
    1616             : template <>
    1617             : struct DeletePolicy<js::WasmInstanceScope::Data>
    1618             :   : public js::GCManagedDeletePolicy<js::WasmInstanceScope::Data>
    1619             : { };
    1620             : 
    1621             : namespace ubi {
    1622             : 
    1623             : template <>
    1624             : class Concrete<js::Scope> : TracerConcrete<js::Scope>
    1625             : {
    1626             :   protected:
    1627             :     explicit Concrete(js::Scope* ptr) : TracerConcrete<js::Scope>(ptr) { }
    1628             : 
    1629             :   public:
    1630             :     static void construct(void* storage, js::Scope* ptr) {
    1631             :         new (storage) Concrete(ptr);
    1632             :     }
    1633             : 
    1634             :     CoarseType coarseType() const final { return CoarseType::Script; }
    1635             : 
    1636             :     Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
    1637             : 
    1638             :     const char16_t* typeName() const override { return concreteTypeName; }
    1639             :     static const char16_t concreteTypeName[];
    1640             : };
    1641             : 
    1642             : } // namespace ubi
    1643             : } // namespace JS
    1644             : 
    1645             : #endif // vm_Scope_h

Generated by: LCOV version 1.13-14-ga5dd952