LCOV - code coverage report
Current view: top level - js/src/vm - Scope.h (source / functions) Hit Total Coverage
Test: output.info Lines: 332 398 83.4 %
Date: 2017-07-14 16:53:18 Functions: 143 192 74.5 %
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/Variant.h"
      12             : 
      13             : #include "jsobj.h"
      14             : #include "jsopcode.h"
      15             : 
      16             : #include "gc/Heap.h"
      17             : #include "gc/Policy.h"
      18             : #include "js/UbiNode.h"
      19             : #include "js/UniquePtr.h"
      20             : #include "vm/Xdr.h"
      21             : 
      22             : namespace js {
      23             : 
      24             : class ModuleObject;
      25             : class Scope;
      26             : 
      27             : enum class BindingKind : uint8_t
      28             : {
      29             :     Import,
      30             :     FormalParameter,
      31             :     Var,
      32             :     Let,
      33             :     Const,
      34             : 
      35             :     // So you think named lambda callee names are consts? Nope! They don't
      36             :     // throw when being assigned to in sloppy mode.
      37             :     NamedLambdaCallee
      38             : };
      39             : 
      40             : static inline bool
      41       77260 : BindingKindIsLexical(BindingKind kind)
      42             : {
      43       77260 :     return kind == BindingKind::Let || kind == BindingKind::Const;
      44             : }
      45             : 
      46             : enum class ScopeKind : uint8_t
      47             : {
      48             :     // FunctionScope
      49             :     Function,
      50             : 
      51             :     // VarScope
      52             :     FunctionBodyVar,
      53             :     ParameterExpressionVar,
      54             : 
      55             :     // LexicalScope
      56             :     Lexical,
      57             :     SimpleCatch,
      58             :     Catch,
      59             :     NamedLambda,
      60             :     StrictNamedLambda,
      61             : 
      62             :     // WithScope
      63             :     With,
      64             : 
      65             :     // EvalScope
      66             :     Eval,
      67             :     StrictEval,
      68             : 
      69             :     // GlobalScope
      70             :     Global,
      71             :     NonSyntactic,
      72             : 
      73             :     // ModuleScope
      74             :     Module,
      75             : 
      76             :     // WasmFunctionScope
      77             :     WasmFunction
      78             : };
      79             : 
      80             : static inline bool
      81           0 : ScopeKindIsCatch(ScopeKind kind)
      82             : {
      83           0 :     return kind == ScopeKind::SimpleCatch || kind == ScopeKind::Catch;
      84             : }
      85             : 
      86             : static inline bool
      87       15324 : ScopeKindIsInBody(ScopeKind kind)
      88             : {
      89        7882 :     return kind == ScopeKind::Lexical ||
      90        6480 :            kind == ScopeKind::SimpleCatch ||
      91        6480 :            kind == ScopeKind::Catch ||
      92        6480 :            kind == ScopeKind::With ||
      93       21596 :            kind == ScopeKind::FunctionBodyVar ||
      94       15324 :            kind == ScopeKind::ParameterExpressionVar;
      95             : }
      96             : 
      97             : const char* BindingKindString(BindingKind kind);
      98             : const char* ScopeKindString(ScopeKind kind);
      99             : 
     100             : class BindingName
     101             : {
     102             :     // A JSAtom* with its low bit used as a tag for whether it is closed over
     103             :     // (i.e., exists in the environment shape).
     104             :     uintptr_t bits_;
     105             : 
     106             :     static const uintptr_t ClosedOverFlag = 0x1;
     107             :     static const uintptr_t FlagMask = 0x1;
     108             : 
     109             :   public:
     110       24374 :     BindingName()
     111       24374 :       : bits_(0)
     112       24374 :     { }
     113             : 
     114       72881 :     BindingName(JSAtom* name, bool closedOver)
     115       72881 :       : bits_(uintptr_t(name) | (closedOver ? ClosedOverFlag : 0x0))
     116       72881 :     { }
     117             : 
     118      236685 :     JSAtom* name() const {
     119      236685 :         return reinterpret_cast<JSAtom*>(bits_ & ~FlagMask);
     120             :     }
     121             : 
     122      210842 :     bool closedOver() const {
     123      210842 :         return bits_ & ClosedOverFlag;
     124             :     }
     125             : 
     126             :     void trace(JSTracer* trc);
     127             : };
     128             : 
     129             : class BindingLocation
     130             : {
     131             :   public:
     132             :     enum class Kind {
     133             :         Global,
     134             :         Argument,
     135             :         Frame,
     136             :         Environment,
     137             :         Import,
     138             :         NamedLambdaCallee
     139             :     };
     140             : 
     141             :   private:
     142             :     Kind kind_;
     143             :     uint32_t slot_;
     144             : 
     145       52477 :     BindingLocation(Kind kind, uint32_t slot)
     146       52477 :       : kind_(kind),
     147       52477 :         slot_(slot)
     148       52477 :     { }
     149             : 
     150             :   public:
     151        2841 :     static BindingLocation Global() {
     152        2841 :         return BindingLocation(Kind::Global, UINT32_MAX);
     153             :     }
     154             : 
     155        6207 :     static BindingLocation Argument(uint16_t slot) {
     156        6207 :         return BindingLocation(Kind::Argument, slot);
     157             :     }
     158             : 
     159       13753 :     static BindingLocation Frame(uint32_t slot) {
     160       13753 :         MOZ_ASSERT(slot < LOCALNO_LIMIT);
     161       13753 :         return BindingLocation(Kind::Frame, slot);
     162             :     }
     163             : 
     164       29293 :     static BindingLocation Environment(uint32_t slot) {
     165       29293 :         MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
     166       29293 :         return BindingLocation(Kind::Environment, slot);
     167             :     }
     168             : 
     169           0 :     static BindingLocation Import() {
     170           0 :         return BindingLocation(Kind::Import, UINT32_MAX);
     171             :     }
     172             : 
     173         384 :     static BindingLocation NamedLambdaCallee() {
     174         384 :         return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
     175             :     }
     176             : 
     177             :     bool operator==(const BindingLocation& other) const {
     178             :         return kind_ == other.kind_ && slot_ == other.slot_;
     179             :     }
     180             : 
     181             :     bool operator!=(const BindingLocation& other) const {
     182             :         return !operator==(other);
     183             :     }
     184             : 
     185       42876 :     Kind kind() const {
     186       42876 :         return kind_;
     187             :     }
     188             : 
     189       30263 :     uint32_t slot() const {
     190       30263 :         MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
     191       30263 :         return slot_;
     192             :     }
     193             : 
     194        5459 :     uint16_t argumentSlot() const {
     195        5459 :         MOZ_ASSERT(kind_ == Kind::Argument);
     196        5459 :         return mozilla::AssertedCast<uint16_t>(slot_);
     197             :     }
     198             : };
     199             : 
     200             : //
     201             : // Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
     202             : //
     203             : template <typename Wrapper>
     204      337542 : class WrappedPtrOperations<Scope*, Wrapper>
     205             : {
     206             :   public:
     207             :     template <class U>
     208       31442 :     JS::Handle<U*> as() const {
     209       31442 :         const Wrapper& self = *static_cast<const Wrapper*>(this);
     210       31442 :         MOZ_ASSERT_IF(self, self->template is<U>());
     211       31442 :         return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
     212             :     }
     213             : };
     214             : 
     215             : //
     216             : // The base class of all Scopes.
     217             : //
     218             : class Scope : public js::gc::TenuredCell
     219             : {
     220             :     friend class GCMarker;
     221             : 
     222             :     // The kind determines data_.
     223             :     ScopeKind kind_;
     224             : 
     225             :     // The enclosing scope or nullptr.
     226             :     GCPtrScope enclosing_;
     227             : 
     228             :     // If there are any aliased bindings, the shape for the
     229             :     // EnvironmentObject. Otherwise nullptr.
     230             :     GCPtrShape environmentShape_;
     231             : 
     232             :   protected:
     233             :     uintptr_t data_;
     234             : 
     235       42341 :     Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
     236       42341 :       : kind_(kind),
     237             :         enclosing_(enclosing),
     238             :         environmentShape_(environmentShape),
     239       42341 :         data_(0)
     240       42341 :     { }
     241             : 
     242             :     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
     243             :                          HandleShape envShape);
     244             : 
     245             :     template <typename T, typename D>
     246             :     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
     247             :                          HandleShape envShape, mozilla::UniquePtr<T, D> data);
     248             : 
     249             :     template <typename ConcreteScope, XDRMode mode>
     250             :     static bool XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
     251             :                                      MutableHandle<typename ConcreteScope::Data*> data);
     252             : 
     253             :     Shape* maybeCloneEnvironmentShape(JSContext* cx);
     254             : 
     255             :     template <typename T, typename D>
     256       42340 :     void initData(mozilla::UniquePtr<T, D> data) {
     257       42340 :         MOZ_ASSERT(!data_);
     258       42340 :         data_ = reinterpret_cast<uintptr_t>(data.release());
     259       42340 :     }
     260             : 
     261             :   public:
     262             :     static const JS::TraceKind TraceKind = JS::TraceKind::Scope;
     263             : 
     264             :     template <typename T>
     265     1436561 :     bool is() const {
     266     1436561 :         return kind_ == T::classScopeKind_;
     267             :     }
     268             : 
     269             :     template <typename T>
     270      796598 :     T& as() {
     271      796598 :         MOZ_ASSERT(this->is<T>());
     272      796600 :         return *static_cast<T*>(this);
     273             :     }
     274             : 
     275             :     template <typename T>
     276             :     const T& as() const {
     277             :         MOZ_ASSERT(this->is<T>());
     278             :         return *static_cast<const T*>(this);
     279             :     }
     280             : 
     281      476963 :     ScopeKind kind() const {
     282      476963 :         return kind_;
     283             :     }
     284             : 
     285      153690 :     Scope* enclosing() const {
     286      153690 :         return enclosing_;
     287             :     }
     288             : 
     289       70881 :     Shape* environmentShape() const {
     290       70881 :         return environmentShape_;
     291             :     }
     292             : 
     293      132036 :     bool hasEnvironment() const {
     294      132036 :         switch (kind()) {
     295             :           case ScopeKind::With:
     296             :           case ScopeKind::Global:
     297             :           case ScopeKind::NonSyntactic:
     298       27928 :             return true;
     299             :           default:
     300             :             // If there's a shape, an environment must be created for this scope.
     301      104108 :             return environmentShape_ != nullptr;
     302             :         }
     303             :     }
     304             : 
     305             :     uint32_t chainLength() const;
     306             :     uint32_t environmentChainLength() const;
     307             : 
     308             :     template <typename T>
     309             :     bool hasOnChain() const {
     310             :         for (const Scope* it = this; it; it = it->enclosing()) {
     311             :             if (it->is<T>())
     312             :                 return true;
     313             :         }
     314             :         return false;
     315             :     }
     316             : 
     317       15420 :     bool hasOnChain(ScopeKind kind) const {
     318       50842 :         for (const Scope* it = this; it; it = it->enclosing()) {
     319       37449 :             if (it->kind() == kind)
     320        2027 :                 return true;
     321             :         }
     322       13393 :         return false;
     323             :     }
     324             : 
     325             :     static Scope* clone(JSContext* cx, HandleScope scope, HandleScope enclosing);
     326             : 
     327             :     void traceChildren(JSTracer* trc);
     328             :     void finalize(FreeOp* fop);
     329             : 
     330             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     331             : 
     332             :     void dump();
     333             : };
     334             : 
     335             : //
     336             : // A lexical scope that holds let and const bindings. There are 4 kinds of
     337             : // LexicalScopes.
     338             : //
     339             : // Lexical
     340             : //   A plain lexical scope.
     341             : //
     342             : // SimpleCatch
     343             : //   Holds the single catch parameter of a catch block.
     344             : //
     345             : // Catch
     346             : //   Holds the catch parameters (and only the catch parameters) of a catch
     347             : //   block.
     348             : //
     349             : // NamedLambda
     350             : // StrictNamedLambda
     351             : //   Holds the single name of the callee for a named lambda expression.
     352             : //
     353             : // All kinds of LexicalScopes correspond to LexicalEnvironmentObjects on the
     354             : // environment chain.
     355             : //
     356             : class LexicalScope : public Scope
     357             : {
     358             :     friend class Scope;
     359             :     friend class BindingIter;
     360             : 
     361             :   public:
     362             :     // Data is public because it is created by the frontend. See
     363             :     // Parser<FullParseHandler>::newLexicalScopeData.
     364        6988 :     struct Data
     365             :     {
     366             :         // Bindings are sorted by kind in both frames and environments.
     367             :         //
     368             :         //   lets - [0, constStart)
     369             :         // consts - [constStart, length)
     370             :         uint32_t constStart;
     371             :         uint32_t length;
     372             : 
     373             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     374             :         // scope.
     375             :         uint32_t nextFrameSlot;
     376             : 
     377             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     378             :         // struct.
     379             :         BindingName names[1];
     380             : 
     381             :         void trace(JSTracer* trc);
     382             :     };
     383             : 
     384       19950 :     static size_t sizeOfData(uint32_t length) {
     385       19950 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     386             :     }
     387             : 
     388        9681 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     389        9681 :         *names = data->names;
     390        9681 :         *length = data->length;
     391        9681 :     }
     392             : 
     393             :     static LexicalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     394             :                                 uint32_t firstFrameSlot, HandleScope enclosing);
     395             : 
     396             :     template <XDRMode mode>
     397             :     static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     398             :                     MutableHandleScope scope);
     399             : 
     400             :   private:
     401             :     static LexicalScope* createWithData(JSContext* cx, ScopeKind kind,
     402             :                                         MutableHandle<UniquePtr<Data>> data,
     403             :                                         uint32_t firstFrameSlot, HandleScope enclosing);
     404             : 
     405       19317 :     Data& data() {
     406       19317 :         return *reinterpret_cast<Data*>(data_);
     407             :     }
     408             : 
     409        7828 :     const Data& data() const {
     410        7828 :         return *reinterpret_cast<Data*>(data_);
     411             :     }
     412             : 
     413             :     static uint32_t nextFrameSlot(Scope* start);
     414             : 
     415             :   public:
     416             :     uint32_t firstFrameSlot() const;
     417             : 
     418        7828 :     uint32_t nextFrameSlot() const {
     419        7828 :         return data().nextFrameSlot;
     420             :     }
     421             : 
     422             :     // Returns an empty shape for extensible global and non-syntactic lexical
     423             :     // scopes.
     424             :     static Shape* getEmptyExtensibleEnvironmentShape(JSContext* cx);
     425             : };
     426             : 
     427             : template <>
     428             : inline bool
     429       73990 : Scope::is<LexicalScope>() const
     430             : {
     431      101972 :     return kind_ == ScopeKind::Lexical ||
     432       51598 :            kind_ == ScopeKind::SimpleCatch ||
     433       47232 :            kind_ == ScopeKind::Catch ||
     434      113070 :            kind_ == ScopeKind::NamedLambda ||
     435       89454 :            kind_ == ScopeKind::StrictNamedLambda;
     436             : }
     437             : 
     438             : //
     439             : // Scope corresponding to a function. Holds formal parameter names, special
     440             : // internal names (see FunctionScope::isSpecialName), and, if the function
     441             : // parameters contain no expressions that might possibly be evaluated, the
     442             : // function's var bindings. For example, in these functions, the FunctionScope
     443             : // will store a/b/c bindings but not d/e/f bindings:
     444             : //
     445             : //   function f1(a, b) {
     446             : //     var c;
     447             : //     let e;
     448             : //     const f = 3;
     449             : //   }
     450             : //   function f2([a], b = 4, ...c) {
     451             : //     var d, e, f; // stored in VarScope
     452             : //   }
     453             : //
     454             : // Corresponds to CallObject on environment chain.
     455             : //
     456             : class FunctionScope : public Scope
     457             : {
     458             :     friend class GCMarker;
     459             :     friend class BindingIter;
     460             :     friend class PositionalFormalParameterIter;
     461             :     friend class Scope;
     462             :     static const ScopeKind classScopeKind_ = ScopeKind::Function;
     463             : 
     464             :   public:
     465             :     // Data is public because it is created by the
     466             :     // frontend. See Parser<FullParseHandler>::newFunctionScopeData.
     467       24110 :     struct Data
     468             :     {
     469             :         // The canonical function of the scope, as during a scope walk we
     470             :         // often query properties of the JSFunction (e.g., is the function an
     471             :         // arrow).
     472             :         GCPtrFunction canonicalFunction;
     473             : 
     474             :         // If parameter expressions are present, parameters act like lexical
     475             :         // bindings.
     476             :         bool hasParameterExprs;
     477             : 
     478             :         // Bindings are sorted by kind in both frames and environments.
     479             :         //
     480             :         // Positional formal parameter names are those that are not
     481             :         // destructured. They may be referred to by argument slots if
     482             :         // !script()->hasParameterExprs().
     483             :         //
     484             :         // An argument slot that needs to be skipped due to being destructured
     485             :         // or having defaults will have a nullptr name in the name array to
     486             :         // advance the argument slot.
     487             :         //
     488             :         // positional formals - [0, nonPositionalFormalStart)
     489             :         //      other formals - [nonPositionalParamStart, varStart)
     490             :         //               vars - [varStart, length)
     491             :         uint16_t nonPositionalFormalStart;
     492             :         uint16_t varStart;
     493             :         uint32_t length;
     494             : 
     495             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     496             :         // scope.
     497             :         uint32_t nextFrameSlot;
     498             : 
     499             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     500             :         // struct.
     501             :         BindingName names[1];
     502             : 
     503             :         void trace(JSTracer* trc);
     504             :         Zone* zone() const;
     505             :     };
     506             : 
     507       28682 :     static size_t sizeOfData(uint32_t length) {
     508       28682 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     509             :     }
     510             : 
     511       14028 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     512       14028 :         *names = data->names;
     513       14028 :         *length = data->length;
     514       14028 :     }
     515             : 
     516             :     static FunctionScope* create(JSContext* cx, Handle<Data*> data,
     517             :                                  bool hasParameterExprs, bool needsEnvironment,
     518             :                                  HandleFunction fun, HandleScope enclosing);
     519             : 
     520             :     static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun,
     521             :                                 HandleScope enclosing);
     522             : 
     523             :     template <XDRMode mode>
     524             :     static bool XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
     525             :                     MutableHandleScope scope);
     526             : 
     527             :   private:
     528             :     static FunctionScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
     529             :                                          bool hasParameterExprs, bool needsEnvironment,
     530             :                                          HandleFunction fun, HandleScope enclosing);
     531             : 
     532       88422 :     Data& data() {
     533       88422 :         return *reinterpret_cast<Data*>(data_);
     534             :     }
     535             : 
     536      632832 :     const Data& data() const {
     537      632832 :         return *reinterpret_cast<Data*>(data_);
     538             :     }
     539             : 
     540             :   public:
     541        9942 :     uint32_t nextFrameSlot() const {
     542        9942 :         return data().nextFrameSlot;
     543             :     }
     544             : 
     545      549354 :     JSFunction* canonicalFunction() const {
     546      549354 :         return data().canonicalFunction;
     547             :     }
     548             : 
     549             :     JSScript* script() const;
     550             : 
     551       64501 :     bool hasParameterExprs() const {
     552       64501 :         return data().hasParameterExprs;
     553             :     }
     554             : 
     555        8998 :     uint32_t numPositionalFormalParameters() const {
     556        8998 :         return data().nonPositionalFormalStart;
     557             :     }
     558             : 
     559             :     static bool isSpecialName(JSContext* cx, JSAtom* name);
     560             : 
     561             :     static Shape* getEmptyEnvironmentShape(JSContext* cx, bool hasParameterExprs);
     562             : };
     563             : 
     564             : //
     565             : // Scope holding only vars. There are 2 kinds of VarScopes.
     566             : //
     567             : // FunctionBodyVar
     568             : //   Corresponds to the extra var scope present in functions with parameter
     569             : //   expressions. See examples in comment above FunctionScope.
     570             : //
     571             : // ParameterExpressionVar
     572             : //   Each parameter expression is evaluated in its own var environment. For
     573             : //   example, f() below will print 'fml', then 'global'. That's right.
     574             : //
     575             : //     var a = 'global';
     576             : //     function f(x = (eval(`var a = 'fml'`), a), y = a) {
     577             : //       print(x);
     578             : //       print(y);
     579             : //     };
     580             : //
     581             : // Corresponds to VarEnvironmentObject on environment chain.
     582             : //
     583             : class VarScope : public Scope
     584             : {
     585             :     friend class GCMarker;
     586             :     friend class BindingIter;
     587             :     friend class Scope;
     588             : 
     589             :   public:
     590             :     // Data is public because it is created by the
     591             :     // frontend. See Parser<FullParseHandler>::newVarScopeData.
     592         110 :     struct Data
     593             :     {
     594             :         // All bindings are vars.
     595             :         uint32_t length;
     596             : 
     597             :         // Frame slots [firstFrameSlot(), nextFrameSlot) are live when this is
     598             :         // the innermost scope.
     599             :         uint32_t nextFrameSlot;
     600             : 
     601             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     602             :         // struct.
     603             :         BindingName names[1];
     604             : 
     605             :         void trace(JSTracer* trc);
     606             :     };
     607             : 
     608         413 :     static size_t sizeOfData(uint32_t length) {
     609         413 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     610             :     }
     611             : 
     612         199 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     613         199 :         *names = data->names;
     614         199 :         *length = data->length;
     615         199 :     }
     616             : 
     617             :     static VarScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     618             :                             uint32_t firstFrameSlot, bool needsEnvironment,
     619             :                             HandleScope enclosing);
     620             : 
     621             :     template <XDRMode mode>
     622             :     static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     623             :                     MutableHandleScope scope);
     624             : 
     625             :   private:
     626             :     static VarScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     627             :                                     uint32_t firstFrameSlot, bool needsEnvironment,
     628             :                                     HandleScope enclosing);
     629             : 
     630         284 :     Data& data() {
     631         284 :         return *reinterpret_cast<Data*>(data_);
     632             :     }
     633             : 
     634         388 :     const Data& data() const {
     635         388 :         return *reinterpret_cast<Data*>(data_);
     636             :     }
     637             : 
     638             :   public:
     639             :     uint32_t firstFrameSlot() const;
     640             : 
     641         388 :     uint32_t nextFrameSlot() const {
     642         388 :         return data().nextFrameSlot;
     643             :     }
     644             : 
     645             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
     646             : };
     647             : 
     648             : template <>
     649             : inline bool
     650       10861 : Scope::is<VarScope>() const
     651             : {
     652       10861 :     return kind_ == ScopeKind::FunctionBodyVar || kind_ == ScopeKind::ParameterExpressionVar;
     653             : }
     654             : 
     655             : //
     656             : // Scope corresponding to both the global object scope and the global lexical
     657             : // scope.
     658             : //
     659             : // Both are extensible and are singletons across <script> tags, so these
     660             : // scopes are a fragment of the names in global scope. In other words, two
     661             : // global scripts may have two different GlobalScopes despite having the same
     662             : // GlobalObject.
     663             : //
     664             : // There are 2 kinds of GlobalScopes.
     665             : //
     666             : // Global
     667             : //   Corresponds to a GlobalObject and its global LexicalEnvironmentObject on
     668             : //   the environment chain.
     669             : //
     670             : // NonSyntactic
     671             : //   Corresponds to a non-GlobalObject created by the embedding on the
     672             : //   environment chain. This distinction is important for optimizations.
     673             : //
     674             : class GlobalScope : public Scope
     675             : {
     676             :     friend class Scope;
     677             :     friend class BindingIter;
     678             : 
     679             :   public:
     680             :     // Data is public because it is created by the frontend. See
     681             :     // Parser<FullParseHandler>::newGlobalScopeData.
     682         892 :     struct Data
     683             :     {
     684             :         // Bindings are sorted by kind.
     685             :         //
     686             :         // top-level funcs - [0, varStart)
     687             :         //            vars - [varStart, letStart)
     688             :         //            lets - [letStart, constStart)
     689             :         //          consts - [constStart, length)
     690             :         uint32_t varStart;
     691             :         uint32_t letStart;
     692             :         uint32_t constStart;
     693             :         uint32_t length;
     694             : 
     695             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     696             :         // struct.
     697             :         BindingName names[1];
     698             : 
     699             :         void trace(JSTracer* trc);
     700             :     };
     701             : 
     702        1383 :     static size_t sizeOfData(uint32_t length) {
     703        1383 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     704             :     }
     705             : 
     706         358 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     707         358 :         *names = data->names;
     708         358 :         *length = data->length;
     709         358 :     }
     710             : 
     711             :     static GlobalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data);
     712             : 
     713         499 :     static GlobalScope* createEmpty(JSContext* cx, ScopeKind kind) {
     714         499 :         return create(cx, kind, nullptr);
     715             :     }
     716             : 
     717             :     static GlobalScope* clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind);
     718             : 
     719             :     template <XDRMode mode>
     720             :     static bool XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope);
     721             : 
     722             :   private:
     723             :     static GlobalScope* createWithData(JSContext* cx, ScopeKind kind,
     724             :                                        MutableHandle<UniquePtr<Data>> data);
     725             : 
     726        2866 :     Data& data() {
     727        2866 :         return *reinterpret_cast<Data*>(data_);
     728             :     }
     729             : 
     730           0 :     const Data& data() const {
     731           0 :         return *reinterpret_cast<Data*>(data_);
     732             :     }
     733             : 
     734             :   public:
     735           0 :     bool isSyntactic() const {
     736           0 :         return kind() != ScopeKind::NonSyntactic;
     737             :     }
     738             : 
     739           0 :     bool hasBindings() const {
     740           0 :         return data().length > 0;
     741             :     }
     742             : };
     743             : 
     744             : template <>
     745             : inline bool
     746       50884 : Scope::is<GlobalScope>() const
     747             : {
     748       50884 :     return kind_ == ScopeKind::Global || kind_ == ScopeKind::NonSyntactic;
     749             : }
     750             : 
     751             : //
     752             : // Scope of a 'with' statement. Has no bindings.
     753             : //
     754             : // Corresponds to a WithEnvironmentObject on the environment chain.
     755             : class WithScope : public Scope
     756             : {
     757             :     friend class Scope;
     758             :     static const ScopeKind classScopeKind_ = ScopeKind::With;
     759             : 
     760             :   public:
     761             :     static WithScope* create(JSContext* cx, HandleScope enclosing);
     762             : };
     763             : 
     764             : //
     765             : // Scope of an eval. Holds var bindings. There are 2 kinds of EvalScopes.
     766             : //
     767             : // StrictEval
     768             : //   A strict eval. Corresponds to a VarEnvironmentObject, where its var
     769             : //   bindings lives.
     770             : //
     771             : // Eval
     772             : //   A sloppy eval. This is an empty scope, used only in the frontend, to
     773             : //   detect redeclaration errors. It has no Environment. Any `var`s declared
     774             : //   in the eval code are bound on the nearest enclosing var environment.
     775             : //
     776             : class EvalScope : public Scope
     777             : {
     778             :     friend class Scope;
     779             :     friend class BindingIter;
     780             : 
     781             :   public:
     782             :     // Data is public because it is created by the frontend. See
     783             :     // Parser<FullParseHandler>::newEvalScopeData.
     784           0 :     struct Data
     785             :     {
     786             :         // All bindings in an eval script are 'var' bindings. The implicit
     787             :         // lexical scope around the eval is present regardless of strictness
     788             :         // and is its own LexicalScope. However, we need to track top-level
     789             :         // functions specially for redeclaration checks.
     790             :         //
     791             :         // top-level funcs - [0, varStart)
     792             :         //            vars - [varStart, length)
     793             :         uint32_t varStart;
     794             :         uint32_t length;
     795             : 
     796             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     797             :         // scope.
     798             :         uint32_t nextFrameSlot;
     799             : 
     800             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     801             :         // struct.
     802             :         BindingName names[1];
     803             : 
     804             :         void trace(JSTracer* trc);
     805             :     };
     806             : 
     807           4 :     static size_t sizeOfData(uint32_t length) {
     808           4 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     809             :     }
     810             : 
     811           2 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     812           2 :         *names = data->names;
     813           2 :         *length = data->length;
     814           2 :     }
     815             : 
     816             :     static EvalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
     817             :                              HandleScope enclosing);
     818             : 
     819             :     template <XDRMode mode>
     820             :     static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
     821             :                     MutableHandleScope scope);
     822             : 
     823             :   private:
     824             :     static EvalScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data,
     825             :                                      HandleScope enclosing);
     826             : 
     827          30 :     Data& data() {
     828          30 :         return *reinterpret_cast<Data*>(data_);
     829             :     }
     830             : 
     831          32 :     const Data& data() const {
     832          32 :         return *reinterpret_cast<Data*>(data_);
     833             :     }
     834             : 
     835             :   public:
     836             :     // Starting a scope, the nearest var scope that a direct eval can
     837             :     // introduce vars on.
     838             :     static Scope* nearestVarScopeForDirectEval(Scope* scope);
     839             : 
     840          32 :     uint32_t nextFrameSlot() const {
     841          32 :         return data().nextFrameSlot;
     842             :     }
     843             : 
     844           0 :     bool strict() const {
     845           0 :         return kind() == ScopeKind::StrictEval;
     846             :     }
     847             : 
     848           0 :     bool hasBindings() const {
     849           0 :         return data().length > 0;
     850             :     }
     851             : 
     852           0 :     bool isNonGlobal() const {
     853           0 :         if (strict())
     854           0 :             return true;
     855           0 :         return !nearestVarScopeForDirectEval(enclosing())->is<GlobalScope>();
     856             :     }
     857             : 
     858             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
     859             : };
     860             : 
     861             : template <>
     862             : inline bool
     863       12690 : Scope::is<EvalScope>() const
     864             : {
     865       12690 :     return kind_ == ScopeKind::Eval || kind_ == ScopeKind::StrictEval;
     866             : }
     867             : 
     868             : //
     869             : // Scope corresponding to the toplevel script in an ES module.
     870             : //
     871             : // Like GlobalScopes, these scopes contain both vars and lexical bindings, as
     872             : // the treating of imports and exports requires putting them in one scope.
     873             : //
     874             : // Corresponds to a ModuleEnvironmentObject on the environment chain.
     875             : //
     876             : class ModuleScope : public Scope
     877             : {
     878             :     friend class GCMarker;
     879             :     friend class BindingIter;
     880             :     friend class Scope;
     881             :     static const ScopeKind classScopeKind_ = ScopeKind::Module;
     882             : 
     883             :   public:
     884             :     // Data is public because it is created by the frontend. See
     885             :     // Parser<FullParseHandler>::newModuleScopeData.
     886           0 :     struct Data
     887             :     {
     888             :         // The module of the scope.
     889             :         GCPtr<ModuleObject*> module;
     890             : 
     891             :         // Bindings are sorted by kind.
     892             :         //
     893             :         // imports - [0, varStart)
     894             :         //    vars - [varStart, letStart)
     895             :         //    lets - [letStart, constStart)
     896             :         //  consts - [constStart, length)
     897             :         uint32_t varStart;
     898             :         uint32_t letStart;
     899             :         uint32_t constStart;
     900             :         uint32_t length;
     901             : 
     902             :         // Frame slots [0, nextFrameSlot) are live when this is the innermost
     903             :         // scope.
     904             :         uint32_t nextFrameSlot;
     905             : 
     906             :         // The array of tagged JSAtom* names, allocated beyond the end of the
     907             :         // struct.
     908             :         BindingName names[1];
     909             : 
     910             :         void trace(JSTracer* trc);
     911             :         Zone* zone() const;
     912             :     };
     913             : 
     914           0 :     static size_t sizeOfData(uint32_t length) {
     915           0 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     916             :     }
     917             : 
     918           0 :     static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
     919           0 :         *names = data->names;
     920           0 :         *length = data->length;
     921           0 :     }
     922             : 
     923             :     static ModuleScope* create(JSContext* cx, Handle<Data*> data,
     924             :                                Handle<ModuleObject*> module, HandleScope enclosing);
     925             : 
     926             :   private:
     927             :     static ModuleScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
     928             :                                        Handle<ModuleObject*> module, HandleScope enclosing);
     929             : 
     930           0 :     Data& data() {
     931           0 :         return *reinterpret_cast<Data*>(data_);
     932             :     }
     933             : 
     934           0 :     const Data& data() const {
     935           0 :         return *reinterpret_cast<Data*>(data_);
     936             :     }
     937             : 
     938             :   public:
     939           0 :     uint32_t nextFrameSlot() const {
     940           0 :         return data().nextFrameSlot;
     941             :     }
     942             : 
     943           0 :     ModuleObject* module() const {
     944           0 :         return data().module;
     945             :     }
     946             : 
     947             :     JSScript* script() const;
     948             : 
     949             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
     950             : };
     951             : 
     952             : // Scope corresponding to the wasm function. A WasmFunctionScope is used by
     953             : // Debugger only, and not for wasm execution.
     954             : //
     955             : class WasmFunctionScope : public Scope
     956             : {
     957             :     friend class BindingIter;
     958             :     friend class Scope;
     959             :     static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
     960             : 
     961             :   public:
     962           0 :     struct Data
     963             :     {
     964             :         uint32_t length;
     965             :         uint32_t nextFrameSlot;
     966             :         uint32_t funcIndex;
     967             : 
     968             :         // The wasm instance of the scope.
     969             :         GCPtr<WasmInstanceObject*> instance;
     970             : 
     971             :         BindingName names[1];
     972             : 
     973             :         void trace(JSTracer* trc);
     974             :     };
     975             : 
     976             :     static WasmFunctionScope* create(JSContext* cx, WasmInstanceObject* instance, uint32_t funcIndex);
     977             : 
     978           0 :     static size_t sizeOfData(uint32_t length) {
     979           0 :         return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
     980             :     }
     981             : 
     982             :   private:
     983           0 :     Data& data() {
     984           0 :         return *reinterpret_cast<Data*>(data_);
     985             :     }
     986             : 
     987             :     const Data& data() const {
     988             :         return *reinterpret_cast<Data*>(data_);
     989             :     }
     990             : 
     991             :   public:
     992             :     WasmInstanceObject* instance() const {
     993             :         return data().instance;
     994             :     }
     995             : 
     996             :     uint32_t funcIndex() const {
     997             :         return data().funcIndex;
     998             :     }
     999             : 
    1000             :     static Shape* getEmptyEnvironmentShape(JSContext* cx);
    1001             : };
    1002             : 
    1003             : //
    1004             : // An iterator for a Scope's bindings. This is the source of truth for frame
    1005             : // and environment object layout.
    1006             : //
    1007             : // It may be placed in GC containers; for example:
    1008             : //
    1009             : //   for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
    1010             : //     use(bi);
    1011             : //     SomeMayGCOperation();
    1012             : //     use(bi);
    1013             : //   }
    1014             : //
    1015             : class BindingIter
    1016             : {
    1017             :   protected:
    1018             :     // Bindings are sorted by kind. Because different Scopes have differently
    1019             :     // laid out Data for packing, BindingIter must handle all binding kinds.
    1020             :     //
    1021             :     // Kind ranges:
    1022             :     //
    1023             :     //            imports - [0, positionalFormalStart)
    1024             :     // positional formals - [positionalFormalStart, nonPositionalFormalStart)
    1025             :     //      other formals - [nonPositionalParamStart, topLevelFunctionStart)
    1026             :     //    top-level funcs - [topLevelFunctionStart, varStart)
    1027             :     //               vars - [varStart, letStart)
    1028             :     //               lets - [letStart, constStart)
    1029             :     //             consts - [constStart, length)
    1030             :     //
    1031             :     // Access method when not closed over:
    1032             :     //
    1033             :     //            imports - name
    1034             :     // positional formals - argument slot
    1035             :     //      other formals - frame slot
    1036             :     //    top-level funcs - frame slot
    1037             :     //               vars - frame slot
    1038             :     //               lets - frame slot
    1039             :     //             consts - frame slot
    1040             :     //
    1041             :     // Access method when closed over:
    1042             :     //
    1043             :     //            imports - name
    1044             :     // positional formals - environment slot or name
    1045             :     //      other formals - environment slot or name
    1046             :     //    top-level funcs - environment slot or name
    1047             :     //               vars - environment slot or name
    1048             :     //               lets - environment slot or name
    1049             :     //             consts - environment slot or name
    1050             :     uint32_t positionalFormalStart_;
    1051             :     uint32_t nonPositionalFormalStart_;
    1052             :     uint32_t topLevelFunctionStart_;
    1053             :     uint32_t varStart_;
    1054             :     uint32_t letStart_;
    1055             :     uint32_t constStart_;
    1056             :     uint32_t length_;
    1057             : 
    1058             :     uint32_t index_;
    1059             : 
    1060             :     enum Flags : uint8_t {
    1061             :         CannotHaveSlots = 0,
    1062             :         CanHaveArgumentSlots = 1 << 0,
    1063             :         CanHaveFrameSlots = 1 << 1,
    1064             :         CanHaveEnvironmentSlots = 1 << 2,
    1065             : 
    1066             :         // See comment in settle below.
    1067             :         HasFormalParameterExprs = 1 << 3,
    1068             :         IgnoreDestructuredFormalParameters = 1 << 4,
    1069             : 
    1070             :         // Truly I hate named lambdas.
    1071             :         IsNamedLambda = 1 << 5
    1072             :     };
    1073             : 
    1074             :     static const uint8_t CanHaveSlotsMask = 0x7;
    1075             : 
    1076             :     uint8_t flags_;
    1077             :     uint16_t argumentSlot_;
    1078             :     uint32_t frameSlot_;
    1079             :     uint32_t environmentSlot_;
    1080             : 
    1081             :     BindingName* names_;
    1082             : 
    1083      102038 :     void init(uint32_t positionalFormalStart, uint32_t nonPositionalFormalStart,
    1084             :               uint32_t topLevelFunctionStart, uint32_t varStart,
    1085             :               uint32_t letStart, uint32_t constStart,
    1086             :               uint8_t flags, uint32_t firstFrameSlot, uint32_t firstEnvironmentSlot,
    1087             :               BindingName* names, uint32_t length)
    1088             :     {
    1089      102038 :         positionalFormalStart_ = positionalFormalStart;
    1090      102038 :         nonPositionalFormalStart_ = nonPositionalFormalStart;
    1091      102038 :         topLevelFunctionStart_ = topLevelFunctionStart;
    1092      102038 :         varStart_ = varStart;
    1093      102038 :         letStart_ = letStart;
    1094      102038 :         constStart_ = constStart;
    1095      102038 :         length_ = length;
    1096      102038 :         index_ = 0;
    1097      102038 :         flags_ = flags;
    1098      102038 :         argumentSlot_ = 0;
    1099      102038 :         frameSlot_ = firstFrameSlot;
    1100      102038 :         environmentSlot_ = firstEnvironmentSlot;
    1101      102038 :         names_ = names;
    1102             : 
    1103      102038 :         settle();
    1104      102036 :     }
    1105             : 
    1106             :     void init(LexicalScope::Data& data, uint32_t firstFrameSlot, uint8_t flags);
    1107             :     void init(FunctionScope::Data& data, uint8_t flags);
    1108             :     void init(VarScope::Data& data, uint32_t firstFrameSlot);
    1109             :     void init(GlobalScope::Data& data);
    1110             :     void init(EvalScope::Data& data, bool strict);
    1111             :     void init(ModuleScope::Data& data);
    1112             :     void init(WasmFunctionScope::Data& data);
    1113             : 
    1114       68834 :     bool hasFormalParameterExprs() const {
    1115       68834 :         return flags_ & HasFormalParameterExprs;
    1116             :     }
    1117             : 
    1118      244385 :     bool ignoreDestructuredFormalParameters() const {
    1119      244385 :         return flags_ & IgnoreDestructuredFormalParameters;
    1120             :     }
    1121             : 
    1122        4761 :     bool isNamedLambda() const {
    1123        4761 :         return flags_ & IsNamedLambda;
    1124             :     }
    1125             : 
    1126      142552 :     void increment() {
    1127      142552 :         MOZ_ASSERT(!done());
    1128      142551 :         if (flags_ & CanHaveSlotsMask) {
    1129      110601 :             if (canHaveArgumentSlots()) {
    1130       77549 :                 if (index_ < nonPositionalFormalStart_) {
    1131       53981 :                     MOZ_ASSERT(index_ >= positionalFormalStart_);
    1132       53981 :                     argumentSlot_++;
    1133             :                 }
    1134             :             }
    1135      110601 :             if (closedOver()) {
    1136             :                 // Imports must not be given known slots. They are
    1137             :                 // indirect bindings.
    1138       28071 :                 MOZ_ASSERT(kind() != BindingKind::Import);
    1139       28071 :                 MOZ_ASSERT(canHaveEnvironmentSlots());
    1140       28071 :                 environmentSlot_++;
    1141       82533 :             } else if (canHaveFrameSlots()) {
    1142             :                 // Usually positional formal parameters don't have frame
    1143             :                 // slots, except when there are parameter expressions, in
    1144             :                 // which case they act like lets.
    1145       80751 :                 if (index_ >= nonPositionalFormalStart_ || (hasFormalParameterExprs() && name()))
    1146       41413 :                     frameSlot_++;
    1147             :             }
    1148             :         }
    1149      142554 :         index_++;
    1150      142554 :     }
    1151             : 
    1152      244384 :     void settle() {
    1153      244384 :         if (ignoreDestructuredFormalParameters()) {
    1154      104345 :             while (!done() && !name())
    1155         297 :                 increment();
    1156             :         }
    1157      244389 :     }
    1158             : 
    1159             :   public:
    1160             :     explicit BindingIter(Scope* scope);
    1161             :     explicit BindingIter(JSScript* script);
    1162             : 
    1163       13660 :     BindingIter(LexicalScope::Data& data, uint32_t firstFrameSlot, bool isNamedLambda) {
    1164       13660 :         init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0);
    1165       13660 :     }
    1166             : 
    1167       19613 :     BindingIter(FunctionScope::Data& data, bool hasParameterExprs) {
    1168       19613 :         init(data,
    1169             :              IgnoreDestructuredFormalParameters |
    1170       19613 :              (hasParameterExprs ? HasFormalParameterExprs : 0));
    1171       19613 :     }
    1172             : 
    1173         318 :     BindingIter(VarScope::Data& data, uint32_t firstFrameSlot) {
    1174         318 :         init(data, firstFrameSlot);
    1175         318 :     }
    1176             : 
    1177         130 :     explicit BindingIter(GlobalScope::Data& data) {
    1178         130 :         init(data);
    1179         130 :     }
    1180             : 
    1181           0 :     explicit BindingIter(ModuleScope::Data& data) {
    1182           0 :         init(data);
    1183           0 :     }
    1184             : 
    1185             :     explicit BindingIter(WasmFunctionScope::Data& data) {
    1186             :         init(data);
    1187             :     }
    1188             : 
    1189           2 :     BindingIter(EvalScope::Data& data, bool strict) {
    1190           2 :         init(data, strict);
    1191           2 :     }
    1192             : 
    1193             :     explicit BindingIter(const BindingIter& bi) = default;
    1194             : 
    1195      964143 :     bool done() const {
    1196      964143 :         return index_ == length_;
    1197             :     }
    1198             : 
    1199      216554 :     explicit operator bool() const {
    1200      216554 :         return !done();
    1201             :     }
    1202             : 
    1203      142255 :     void operator++(int) {
    1204      142255 :         increment();
    1205      142253 :         settle();
    1206      142255 :     }
    1207             : 
    1208           0 :     bool isLast() const {
    1209           0 :         MOZ_ASSERT(!done());
    1210           0 :         return index_ + 1 == length_;
    1211             :     }
    1212             : 
    1213      160170 :     bool canHaveArgumentSlots() const {
    1214      160170 :         return flags_ & CanHaveArgumentSlots;
    1215             :     }
    1216             : 
    1217      171593 :     bool canHaveFrameSlots() const {
    1218      171593 :         return flags_ & CanHaveFrameSlots;
    1219             :     }
    1220             : 
    1221      103929 :     bool canHaveEnvironmentSlots() const {
    1222      103929 :         return flags_ & CanHaveEnvironmentSlots;
    1223             :     }
    1224             : 
    1225      174722 :     JSAtom* name() const {
    1226      174722 :         MOZ_ASSERT(!done());
    1227      174722 :         return names_[index_].name();
    1228             :     }
    1229             : 
    1230      201670 :     bool closedOver() const {
    1231      201670 :         MOZ_ASSERT(!done());
    1232      201669 :         return names_[index_].closedOver();
    1233             :     }
    1234             : 
    1235       52477 :     BindingLocation location() const {
    1236       52477 :         MOZ_ASSERT(!done());
    1237       52477 :         if (!(flags_ & CanHaveSlotsMask))
    1238        2841 :             return BindingLocation::Global();
    1239       49636 :         if (index_ < positionalFormalStart_)
    1240           0 :             return BindingLocation::Import();
    1241       49636 :         if (closedOver()) {
    1242       29293 :             MOZ_ASSERT(canHaveEnvironmentSlots());
    1243       29293 :             return BindingLocation::Environment(environmentSlot_);
    1244             :         }
    1245       20344 :         if (index_ < nonPositionalFormalStart_ && canHaveArgumentSlots())
    1246        6207 :             return BindingLocation::Argument(argumentSlot_);
    1247       14137 :         if (canHaveFrameSlots())
    1248       13753 :             return BindingLocation::Frame(frameSlot_);
    1249         384 :         MOZ_ASSERT(isNamedLambda());
    1250         384 :         return BindingLocation::NamedLambdaCallee();
    1251             :     }
    1252             : 
    1253       61270 :     BindingKind kind() const {
    1254       61270 :         MOZ_ASSERT(!done());
    1255       61270 :         if (index_ < positionalFormalStart_)
    1256           0 :             return BindingKind::Import;
    1257       61270 :         if (index_ < topLevelFunctionStart_) {
    1258             :             // When the parameter list has expressions, the parameters act
    1259             :             // like lexical bindings and have TDZ.
    1260       25347 :             if (hasFormalParameterExprs())
    1261        2639 :                 return BindingKind::Let;
    1262       22708 :             return BindingKind::FormalParameter;
    1263             :         }
    1264       35923 :         if (index_ < letStart_)
    1265       17440 :             return BindingKind::Var;
    1266       18483 :         if (index_ < constStart_)
    1267       14106 :             return BindingKind::Let;
    1268        4377 :         if (isNamedLambda())
    1269         856 :             return BindingKind::NamedLambdaCallee;
    1270        3521 :         return BindingKind::Const;
    1271             :     }
    1272             : 
    1273        3569 :     bool isTopLevelFunction() const {
    1274        3569 :         MOZ_ASSERT(!done());
    1275        3569 :         return index_ >= topLevelFunctionStart_ && index_ < varStart_;
    1276             :     }
    1277             : 
    1278        2029 :     bool hasArgumentSlot() const {
    1279        2029 :         MOZ_ASSERT(!done());
    1280        2029 :         if (hasFormalParameterExprs())
    1281          62 :             return false;
    1282        1967 :         return index_ >= positionalFormalStart_ && index_ < nonPositionalFormalStart_;
    1283             :     }
    1284             : 
    1285       42212 :     uint16_t argumentSlot() const {
    1286       42212 :         MOZ_ASSERT(canHaveArgumentSlots());
    1287       42212 :         return mozilla::AssertedCast<uint16_t>(index_);
    1288             :     }
    1289             : 
    1290       49554 :     uint32_t nextFrameSlot() const {
    1291       49554 :         MOZ_ASSERT(canHaveFrameSlots());
    1292       49554 :         return frameSlot_;
    1293             :     }
    1294             : 
    1295       46501 :     uint32_t nextEnvironmentSlot() const {
    1296       46501 :         MOZ_ASSERT(canHaveEnvironmentSlots());
    1297       46501 :         return environmentSlot_;
    1298             :     }
    1299             : 
    1300             :     void trace(JSTracer* trc);
    1301             : };
    1302             : 
    1303             : void DumpBindings(JSContext* cx, Scope* scope);
    1304             : JSAtom* FrameSlotName(JSScript* script, jsbytecode* pc);
    1305             : 
    1306             : //
    1307             : // A refinement BindingIter that only iterates over positional formal
    1308             : // parameters of a function.
    1309             : //
    1310             : class PositionalFormalParameterIter : public BindingIter
    1311             : {
    1312       61320 :     void settle() {
    1313       61320 :         if (index_ >= nonPositionalFormalStart_)
    1314        9139 :             index_ = length_;
    1315       61320 :     }
    1316             : 
    1317             :   public:
    1318             :     explicit PositionalFormalParameterIter(JSScript* script);
    1319             : 
    1320       29927 :     void operator++(int) {
    1321       29927 :         BindingIter::operator++(1);
    1322       29927 :         settle();
    1323       29927 :     }
    1324             : 
    1325           0 :     bool isDestructured() const {
    1326           0 :         return !name();
    1327             :     }
    1328             : };
    1329             : 
    1330             : //
    1331             : // Iterator for walking the scope chain.
    1332             : //
    1333             : // It may be placed in GC containers; for example:
    1334             : //
    1335             : //   for (Rooted<ScopeIter> si(cx, ScopeIter(scope)); si; si++) {
    1336             : //     use(si);
    1337             : //     SomeMayGCOperation();
    1338             : //     use(si);
    1339             : //   }
    1340             : //
    1341             : class MOZ_STACK_CLASS ScopeIter
    1342             : {
    1343             :     Scope* scope_;
    1344             : 
    1345             :   public:
    1346       55636 :     explicit ScopeIter(Scope* scope)
    1347       55636 :       : scope_(scope)
    1348       55636 :     { }
    1349             : 
    1350             :     explicit ScopeIter(JSScript* script);
    1351             : 
    1352          34 :     explicit ScopeIter(const ScopeIter& si)
    1353          34 :       : scope_(si.scope_)
    1354          34 :     { }
    1355             : 
    1356      491194 :     bool done() const {
    1357      491194 :         return !scope_;
    1358             :     }
    1359             : 
    1360       63476 :     explicit operator bool() const {
    1361       63476 :         return !done();
    1362             :     }
    1363             : 
    1364       41730 :     void operator++(int) {
    1365       41730 :         MOZ_ASSERT(!done());
    1366       41730 :         scope_ = scope_->enclosing();
    1367       41730 :     }
    1368             : 
    1369      229351 :     Scope* scope() const {
    1370      229351 :         MOZ_ASSERT(!done());
    1371      229349 :         return scope_;
    1372             :     }
    1373             : 
    1374       92060 :     ScopeKind kind() const {
    1375       92060 :         MOZ_ASSERT(!done());
    1376       92060 :         return scope_->kind();
    1377             :     }
    1378             : 
    1379             :     // Returns the shape of the environment if it is known. It is possible to
    1380             :     // hasSyntacticEnvironment and to have no known shape, e.g., eval.
    1381        1654 :     Shape* environmentShape() const {
    1382        1654 :         return scope()->environmentShape();
    1383             :     }
    1384             : 
    1385             :     // Returns whether this scope has a syntactic environment (i.e., an
    1386             :     // Environment that isn't a non-syntactic With or NonSyntacticVariables)
    1387             :     // on the environment chain.
    1388             :     bool hasSyntacticEnvironment() const;
    1389             : 
    1390           0 :     void trace(JSTracer* trc) {
    1391           0 :         if (scope_)
    1392           0 :             TraceRoot(trc, &scope_, "scope iter scope");
    1393           0 :     }
    1394             : };
    1395             : 
    1396             : //
    1397             : // Specializations of Rooted containers for the iterators.
    1398             : //
    1399             : 
    1400             : template <typename Wrapper>
    1401         495 : class WrappedPtrOperations<BindingIter, Wrapper>
    1402             : {
    1403       13348 :     const BindingIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
    1404             : 
    1405             :   public:
    1406        5279 :     bool done() const { return iter().done(); }
    1407        5279 :     explicit operator bool() const { return !done(); }
    1408           0 :     bool isLast() const { return iter().isLast(); }
    1409             :     bool canHaveArgumentSlots() const { return iter().canHaveArgumentSlots(); }
    1410             :     bool canHaveFrameSlots() const { return iter().canHaveFrameSlots(); }
    1411             :     bool canHaveEnvironmentSlots() const { return iter().canHaveEnvironmentSlots(); }
    1412        4289 :     JSAtom* name() const { return iter().name(); }
    1413           0 :     bool closedOver() const { return iter().closedOver(); }
    1414           0 :     BindingLocation location() const { return iter().location(); }
    1415        2135 :     BindingKind kind() const { return iter().kind(); }
    1416        1645 :     bool isTopLevelFunction() const { return iter().isTopLevelFunction(); }
    1417             :     bool hasArgumentSlot() const { return iter().hasArgumentSlot(); }
    1418             :     uint16_t argumentSlot() const { return iter().argumentSlot(); }
    1419             :     uint32_t nextFrameSlot() const { return iter().nextFrameSlot(); }
    1420             :     uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); }
    1421             : };
    1422             : 
    1423             : template <typename Wrapper>
    1424         495 : class MutableWrappedPtrOperations<BindingIter, Wrapper>
    1425             :   : public WrappedPtrOperations<BindingIter, Wrapper>
    1426             : {
    1427        4289 :     BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); }
    1428             : 
    1429             :   public:
    1430        4289 :     void operator++(int) { iter().operator++(1); }
    1431             : };
    1432             : 
    1433             : template <typename Wrapper>
    1434       14330 : class WrappedPtrOperations<ScopeIter, Wrapper>
    1435             : {
    1436      219791 :     const ScopeIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
    1437             : 
    1438             :   public:
    1439       60453 :     bool done() const { return iter().done(); }
    1440       60413 :     explicit operator bool() const { return !done(); }
    1441       86042 :     Scope* scope() const { return iter().scope(); }
    1442       31158 :     ScopeKind kind() const { return iter().kind(); }
    1443             :     Shape* environmentShape() const { return iter().environmentShape(); }
    1444       42138 :     bool hasSyntacticEnvironment() const { return iter().hasSyntacticEnvironment(); }
    1445             : };
    1446             : 
    1447             : template <typename Wrapper>
    1448       14330 : class MutableWrappedPtrOperations<ScopeIter, Wrapper>
    1449             :   : public WrappedPtrOperations<ScopeIter, Wrapper>
    1450             : {
    1451       13495 :     ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); }
    1452             : 
    1453             :   public:
    1454       13495 :     void operator++(int) { iter().operator++(1); }
    1455             : };
    1456             : 
    1457             : } // namespace js
    1458             : 
    1459             : namespace JS {
    1460             : 
    1461             : template <>
    1462             : struct GCPolicy<js::ScopeKind> : public IgnoreGCPolicy<js::ScopeKind>
    1463             : { };
    1464             : 
    1465             : template <typename T>
    1466             : struct ScopeDataGCPolicy
    1467             : {
    1468       21831 :     static T initial() {
    1469       21831 :         return nullptr;
    1470             :     }
    1471             : 
    1472           0 :     static void trace(JSTracer* trc, T* vp, const char* name) {
    1473           0 :         if (*vp)
    1474           0 :             (*vp)->trace(trc);
    1475           0 :     }
    1476             : };
    1477             : 
    1478             : #define DEFINE_SCOPE_DATA_GCPOLICY(Data)                        \
    1479             :     template <>                                                 \
    1480             :     struct MapTypeToRootKind<Data*> {                           \
    1481             :         static const RootKind kind = RootKind::Traceable;       \
    1482             :     };                                                          \
    1483             :     template <>                                                 \
    1484             :     struct GCPolicy<Data*> : public ScopeDataGCPolicy<Data*>    \
    1485             :     { }
    1486             : 
    1487             : DEFINE_SCOPE_DATA_GCPOLICY(js::LexicalScope::Data);
    1488             : DEFINE_SCOPE_DATA_GCPOLICY(js::FunctionScope::Data);
    1489             : DEFINE_SCOPE_DATA_GCPOLICY(js::VarScope::Data);
    1490             : DEFINE_SCOPE_DATA_GCPOLICY(js::GlobalScope::Data);
    1491             : DEFINE_SCOPE_DATA_GCPOLICY(js::EvalScope::Data);
    1492             : DEFINE_SCOPE_DATA_GCPOLICY(js::ModuleScope::Data);
    1493             : DEFINE_SCOPE_DATA_GCPOLICY(js::WasmFunctionScope::Data);
    1494             : 
    1495             : #undef DEFINE_SCOPE_DATA_GCPOLICY
    1496             : 
    1497             : namespace ubi {
    1498             : 
    1499             : template <>
    1500             : class Concrete<js::Scope> : TracerConcrete<js::Scope>
    1501             : {
    1502             :   protected:
    1503           0 :     explicit Concrete(js::Scope* ptr) : TracerConcrete<js::Scope>(ptr) { }
    1504             : 
    1505             :   public:
    1506           0 :     static void construct(void* storage, js::Scope* ptr) {
    1507           0 :         new (storage) Concrete(ptr);
    1508           0 :     }
    1509             : 
    1510           0 :     CoarseType coarseType() const final { return CoarseType::Script; }
    1511             : 
    1512             :     Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
    1513             : 
    1514           0 :     const char16_t* typeName() const override { return concreteTypeName; }
    1515             :     static const char16_t concreteTypeName[];
    1516             : };
    1517             : 
    1518             : } // namespace ubi
    1519             : } // namespace JS
    1520             : 
    1521             : #endif // vm_Scope_h

Generated by: LCOV version 1.13