tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Scope.h (60558B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/Assertions.h"  // MOZ_ASSERT, MOZ_ASSERT_IF
     11 #include "mozilla/Attributes.h"  // MOZ_IMPLICIT, MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS
     12 #include "mozilla/Casting.h"          // mozilla::AssertedCast
     13 #include "mozilla/Maybe.h"            // mozilla::Maybe
     14 #include "mozilla/MemoryReporting.h"  // mozilla::MallocSizeOf
     15 #include "mozilla/Span.h"             // mozilla::Span
     16 
     17 #include <algorithm>    // std::fill_n
     18 #include <stddef.h>     // size_t
     19 #include <stdint.h>     // uint8_t, uint16_t, uint32_t, uintptr_t
     20 #include <type_traits>  // std::is_same_v, std::is_base_of_v
     21 
     22 #include "builtin/ModuleObject.h"  // ModuleObject, Handle<ModuleObject*>
     23 #include "frontend/ParserAtom.h"   // frontend::TaggedParserAtomIndex
     24 #include "gc/Allocator.h"          // HandleBuffer
     25 #include "gc/Barrier.h"            // GCPtr
     26 #include "gc/Cell.h"               // TenuredCellWithNonGCPointer
     27 #include "js/GCPolicyAPI.h"        // GCPolicy, IgnoreGCPolicy
     28 #include "js/HeapAPI.h"            // CellFlagBitsReservedForGC
     29 #include "js/RootingAPI.h"         // Handle, MutableHandle
     30 #include "js/TraceKind.h"          // JS::TraceKind
     31 #include "js/TypeDecls.h"          // HandleFunction
     32 #include "js/UbiNode.h"            // ubi::*
     33 #include "util/Poison.h"  // AlwaysPoison, JS_SCOPE_DATA_TRAILING_NAMES_PATTERN, MemCheckKind
     34 #include "vm/JSFunction.h"  // JSFunction
     35 #include "vm/ScopeKind.h"   // ScopeKind
     36 #include "vm/Shape.h"       // Shape
     37 #include "wasm/WasmJS.h"    // WasmInstanceObject
     38 
     39 class JSAtom;
     40 class JSScript;
     41 class JSTracer;
     42 struct JSContext;
     43 
     44 namespace js {
     45 
     46 class JS_PUBLIC_API GenericPrinter;
     47 
     48 namespace frontend {
     49 class ScopeStencil;
     50 struct ScopeStencilRef;
     51 class RuntimeScopeBindingCache;
     52 }  // namespace frontend
     53 
     54 template <typename NameT>
     55 class AbstractBaseScopeData;
     56 
     57 template <typename NameT>
     58 class BaseAbstractBindingIter;
     59 
     60 template <typename NameT>
     61 class AbstractBindingIter;
     62 
     63 template <typename NameT>
     64 class AbstractPositionalFormalParameterIter;
     65 
     66 using BindingIter = AbstractBindingIter<JSAtom>;
     67 
     68 class AbstractScopePtr;
     69 
     70 static inline bool ScopeKindIsCatch(ScopeKind kind) {
     71  return kind == ScopeKind::SimpleCatch || kind == ScopeKind::Catch;
     72 }
     73 
     74 static inline bool ScopeKindIsInBody(ScopeKind kind) {
     75  return kind == ScopeKind::Lexical || kind == ScopeKind::SimpleCatch ||
     76         kind == ScopeKind::Catch || kind == ScopeKind::With ||
     77         kind == ScopeKind::FunctionLexical ||
     78         kind == ScopeKind::FunctionBodyVar || kind == ScopeKind::ClassBody;
     79 }
     80 
     81 const char* BindingKindString(BindingKind kind);
     82 const char* ScopeKindString(ScopeKind kind);
     83 
     84 template <typename NameT>
     85 class AbstractBindingName;
     86 
     87 template <>
     88 class AbstractBindingName<JSAtom> {
     89 public:
     90  using NameT = JSAtom;
     91  using NamePointerT = NameT*;
     92 
     93 private:
     94  // A JSAtom* with its low bit used as a tag for the:
     95  //  * whether it is closed over (i.e., exists in the environment shape)
     96  //  * whether it is a top-level function binding in global or eval scope,
     97  //    instead of var binding (both are in the same range in Scope data)
     98  uintptr_t bits_;
     99 
    100  static constexpr uintptr_t ClosedOverFlag = 0x1;
    101  // TODO: We should reuse this bit for let vs class distinction to
    102  //       show the better redeclaration error message (bug 1428672).
    103  static constexpr uintptr_t TopLevelFunctionFlag = 0x2;
    104  static constexpr uintptr_t FlagMask = 0x3;
    105 
    106 public:
    107  AbstractBindingName() : bits_(0) {}
    108 
    109  AbstractBindingName(NameT* name, bool closedOver,
    110                      bool isTopLevelFunction = false)
    111      : bits_(uintptr_t(name) | (closedOver ? ClosedOverFlag : 0x0) |
    112              (isTopLevelFunction ? TopLevelFunctionFlag : 0x0)) {}
    113 
    114  NamePointerT name() const {
    115    return reinterpret_cast<NameT*>(bits_ & ~FlagMask);
    116  }
    117 
    118  bool closedOver() const { return bits_ & ClosedOverFlag; }
    119 
    120 private:
    121  friend class BaseAbstractBindingIter<NameT>;
    122 
    123  // This method should be called only for binding names in `vars` range in
    124  // BindingIter.
    125  bool isTopLevelFunction() const { return bits_ & TopLevelFunctionFlag; }
    126 
    127 public:
    128  void trace(JSTracer* trc) {
    129    if (JSAtom* atom = name()) {
    130      TraceManuallyBarrieredEdge(trc, &atom, "binding name");
    131    }
    132  }
    133 };
    134 
    135 template <>
    136 class AbstractBindingName<frontend::TaggedParserAtomIndex> {
    137  uint32_t bits_;
    138 
    139  using TaggedParserAtomIndex = frontend::TaggedParserAtomIndex;
    140 
    141 public:
    142  using NameT = TaggedParserAtomIndex;
    143  using NamePointerT = NameT;
    144 
    145 private:
    146  static constexpr size_t TaggedIndexBit = TaggedParserAtomIndex::IndexBit + 2;
    147 
    148  static constexpr size_t FlagShift = TaggedIndexBit;
    149  static constexpr size_t FlagBit = 2;
    150  static constexpr uint32_t FlagMask = BitMask(FlagBit) << FlagShift;
    151 
    152  static constexpr uint32_t ClosedOverFlag = 1 << FlagShift;
    153  static constexpr uint32_t TopLevelFunctionFlag = 2 << FlagShift;
    154 
    155 public:
    156  AbstractBindingName() : bits_(TaggedParserAtomIndex::NullTag) {
    157    // TaggedParserAtomIndex's tags shouldn't overlap with flags.
    158    static_assert((TaggedParserAtomIndex::NullTag & FlagMask) == 0);
    159    static_assert((TaggedParserAtomIndex::ParserAtomIndexTag & FlagMask) == 0);
    160    static_assert((TaggedParserAtomIndex::WellKnownTag & FlagMask) == 0);
    161  }
    162 
    163  AbstractBindingName(TaggedParserAtomIndex name, bool closedOver,
    164                      bool isTopLevelFunction = false)
    165      : bits_(name.rawData() | (closedOver ? ClosedOverFlag : 0x0) |
    166              (isTopLevelFunction ? TopLevelFunctionFlag : 0x0)) {}
    167 
    168 public:
    169  NamePointerT name() const {
    170    return TaggedParserAtomIndex::fromRaw(bits_ & ~FlagMask);
    171  }
    172 
    173  bool closedOver() const { return bits_ & ClosedOverFlag; }
    174 
    175  AbstractBindingName<JSAtom> copyWithNewAtom(JSAtom* newName) const {
    176    return AbstractBindingName<JSAtom>(newName, closedOver(),
    177                                       isTopLevelFunction());
    178  }
    179 
    180  void updateNameAfterStencilMerge(TaggedParserAtomIndex name) {
    181    bits_ = (bits_ & FlagMask) | name.rawData();
    182  }
    183 
    184 private:
    185  friend class BaseAbstractBindingIter<TaggedParserAtomIndex>;
    186  friend class frontend::ScopeStencil;
    187 
    188  // This method should be called only for binding names in `vars` range in
    189  // BindingIter.
    190  bool isTopLevelFunction() const { return bits_ & TopLevelFunctionFlag; }
    191 };
    192 
    193 using BindingName = AbstractBindingName<JSAtom>;
    194 
    195 static inline void TraceBindingNames(JSTracer* trc, BindingName* names,
    196                                     uint32_t length) {
    197  for (uint32_t i = 0; i < length; i++) {
    198    JSAtom* name = names[i].name();
    199    MOZ_ASSERT(name);
    200    TraceManuallyBarrieredEdge(trc, &name, "scope name");
    201  }
    202 };
    203 static inline void TraceNullableBindingNames(JSTracer* trc, BindingName* names,
    204                                             uint32_t length) {
    205  for (uint32_t i = 0; i < length; i++) {
    206    if (JSAtom* name = names[i].name()) {
    207      TraceManuallyBarrieredEdge(trc, &name, "scope name");
    208    }
    209  }
    210 };
    211 
    212 const size_t ScopeDataAlignBytes = size_t(1) << gc::CellFlagBitsReservedForGC;
    213 
    214 /**
    215 * Base class for scope {Runtime,Parser}Data classes to inherit from.
    216 *
    217 * `js::Scope` stores a pointer to RuntimeData classes in their first word, so
    218 * they must be suitably aligned to allow storing GC flags in the low bits.
    219 */
    220 template <typename NameT>
    221 class AbstractBaseScopeData {
    222 public:
    223  using NameType = NameT;
    224 
    225  // The length of names after specialized ScopeData subclasses.
    226  uint32_t length = 0;
    227 };
    228 
    229 template <typename ScopeDataT>
    230 static inline void AssertDerivedScopeData() {
    231  static_assert(
    232      !std::is_same_v<ScopeDataT,
    233                      AbstractBaseScopeData<typename ScopeDataT::NameType>>,
    234      "ScopeDataT shouldn't be AbstractBaseScopeData");
    235  static_assert(
    236      std::is_base_of_v<AbstractBaseScopeData<typename ScopeDataT::NameType>,
    237                        ScopeDataT>,
    238      "ScopeDataT should be subclass of AbstractBaseScopeData");
    239 }
    240 
    241 template <typename ScopeDataT>
    242 static inline size_t GetOffsetOfScopeDataTrailingNames() {
    243  AssertDerivedScopeData<ScopeDataT>();
    244  return sizeof(ScopeDataT);
    245 }
    246 
    247 template <typename ScopeDataT>
    248 static inline AbstractBindingName<typename ScopeDataT::NameType>*
    249 GetScopeDataTrailingNamesPointer(ScopeDataT* data) {
    250  AssertDerivedScopeData<ScopeDataT>();
    251  return reinterpret_cast<AbstractBindingName<typename ScopeDataT::NameType>*>(
    252      data + 1);
    253 }
    254 
    255 template <typename ScopeDataT>
    256 static inline const AbstractBindingName<typename ScopeDataT::NameType>*
    257 GetScopeDataTrailingNamesPointer(const ScopeDataT* data) {
    258  AssertDerivedScopeData<ScopeDataT>();
    259  return reinterpret_cast<
    260      const AbstractBindingName<typename ScopeDataT::NameType>*>(data + 1);
    261 }
    262 
    263 template <typename ScopeDataT>
    264 static inline mozilla::Span<AbstractBindingName<typename ScopeDataT::NameType>>
    265 GetScopeDataTrailingNames(ScopeDataT* data) {
    266  return mozilla::Span(GetScopeDataTrailingNamesPointer(data), data->length);
    267 }
    268 
    269 template <typename ScopeDataT>
    270 static inline mozilla::Span<
    271    const AbstractBindingName<typename ScopeDataT::NameType>>
    272 GetScopeDataTrailingNames(const ScopeDataT* data) {
    273  return mozilla::Span(GetScopeDataTrailingNamesPointer(data), data->length);
    274 }
    275 
    276 using BaseScopeData = AbstractBaseScopeData<JSAtom>;
    277 
    278 inline void PoisonNames(AbstractBindingName<JSAtom>* data, uint32_t length) {
    279  AlwaysPoison(data, JS_SCOPE_DATA_TRAILING_NAMES_PATTERN,
    280               sizeof(AbstractBindingName<JSAtom>) * length,
    281               MemCheckKind::MakeUndefined);
    282 }
    283 
    284 // frontend::TaggedParserAtomIndex doesn't require poison value.
    285 // Fill with null value instead.
    286 inline void PoisonNames(
    287    AbstractBindingName<frontend::TaggedParserAtomIndex>* data,
    288    uint32_t length) {
    289  std::fill_n(data, length,
    290              AbstractBindingName<frontend::TaggedParserAtomIndex>());
    291 }
    292 
    293 template <typename ScopeDataT>
    294 static inline void PoisonNames(ScopeDataT* data, uint32_t length) {
    295  if (length) {
    296    PoisonNames(GetScopeDataTrailingNamesPointer(data), length);
    297  }
    298 }
    299 
    300 //
    301 // Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
    302 //
    303 template <typename Wrapper>
    304 class WrappedPtrOperations<Scope*, Wrapper> {
    305 public:
    306  template <class U>
    307  JS::Handle<U*> as() const {
    308    const Wrapper& self = *static_cast<const Wrapper*>(this);
    309    MOZ_ASSERT_IF(self, self->template is<U>());
    310    return Handle<U*>::fromMarkedLocation(
    311        reinterpret_cast<U* const*>(self.address()));
    312  }
    313 };
    314 
    315 //
    316 // The base class of all Scopes.
    317 //
    318 class Scope : public gc::TenuredCellWithNonGCPointer<BaseScopeData> {
    319  friend class GCMarker;
    320  friend class frontend::ScopeStencil;
    321  friend class js::AbstractBindingIter<JSAtom>;
    322  friend class js::frontend::RuntimeScopeBindingCache;
    323  friend class gc::CellAllocator;
    324 
    325 protected:
    326  // The raw data pointer, stored in the cell header.
    327  BaseScopeData* rawData() { return headerPtr(); }
    328  const BaseScopeData* rawData() const { return headerPtr(); }
    329 
    330  // The kind determines data_.
    331  const ScopeKind kind_;
    332 
    333  // If there are any aliased bindings, the shape for the
    334  // EnvironmentObject. Otherwise nullptr.
    335  const GCPtr<SharedShape*> environmentShape_;
    336 
    337  // The enclosing scope or nullptr.
    338  GCPtr<Scope*> enclosingScope_;
    339 
    340  Scope(ScopeKind kind, Scope* enclosing, SharedShape* environmentShape)
    341      : TenuredCellWithNonGCPointer(nullptr),
    342        kind_(kind),
    343        environmentShape_(environmentShape),
    344        enclosingScope_(enclosing) {}
    345 
    346  static Scope* create(JSContext* cx, ScopeKind kind, Handle<Scope*> enclosing,
    347                       Handle<SharedShape*> envShape);
    348 
    349  template <typename ConcreteScope>
    350  void initData(HandleBuffer<typename ConcreteScope::RuntimeData> data);
    351 
    352  template <typename F>
    353  void applyScopeDataTyped(F&& f);
    354 
    355  static void updateEnvShapeIfRequired(mozilla::Maybe<uint32_t>* envShape,
    356                                       bool needsEnvironment);
    357 
    358 public:
    359  template <typename ConcreteScope>
    360  static ConcreteScope* create(
    361      JSContext* cx, ScopeKind kind, Handle<Scope*> enclosing,
    362      Handle<SharedShape*> envShape,
    363      HandleBuffer<typename ConcreteScope::RuntimeData> data);
    364 
    365  static const JS::TraceKind TraceKind = JS::TraceKind::Scope;
    366 
    367  template <typename T>
    368  bool is() const {
    369    return kind_ == T::classScopeKind_;
    370  }
    371 
    372  template <typename T>
    373  T& as() {
    374    MOZ_ASSERT(this->is<T>());
    375    return *static_cast<T*>(this);
    376  }
    377 
    378  template <typename T>
    379  const T& as() const {
    380    MOZ_ASSERT(this->is<T>());
    381    return *static_cast<const T*>(this);
    382  }
    383 
    384  ScopeKind kind() const { return kind_; }
    385 
    386  bool isNamedLambda() const {
    387    return kind() == ScopeKind::NamedLambda ||
    388           kind() == ScopeKind::StrictNamedLambda;
    389  }
    390 
    391  SharedShape* environmentShape() const { return environmentShape_; }
    392 
    393  Scope* enclosing() const { return enclosingScope_; }
    394 
    395  static bool hasEnvironment(ScopeKind kind, bool hasEnvironmentShape = false) {
    396    switch (kind) {
    397      case ScopeKind::With:
    398      case ScopeKind::Global:
    399      case ScopeKind::NonSyntactic:
    400        return true;
    401      default:
    402        // If there's a shape, an environment must be created for this scope.
    403        return hasEnvironmentShape;
    404    }
    405  }
    406 
    407  bool hasEnvironment() const {
    408    return hasEnvironment(kind_, !!environmentShape());
    409  }
    410 
    411  uint32_t firstFrameSlot() const;
    412 
    413  uint32_t chainLength() const;
    414  uint32_t environmentChainLength() const;
    415 
    416  template <typename T>
    417  bool hasOnChain() const {
    418    for (const Scope* it = this; it; it = it->enclosing()) {
    419      if (it->is<T>()) {
    420        return true;
    421      }
    422    }
    423    return false;
    424  }
    425 
    426  bool hasOnChain(ScopeKind kind) const {
    427    for (const Scope* it = this; it; it = it->enclosing()) {
    428      if (it->kind() == kind) {
    429        return true;
    430      }
    431    }
    432    return false;
    433  }
    434 
    435  void traceChildren(JSTracer* trc);
    436 
    437  size_t sizeOfExcludingThis() const;
    438 
    439  void dump();
    440 #if defined(DEBUG) || defined(JS_JITSPEW)
    441  static bool dumpForDisassemble(JSContext* cx, JS::Handle<Scope*> scope,
    442                                 GenericPrinter& out, const char* indent);
    443 #endif /* defined(DEBUG) || defined(JS_JITSPEW) */
    444 };
    445 
    446 template <class DataT>
    447 inline size_t SizeOfScopeData(uint32_t length) {
    448  using BindingT = AbstractBindingName<typename DataT::NameType>;
    449  return GetOffsetOfScopeDataTrailingNames<DataT>() + length * sizeof(BindingT);
    450 }
    451 
    452 //
    453 // A useful typedef for selecting between a gc-aware wrappers
    454 // around pointers to BaseScopeData-derived types, and around raw
    455 // pointer wrappers around BaseParserScopeData-derived types.
    456 //
    457 template <typename ScopeT, typename AtomT>
    458 using AbstractScopeData = typename ScopeT::template AbstractData<AtomT>;
    459 
    460 // Binding names are stored from `this+1`.
    461 // Make sure the class aligns the binding name size.
    462 template <typename SlotInfo>
    463 struct alignas(alignof(AbstractBindingName<frontend::TaggedParserAtomIndex>))
    464    ParserScopeData
    465    : public AbstractBaseScopeData<frontend::TaggedParserAtomIndex> {
    466  SlotInfo slotInfo;
    467 
    468  explicit ParserScopeData(size_t length) { PoisonNames(this, length); }
    469  ParserScopeData() = delete;
    470 };
    471 
    472 // RuntimeScopeData has 2 requirements:
    473 //   * It aligns with `BindingName`, that is stored after `this+1`
    474 //   * It aligns with ScopeDataAlignBytes, in order to put it in the first
    475 //     word of `js::Scope`
    476 static_assert(alignof(BindingName) <= ScopeDataAlignBytes);
    477 template <typename SlotInfo>
    478 struct alignas(ScopeDataAlignBytes) RuntimeScopeData
    479    : public AbstractBaseScopeData<JSAtom> {
    480  SlotInfo slotInfo;
    481 
    482  explicit RuntimeScopeData(size_t length) { PoisonNames(this, length); }
    483  RuntimeScopeData() = delete;
    484 
    485  void trace(JSTracer* trc);
    486 };
    487 
    488 //
    489 // A lexical scope that holds let and const bindings. There are 4 kinds of
    490 // LexicalScopes.
    491 //
    492 // Lexical
    493 //   A plain lexical scope.
    494 //
    495 // SimpleCatch
    496 //   Holds the single catch parameter of a catch block.
    497 //
    498 // Catch
    499 //   Holds the catch parameters (and only the catch parameters) of a catch
    500 //   block.
    501 //
    502 // NamedLambda
    503 // StrictNamedLambda
    504 //   Holds the single name of the callee for a named lambda expression.
    505 //
    506 // All kinds of LexicalScopes correspond to LexicalEnvironmentObjects on the
    507 // environment chain.
    508 //
    509 class LexicalScope : public Scope {
    510  friend class Scope;
    511  friend class AbstractBindingIter<JSAtom>;
    512  friend class GCMarker;
    513  friend class frontend::ScopeStencil;
    514 
    515 public:
    516  struct SlotInfo {
    517    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    518    // scope.
    519    uint32_t nextFrameSlot = 0;
    520 
    521    // Bindings are sorted by kind in both frames and environments.
    522    //
    523    //   lets - [0, constStart)
    524    // consts - [constStart, length)
    525    uint32_t constStart = 0;
    526 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    527    // consts - [constStart, usingStart)
    528    // usings - [usingStart, length)
    529    uint32_t usingStart = 0;
    530 #endif
    531  };
    532 
    533  using RuntimeData = RuntimeScopeData<SlotInfo>;
    534  using ParserData = ParserScopeData<SlotInfo>;
    535 
    536  template <typename NameT>
    537  using AbstractData =
    538      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    539                                  RuntimeData, ParserData>;
    540 
    541 private:
    542  static void prepareForScopeCreation(ScopeKind kind, uint32_t firstFrameSlot,
    543                                      LexicalScope::ParserData* data,
    544                                      mozilla::Maybe<uint32_t>* envShape);
    545 
    546  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    547  const RuntimeData& data() const {
    548    return *static_cast<const RuntimeData*>(rawData());
    549  }
    550 
    551 public:
    552  static uint32_t nextFrameSlot(Scope* scope);
    553 
    554  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
    555 
    556  // Returns an empty shape for extensible global and non-syntactic lexical
    557  // scopes.
    558  static SharedShape* getEmptyExtensibleEnvironmentShape(JSContext* cx);
    559 };
    560 
    561 template <>
    562 inline bool Scope::is<LexicalScope>() const {
    563  return kind_ == ScopeKind::Lexical || kind_ == ScopeKind::SimpleCatch ||
    564         kind_ == ScopeKind::Catch || kind_ == ScopeKind::NamedLambda ||
    565         kind_ == ScopeKind::StrictNamedLambda ||
    566         kind_ == ScopeKind::FunctionLexical;
    567 }
    568 
    569 // The body scope of a JS class, containing only synthetic bindings for private
    570 // class members. (The binding for the class name, `C` in the example below, is
    571 // in another scope, a `LexicalScope`, that encloses the `ClassBodyScope`.)
    572 // Example:
    573 //
    574 //     class C {
    575 //       #f = 0;
    576 //       #m() {
    577 //         return this.#f++;
    578 //       }
    579 //     }
    580 //
    581 // This class has a ClassBodyScope with four synthetic bindings:
    582 // - `#f` (private name)
    583 // - `#m` (private name)
    584 // - `#m.method` (function object)
    585 // - `.privateBrand` (the class's private brand)
    586 class ClassBodyScope : public Scope {
    587  friend class Scope;
    588  friend class AbstractBindingIter<JSAtom>;
    589  friend class GCMarker;
    590  friend class frontend::ScopeStencil;
    591  friend class AbstractScopePtr;
    592 
    593  static const ScopeKind classScopeKind_ = ScopeKind::ClassBody;
    594 
    595 public:
    596  struct SlotInfo {
    597    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    598    // scope.
    599    uint32_t nextFrameSlot = 0;
    600 
    601    // Bindings are sorted by kind in both frames and environments.
    602    //
    603    //     synthetic - [0, privateMethodStart)
    604    // privateMethod - [privateMethodStart, length)
    605    uint32_t privateMethodStart = 0;
    606  };
    607 
    608  using RuntimeData = RuntimeScopeData<SlotInfo>;
    609  using ParserData = ParserScopeData<SlotInfo>;
    610 
    611  template <typename NameT>
    612  using AbstractData =
    613      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    614                                  RuntimeData, ParserData>;
    615 
    616 private:
    617  static void prepareForScopeCreation(ScopeKind kind, uint32_t firstFrameSlot,
    618                                      ClassBodyScope::ParserData* data,
    619                                      mozilla::Maybe<uint32_t>* envShape);
    620 
    621  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    622  const RuntimeData& data() const {
    623    return *static_cast<const RuntimeData*>(rawData());
    624  }
    625 
    626 public:
    627  static uint32_t nextFrameSlot(Scope* scope);
    628 
    629  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
    630 
    631  // Returns an empty shape for extensible global and non-syntactic lexical
    632  // scopes.
    633  static SharedShape* getEmptyExtensibleEnvironmentShape(JSContext* cx);
    634 };
    635 
    636 //
    637 // Scope corresponding to a function. Holds formal parameter names, special
    638 // internal names (see FunctionScope::isSpecialName), and, if the function
    639 // parameters contain no expressions that might possibly be evaluated, the
    640 // function's var bindings. For example, in these functions, the FunctionScope
    641 // will store a/b/c bindings but not d/e/f bindings:
    642 //
    643 //   function f1(a, b) {
    644 //     var c;
    645 //     let e;
    646 //     const f = 3;
    647 //   }
    648 //   function f2([a], b = 4, ...c) {
    649 //     var d, e, f; // stored in VarScope
    650 //   }
    651 //
    652 // Corresponds to CallObject on environment chain.
    653 //
    654 class FunctionScope : public Scope {
    655  friend class GCMarker;
    656  friend class AbstractBindingIter<JSAtom>;
    657  friend class AbstractPositionalFormalParameterIter<JSAtom>;
    658  friend class Scope;
    659  friend class AbstractScopePtr;
    660  static const ScopeKind classScopeKind_ = ScopeKind::Function;
    661 
    662 public:
    663  struct SlotInfo {
    664    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    665    // scope.
    666    uint32_t nextFrameSlot = 0;
    667 
    668    // Flag bits.
    669    // This uses uint32_t in order to make this struct packed.
    670    uint32_t flags = 0;
    671 
    672    // If parameter expressions are present, parameters act like lexical
    673    // bindings.
    674    static constexpr uint32_t HasParameterExprsFlag = 1;
    675 
    676    // Bindings are sorted by kind in both frames and environments.
    677    //
    678    // Positional formal parameter names are those that are not
    679    // destructured. They may be referred to by argument slots if
    680    // !script()->hasParameterExprs().
    681    //
    682    // An argument slot that needs to be skipped due to being destructured
    683    // or having defaults will have a nullptr name in the name array to
    684    // advance the argument slot.
    685    //
    686    // Rest parameter binding is also included in positional formals.
    687    // This also becomes nullptr if destructuring.
    688    //
    689    // The number of positional formals is equal to function.length if
    690    // there's no rest, function.length+1 otherwise.
    691    //
    692    // Destructuring parameters and destructuring rest are included in
    693    // "other formals" below.
    694    //
    695    // "vars" contains the following:
    696    //   * function's top level vars if !script()->hasParameterExprs()
    697    //   * special internal names (arguments, .this, .generator) if
    698    //     they're used.
    699    //
    700    // positional formals - [0, nonPositionalFormalStart)
    701    //      other formals - [nonPositionalParamStart, varStart)
    702    //               vars - [varStart, length)
    703    uint16_t nonPositionalFormalStart = 0;
    704    uint16_t varStart = 0;
    705 
    706    bool hasParameterExprs() const { return flags & HasParameterExprsFlag; }
    707    void setHasParameterExprs() { flags |= HasParameterExprsFlag; }
    708  };
    709 
    710  struct alignas(ScopeDataAlignBytes) RuntimeData
    711      : public AbstractBaseScopeData<JSAtom> {
    712    SlotInfo slotInfo;
    713    // The canonical function of the scope, as during a scope walk we
    714    // often query properties of the JSFunction (e.g., is the function an
    715    // arrow).
    716    GCPtr<JSFunction*> canonicalFunction = {};
    717 
    718    explicit RuntimeData(size_t length) { PoisonNames(this, length); }
    719    RuntimeData() = delete;
    720 
    721    inline void trace(JSTracer* trc);
    722  };
    723 
    724  using ParserData = ParserScopeData<SlotInfo>;
    725 
    726  template <typename NameT>
    727  using AbstractData =
    728      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    729                                  RuntimeData, ParserData>;
    730 
    731  static void prepareForScopeCreation(FunctionScope::ParserData* data,
    732                                      bool hasParameterExprs,
    733                                      bool needsEnvironment,
    734                                      mozilla::Maybe<uint32_t>* envShape);
    735 
    736 private:
    737  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    738 
    739  const RuntimeData& data() const {
    740    return *static_cast<const RuntimeData*>(rawData());
    741  }
    742 
    743 public:
    744  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
    745 
    746  JSFunction* canonicalFunction() const { return data().canonicalFunction; }
    747  void initCanonicalFunction(JSFunction* fun) {
    748    data().canonicalFunction.init(fun);
    749  }
    750 
    751  JSScript* script() const;
    752 
    753  bool hasParameterExprs() const { return data().slotInfo.hasParameterExprs(); }
    754 
    755  uint32_t numPositionalFormalParameters() const {
    756    return data().slotInfo.nonPositionalFormalStart;
    757  }
    758 
    759  static bool isSpecialName(frontend::TaggedParserAtomIndex name);
    760 };
    761 
    762 //
    763 // Scope holding only vars. There is a single kind of VarScopes.
    764 //
    765 // FunctionBodyVar
    766 //   Corresponds to the extra var scope present in functions with parameter
    767 //   expressions. See examples in comment above FunctionScope.
    768 //
    769 // Corresponds to VarEnvironmentObject on environment chain.
    770 //
    771 class VarScope : public Scope {
    772  friend class GCMarker;
    773  friend class AbstractBindingIter<JSAtom>;
    774  friend class Scope;
    775  friend class frontend::ScopeStencil;
    776 
    777 public:
    778  struct SlotInfo {
    779    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    780    // scope.
    781    uint32_t nextFrameSlot = 0;
    782 
    783    // All bindings are vars.
    784    //
    785    //            vars - [0, length)
    786  };
    787 
    788  using RuntimeData = RuntimeScopeData<SlotInfo>;
    789  using ParserData = ParserScopeData<SlotInfo>;
    790 
    791  template <typename NameT>
    792  using AbstractData =
    793      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    794                                  RuntimeData, ParserData>;
    795 
    796 private:
    797  static void prepareForScopeCreation(ScopeKind kind,
    798                                      VarScope::ParserData* data,
    799                                      uint32_t firstFrameSlot,
    800                                      bool needsEnvironment,
    801                                      mozilla::Maybe<uint32_t>* envShape);
    802 
    803  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    804 
    805  const RuntimeData& data() const {
    806    return *static_cast<const RuntimeData*>(rawData());
    807  }
    808 
    809 public:
    810  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
    811 };
    812 
    813 template <>
    814 inline bool Scope::is<VarScope>() const {
    815  return kind_ == ScopeKind::FunctionBodyVar;
    816 }
    817 
    818 //
    819 // Scope corresponding to both the global object scope and the global lexical
    820 // scope.
    821 //
    822 // Both are extensible and are singletons across <script> tags, so these
    823 // scopes are a fragment of the names in global scope. In other words, two
    824 // global scripts may have two different GlobalScopes despite having the same
    825 // GlobalObject.
    826 //
    827 // There are 2 kinds of GlobalScopes.
    828 //
    829 // Global
    830 //   Corresponds to a GlobalObject and its GlobalLexicalEnvironmentObject on
    831 //   the environment chain.
    832 //
    833 // NonSyntactic
    834 //   Corresponds to a non-GlobalObject created by the embedding on the
    835 //   environment chain. This distinction is important for optimizations.
    836 //
    837 class GlobalScope : public Scope {
    838  friend class Scope;
    839  friend class AbstractBindingIter<JSAtom>;
    840  friend class GCMarker;
    841 
    842 public:
    843  struct SlotInfo {
    844    // Bindings are sorted by kind.
    845    // `vars` includes top-level functions which is distinguished by a bit
    846    // on the BindingName.
    847    //
    848    //            vars - [0, letStart)
    849    //            lets - [letStart, constStart)
    850    //          consts - [constStart, length)
    851    uint32_t letStart = 0;
    852    uint32_t constStart = 0;
    853  };
    854 
    855  using RuntimeData = RuntimeScopeData<SlotInfo>;
    856  using ParserData = ParserScopeData<SlotInfo>;
    857 
    858  template <typename NameT>
    859  using AbstractData =
    860      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    861                                  RuntimeData, ParserData>;
    862 
    863  static GlobalScope* createEmpty(JSContext* cx, ScopeKind kind);
    864 
    865 private:
    866  static GlobalScope* createWithData(JSContext* cx, ScopeKind kind,
    867                                     HandleBuffer<RuntimeData> data);
    868 
    869  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    870 
    871  const RuntimeData& data() const {
    872    return *static_cast<const RuntimeData*>(rawData());
    873  }
    874 
    875 public:
    876  bool isSyntactic() const { return kind() != ScopeKind::NonSyntactic; }
    877 
    878  bool hasBindings() const { return data().length > 0; }
    879 };
    880 
    881 template <>
    882 inline bool Scope::is<GlobalScope>() const {
    883  return kind_ == ScopeKind::Global || kind_ == ScopeKind::NonSyntactic;
    884 }
    885 
    886 //
    887 // Scope of a 'with' statement. Has no bindings.
    888 //
    889 // Corresponds to a WithEnvironmentObject on the environment chain.
    890 class WithScope : public Scope {
    891  friend class Scope;
    892  friend class AbstractScopePtr;
    893  static const ScopeKind classScopeKind_ = ScopeKind::With;
    894 
    895 public:
    896  static WithScope* create(JSContext* cx, Handle<Scope*> enclosing);
    897 };
    898 
    899 //
    900 // Scope of an eval. Holds var bindings. There are 2 kinds of EvalScopes.
    901 //
    902 // StrictEval
    903 //   A strict eval. Corresponds to a VarEnvironmentObject, where its var
    904 //   bindings lives.
    905 //
    906 // Eval
    907 //   A sloppy eval. This is an empty scope, used only in the frontend, to
    908 //   detect redeclaration errors. It has no Environment. Any `var`s declared
    909 //   in the eval code are bound on the nearest enclosing var environment.
    910 //
    911 class EvalScope : public Scope {
    912  friend class Scope;
    913  friend class AbstractBindingIter<JSAtom>;
    914  friend class GCMarker;
    915  friend class frontend::ScopeStencil;
    916 
    917 public:
    918  struct SlotInfo {
    919    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    920    // scope.
    921    uint32_t nextFrameSlot = 0;
    922 
    923    // All bindings in an eval script are 'var' bindings. The implicit
    924    // lexical scope around the eval is present regardless of strictness
    925    // and is its own LexicalScope.
    926    // `vars` includes top-level functions which is distinguished by a bit
    927    // on the BindingName.
    928    //
    929    //            vars - [0, length)
    930  };
    931 
    932  using RuntimeData = RuntimeScopeData<SlotInfo>;
    933  using ParserData = ParserScopeData<SlotInfo>;
    934 
    935  template <typename NameT>
    936  using AbstractData =
    937      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
    938                                  RuntimeData, ParserData>;
    939 
    940 private:
    941  static void prepareForScopeCreation(ScopeKind scopeKind,
    942                                      EvalScope::ParserData* data,
    943                                      mozilla::Maybe<uint32_t>* envShape);
    944 
    945  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
    946 
    947  const RuntimeData& data() const {
    948    return *static_cast<const RuntimeData*>(rawData());
    949  }
    950 
    951 public:
    952  // Starting a scope, the nearest var scope that a direct eval can
    953  // introduce vars on.
    954  static Scope* nearestVarScopeForDirectEval(Scope* scope);
    955 
    956  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
    957 
    958  bool strict() const { return kind() == ScopeKind::StrictEval; }
    959 
    960  bool hasBindings() const { return data().length > 0; }
    961 
    962  bool isNonGlobal() const {
    963    if (strict()) {
    964      return true;
    965    }
    966    return !nearestVarScopeForDirectEval(enclosing())->is<GlobalScope>();
    967  }
    968 };
    969 
    970 template <>
    971 inline bool Scope::is<EvalScope>() const {
    972  return kind_ == ScopeKind::Eval || kind_ == ScopeKind::StrictEval;
    973 }
    974 
    975 //
    976 // Scope corresponding to the toplevel script in an ES module.
    977 //
    978 // Like GlobalScopes, these scopes contain both vars and lexical bindings, as
    979 // the treating of imports and exports requires putting them in one scope.
    980 //
    981 // Corresponds to a ModuleEnvironmentObject on the environment chain.
    982 //
    983 class ModuleScope : public Scope {
    984  friend class GCMarker;
    985  friend class AbstractBindingIter<JSAtom>;
    986  friend class Scope;
    987  friend class AbstractScopePtr;
    988  friend class frontend::ScopeStencil;
    989  static const ScopeKind classScopeKind_ = ScopeKind::Module;
    990 
    991 public:
    992  struct SlotInfo {
    993    // Frame slots [0, nextFrameSlot) are live when this is the innermost
    994    // scope.
    995    uint32_t nextFrameSlot = 0;
    996 
    997    // Bindings are sorted by kind.
    998    //
    999    // imports - [0, varStart)
   1000    //    vars - [varStart, letStart)
   1001    //    lets - [letStart, constStart)
   1002    //  consts - [constStart, length)
   1003    uint32_t varStart = 0;
   1004    uint32_t letStart = 0;
   1005    uint32_t constStart = 0;
   1006 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1007    // consts - [constStart, usingStart)
   1008    // usings - [usingStart, length)
   1009    uint32_t usingStart = 0;
   1010 #endif
   1011  };
   1012 
   1013  struct alignas(ScopeDataAlignBytes) RuntimeData
   1014      : public AbstractBaseScopeData<JSAtom> {
   1015    SlotInfo slotInfo;
   1016    // The module of the scope.
   1017    GCPtr<ModuleObject*> module = {};
   1018 
   1019    explicit RuntimeData(size_t length);
   1020    RuntimeData() = delete;
   1021 
   1022    inline void trace(JSTracer* trc);
   1023  };
   1024 
   1025  using ParserData = ParserScopeData<SlotInfo>;
   1026 
   1027  template <typename NameT>
   1028  using AbstractData =
   1029      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
   1030                                  RuntimeData, ParserData>;
   1031 
   1032 private:
   1033  static void prepareForScopeCreation(ModuleScope::ParserData* data,
   1034                                      mozilla::Maybe<uint32_t>* envShape);
   1035 
   1036  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
   1037 
   1038  const RuntimeData& data() const {
   1039    return *static_cast<const RuntimeData*>(rawData());
   1040  }
   1041 
   1042 public:
   1043  uint32_t nextFrameSlot() const { return data().slotInfo.nextFrameSlot; }
   1044 
   1045  ModuleObject* module() const { return data().module; }
   1046  void initModule(ModuleObject* mod) { return data().module.init(mod); }
   1047 
   1048  // Off-thread compilation needs to calculate environmentChainLength for
   1049  // an emptyGlobalScope where the global may not be available.
   1050  static const size_t EnclosingEnvironmentChainLength = 1;
   1051 };
   1052 
   1053 class WasmInstanceScope : public Scope {
   1054  friend class AbstractBindingIter<JSAtom>;
   1055  friend class Scope;
   1056  friend class GCMarker;
   1057  friend class AbstractScopePtr;
   1058  static const ScopeKind classScopeKind_ = ScopeKind::WasmInstance;
   1059 
   1060 public:
   1061  struct SlotInfo {
   1062    // Frame slots [0, nextFrameSlot) are live when this is the innermost
   1063    // scope.
   1064    uint32_t nextFrameSlot = 0;
   1065 
   1066    // Bindings list the WASM memories and globals.
   1067    //
   1068    // memories - [0, globalsStart)
   1069    //  globals - [globalsStart, length)
   1070    uint32_t memoriesStart = 0;
   1071    uint32_t globalsStart = 0;
   1072  };
   1073 
   1074  struct alignas(ScopeDataAlignBytes) RuntimeData
   1075      : public AbstractBaseScopeData<JSAtom> {
   1076    SlotInfo slotInfo;
   1077    // The wasm instance of the scope.
   1078    GCPtr<WasmInstanceObject*> instance = {};
   1079 
   1080    explicit RuntimeData(size_t length);
   1081    RuntimeData() = delete;
   1082 
   1083    inline void trace(JSTracer* trc);
   1084  };
   1085 
   1086  using ParserData = ParserScopeData<SlotInfo>;
   1087 
   1088  template <typename NameT>
   1089  using AbstractData =
   1090      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
   1091                                  RuntimeData, ParserData>;
   1092 
   1093  static WasmInstanceScope* create(JSContext* cx,
   1094                                   Handle<WasmInstanceObject*> instance);
   1095 
   1096 private:
   1097  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
   1098 
   1099  const RuntimeData& data() const {
   1100    return *static_cast<const RuntimeData*>(rawData());
   1101  }
   1102 
   1103 public:
   1104  WasmInstanceObject* instance() const { return data().instance; }
   1105 
   1106  uint32_t memoriesStart() const { return data().slotInfo.memoriesStart; }
   1107 
   1108  uint32_t globalsStart() const { return data().slotInfo.globalsStart; }
   1109 
   1110  uint32_t namesCount() const { return data().length; }
   1111 };
   1112 
   1113 // Scope corresponding to the wasm function. A WasmFunctionScope is used by
   1114 // Debugger only, and not for wasm execution.
   1115 //
   1116 class WasmFunctionScope : public Scope {
   1117  friend class AbstractBindingIter<JSAtom>;
   1118  friend class Scope;
   1119  friend class GCMarker;
   1120  friend class AbstractScopePtr;
   1121  static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
   1122 
   1123 public:
   1124  struct SlotInfo {
   1125    // Frame slots [0, nextFrameSlot) are live when this is the innermost
   1126    // scope.
   1127    uint32_t nextFrameSlot = 0;
   1128 
   1129    // Bindings are the local variable names.
   1130    //
   1131    //    vars - [0, length)
   1132  };
   1133 
   1134  using RuntimeData = RuntimeScopeData<SlotInfo>;
   1135  using ParserData = ParserScopeData<SlotInfo>;
   1136 
   1137  template <typename NameT>
   1138  using AbstractData =
   1139      typename std::conditional_t<std::is_same<NameT, JSAtom>::value,
   1140                                  RuntimeData, ParserData>;
   1141 
   1142  static WasmFunctionScope* create(JSContext* cx, Handle<Scope*> enclosing,
   1143                                   uint32_t funcIndex);
   1144 
   1145 private:
   1146  RuntimeData& data() { return *static_cast<RuntimeData*>(rawData()); }
   1147 
   1148  const RuntimeData& data() const {
   1149    return *static_cast<const RuntimeData*>(rawData());
   1150  }
   1151 };
   1152 
   1153 template <typename F>
   1154 void Scope::applyScopeDataTyped(F&& f) {
   1155  switch (kind()) {
   1156    case ScopeKind::Function: {
   1157      f(&as<FunctionScope>().data());
   1158      break;
   1159      case ScopeKind::FunctionBodyVar:
   1160        f(&as<VarScope>().data());
   1161        break;
   1162      case ScopeKind::Lexical:
   1163      case ScopeKind::SimpleCatch:
   1164      case ScopeKind::Catch:
   1165      case ScopeKind::NamedLambda:
   1166      case ScopeKind::StrictNamedLambda:
   1167      case ScopeKind::FunctionLexical:
   1168        f(&as<LexicalScope>().data());
   1169        break;
   1170      case ScopeKind::ClassBody:
   1171        f(&as<ClassBodyScope>().data());
   1172        break;
   1173      case ScopeKind::With:
   1174        // With scopes do not have data.
   1175        break;
   1176      case ScopeKind::Eval:
   1177      case ScopeKind::StrictEval:
   1178        f(&as<EvalScope>().data());
   1179        break;
   1180      case ScopeKind::Global:
   1181      case ScopeKind::NonSyntactic:
   1182        f(&as<GlobalScope>().data());
   1183        break;
   1184      case ScopeKind::Module:
   1185        f(&as<ModuleScope>().data());
   1186        break;
   1187      case ScopeKind::WasmInstance:
   1188        f(&as<WasmInstanceScope>().data());
   1189        break;
   1190      case ScopeKind::WasmFunction:
   1191        f(&as<WasmFunctionScope>().data());
   1192        break;
   1193    }
   1194  }
   1195 }
   1196 
   1197 //
   1198 // An iterator for a Scope's bindings. This is the source of truth for frame
   1199 // and environment object layout.
   1200 //
   1201 // It may be placed in GC containers; for example:
   1202 //
   1203 //   for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
   1204 //     use(bi);
   1205 //     SomeMayGCOperation();
   1206 //     use(bi);
   1207 //   }
   1208 //
   1209 template <typename NameT>
   1210 class BaseAbstractBindingIter {
   1211 protected:
   1212  // Bindings are sorted by kind. Because different Scopes have differently
   1213  // laid out {Runtime,Parser}Data for packing, BindingIter must handle all
   1214  // binding kinds.
   1215  //
   1216  // Kind ranges:
   1217  //
   1218  //            imports - [0, positionalFormalStart)
   1219  // positional formals - [positionalFormalStart, nonPositionalFormalStart)
   1220  //      other formals - [nonPositionalParamStart, varStart)
   1221  //               vars - [varStart, letStart)
   1222  //               lets - [letStart, constStart)
   1223  //             consts - [constStart, syntheticStart)
   1224  //          synthetic - [syntheticStart, privateMethodStart)
   1225  //    private methods = [privateMethodStart, length)
   1226  //
   1227  // If ENABLE_EXPLICIT_RESOURCE_MANAGEMENT is set, the consts range is split
   1228  // into the following:
   1229  //             consts - [constStart, usingStart)
   1230  //             usings - [usingStart, syntheticStart)
   1231  //
   1232  // Access method when not closed over:
   1233  //
   1234  //            imports - name
   1235  // positional formals - argument slot
   1236  //      other formals - frame slot
   1237  //               vars - frame slot
   1238  //               lets - frame slot
   1239  //             consts - frame slot
   1240  //          synthetic - frame slot
   1241  //    private methods - frame slot
   1242  //
   1243  // Access method when closed over:
   1244  //
   1245  //            imports - name
   1246  // positional formals - environment slot or name
   1247  //      other formals - environment slot or name
   1248  //               vars - environment slot or name
   1249  //               lets - environment slot or name
   1250  //             consts - environment slot or name
   1251  //          synthetic - environment slot or name
   1252  //    private methods - environment slot or name
   1253  MOZ_INIT_OUTSIDE_CTOR uint32_t positionalFormalStart_;
   1254  MOZ_INIT_OUTSIDE_CTOR uint32_t nonPositionalFormalStart_;
   1255  MOZ_INIT_OUTSIDE_CTOR uint32_t varStart_;
   1256  MOZ_INIT_OUTSIDE_CTOR uint32_t letStart_;
   1257  MOZ_INIT_OUTSIDE_CTOR uint32_t constStart_;
   1258 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1259  MOZ_INIT_OUTSIDE_CTOR uint32_t usingStart_;
   1260 #endif
   1261  MOZ_INIT_OUTSIDE_CTOR uint32_t syntheticStart_;
   1262  MOZ_INIT_OUTSIDE_CTOR uint32_t privateMethodStart_;
   1263  MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
   1264 
   1265  MOZ_INIT_OUTSIDE_CTOR uint32_t index_;
   1266 
   1267  enum Flags : uint8_t {
   1268    CannotHaveSlots = 0,
   1269    CanHaveArgumentSlots = 1 << 0,
   1270    CanHaveFrameSlots = 1 << 1,
   1271    CanHaveEnvironmentSlots = 1 << 2,
   1272 
   1273    // See comment in settle below.
   1274    HasFormalParameterExprs = 1 << 3,
   1275    IgnoreDestructuredFormalParameters = 1 << 4,
   1276 
   1277    // Truly I hate named lambdas.
   1278    IsNamedLambda = 1 << 5
   1279  };
   1280 
   1281  static const uint8_t CanHaveSlotsMask = 0x7;
   1282 
   1283  MOZ_INIT_OUTSIDE_CTOR uint8_t flags_;
   1284  MOZ_INIT_OUTSIDE_CTOR uint16_t argumentSlot_;
   1285  MOZ_INIT_OUTSIDE_CTOR uint32_t frameSlot_;
   1286  MOZ_INIT_OUTSIDE_CTOR uint32_t environmentSlot_;
   1287 
   1288  MOZ_INIT_OUTSIDE_CTOR AbstractBindingName<NameT>* names_;
   1289 
   1290  void init(uint32_t positionalFormalStart, uint32_t nonPositionalFormalStart,
   1291            uint32_t varStart, uint32_t letStart, uint32_t constStart,
   1292 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1293            uint32_t usingStart,
   1294 #endif
   1295            uint32_t syntheticStart, uint32_t privateMethodStart, uint8_t flags,
   1296            uint32_t firstFrameSlot, uint32_t firstEnvironmentSlot,
   1297            mozilla::Span<AbstractBindingName<NameT>> names) {
   1298    positionalFormalStart_ = positionalFormalStart;
   1299    nonPositionalFormalStart_ = nonPositionalFormalStart;
   1300    varStart_ = varStart;
   1301    letStart_ = letStart;
   1302    constStart_ = constStart;
   1303 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1304    usingStart_ = usingStart;
   1305 #endif
   1306    syntheticStart_ = syntheticStart;
   1307    privateMethodStart_ = privateMethodStart;
   1308    length_ = names.size();
   1309 
   1310    index_ = 0;
   1311    flags_ = flags;
   1312    argumentSlot_ = 0;
   1313    frameSlot_ = firstFrameSlot;
   1314    environmentSlot_ = firstEnvironmentSlot;
   1315    names_ = names.data();
   1316 
   1317    settle();
   1318  }
   1319 
   1320  void init(LexicalScope::AbstractData<NameT>& data, uint32_t firstFrameSlot,
   1321            uint8_t flags);
   1322 
   1323  void init(ClassBodyScope::AbstractData<NameT>& data, uint32_t firstFrameSlot);
   1324  void init(FunctionScope::AbstractData<NameT>& data, uint8_t flags);
   1325 
   1326  void init(VarScope::AbstractData<NameT>& data, uint32_t firstFrameSlot);
   1327  void init(GlobalScope::AbstractData<NameT>& data);
   1328  void init(EvalScope::AbstractData<NameT>& data, bool strict);
   1329  void init(ModuleScope::AbstractData<NameT>& data);
   1330  void init(WasmInstanceScope::AbstractData<NameT>& data);
   1331  void init(WasmFunctionScope::AbstractData<NameT>& data);
   1332 
   1333  bool hasFormalParameterExprs() const {
   1334    return flags_ & HasFormalParameterExprs;
   1335  }
   1336 
   1337  bool ignoreDestructuredFormalParameters() const {
   1338    return flags_ & IgnoreDestructuredFormalParameters;
   1339  }
   1340 
   1341  bool isNamedLambda() const { return flags_ & IsNamedLambda; }
   1342 
   1343  void increment() {
   1344    MOZ_ASSERT(!done());
   1345    if (flags_ & CanHaveSlotsMask) {
   1346      if (canHaveArgumentSlots()) {
   1347        if (index_ < nonPositionalFormalStart_) {
   1348          MOZ_ASSERT(index_ >= positionalFormalStart_);
   1349          argumentSlot_++;
   1350        }
   1351      }
   1352      if (closedOver()) {
   1353        // Imports must not be given known slots. They are
   1354        // indirect bindings.
   1355        MOZ_ASSERT(kind() != BindingKind::Import);
   1356        MOZ_ASSERT(canHaveEnvironmentSlots());
   1357        environmentSlot_++;
   1358      } else if (canHaveFrameSlots()) {
   1359        // Usually positional formal parameters don't have frame
   1360        // slots, except when there are parameter expressions, in
   1361        // which case they act like lets.
   1362        if (index_ >= nonPositionalFormalStart_ ||
   1363            (hasFormalParameterExprs() && name())) {
   1364          frameSlot_++;
   1365        }
   1366      }
   1367    }
   1368    index_++;
   1369  }
   1370 
   1371  void settle() {
   1372    if (ignoreDestructuredFormalParameters()) {
   1373      while (!done() && !name()) {
   1374        increment();
   1375      }
   1376    }
   1377  }
   1378 
   1379  BaseAbstractBindingIter() = default;
   1380 
   1381 public:
   1382  BaseAbstractBindingIter(LexicalScope::AbstractData<NameT>& data,
   1383                          uint32_t firstFrameSlot, bool isNamedLambda) {
   1384    init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0);
   1385  }
   1386 
   1387  BaseAbstractBindingIter(ClassBodyScope::AbstractData<NameT>& data,
   1388                          uint32_t firstFrameSlot) {
   1389    init(data, firstFrameSlot);
   1390  }
   1391 
   1392  BaseAbstractBindingIter(FunctionScope::AbstractData<NameT>& data,
   1393                          bool hasParameterExprs) {
   1394    init(data, IgnoreDestructuredFormalParameters |
   1395                   (hasParameterExprs ? HasFormalParameterExprs : 0));
   1396  }
   1397 
   1398  BaseAbstractBindingIter(VarScope::AbstractData<NameT>& data,
   1399                          uint32_t firstFrameSlot) {
   1400    init(data, firstFrameSlot);
   1401  }
   1402 
   1403  explicit BaseAbstractBindingIter(GlobalScope::AbstractData<NameT>& data) {
   1404    init(data);
   1405  }
   1406 
   1407  explicit BaseAbstractBindingIter(ModuleScope::AbstractData<NameT>& data) {
   1408    init(data);
   1409  }
   1410 
   1411  explicit BaseAbstractBindingIter(
   1412      WasmFunctionScope::AbstractData<NameT>& data) {
   1413    init(data);
   1414  }
   1415 
   1416  BaseAbstractBindingIter(EvalScope::AbstractData<NameT>& data, bool strict) {
   1417    init(data, strict);
   1418  }
   1419 
   1420  MOZ_IMPLICIT BaseAbstractBindingIter(
   1421      const BaseAbstractBindingIter<NameT>& bi) = default;
   1422 
   1423  bool done() const { return index_ == length_; }
   1424 
   1425  explicit operator bool() const { return !done(); }
   1426 
   1427  void operator++(int) {
   1428    increment();
   1429    settle();
   1430  }
   1431 
   1432  bool isLast() const {
   1433    MOZ_ASSERT(!done());
   1434    return index_ + 1 == length_;
   1435  }
   1436 
   1437  bool canHaveArgumentSlots() const { return flags_ & CanHaveArgumentSlots; }
   1438 
   1439  bool canHaveFrameSlots() const { return flags_ & CanHaveFrameSlots; }
   1440 
   1441  bool canHaveEnvironmentSlots() const {
   1442    return flags_ & CanHaveEnvironmentSlots;
   1443  }
   1444 
   1445  typename AbstractBindingName<NameT>::NamePointerT name() const {
   1446    MOZ_ASSERT(!done());
   1447    return names_[index_].name();
   1448  }
   1449 
   1450  bool closedOver() const {
   1451    MOZ_ASSERT(!done());
   1452    return names_[index_].closedOver();
   1453  }
   1454 
   1455  BindingLocation location() const {
   1456    MOZ_ASSERT(!done());
   1457    if (!(flags_ & CanHaveSlotsMask)) {
   1458      return BindingLocation::Global();
   1459    }
   1460    if (index_ < positionalFormalStart_) {
   1461      return BindingLocation::Import();
   1462    }
   1463    if (closedOver()) {
   1464      MOZ_ASSERT(canHaveEnvironmentSlots());
   1465      return BindingLocation::Environment(environmentSlot_);
   1466    }
   1467    if (index_ < nonPositionalFormalStart_ && canHaveArgumentSlots()) {
   1468      return BindingLocation::Argument(argumentSlot_);
   1469    }
   1470    if (canHaveFrameSlots()) {
   1471      return BindingLocation::Frame(frameSlot_);
   1472    }
   1473    MOZ_ASSERT(isNamedLambda());
   1474    return BindingLocation::NamedLambdaCallee();
   1475  }
   1476 
   1477  BindingKind kind() const {
   1478    MOZ_ASSERT(!done());
   1479    if (index_ < positionalFormalStart_) {
   1480      return BindingKind::Import;
   1481    }
   1482    if (index_ < varStart_) {
   1483      // When the parameter list has expressions, the parameters act
   1484      // like lexical bindings and have TDZ.
   1485      if (hasFormalParameterExprs()) {
   1486        return BindingKind::Let;
   1487      }
   1488      return BindingKind::FormalParameter;
   1489    }
   1490    if (index_ < letStart_) {
   1491      return BindingKind::Var;
   1492    }
   1493    if (index_ < constStart_) {
   1494      return BindingKind::Let;
   1495    }
   1496 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1497    if (index_ < usingStart_) {
   1498      return isNamedLambda() ? BindingKind::NamedLambdaCallee
   1499                             : BindingKind::Const;
   1500    }
   1501    if (index_ < syntheticStart_) {
   1502      return BindingKind::Using;
   1503    }
   1504 #else
   1505    if (index_ < syntheticStart_) {
   1506      return isNamedLambda() ? BindingKind::NamedLambdaCallee
   1507                             : BindingKind::Const;
   1508    }
   1509 #endif
   1510    if (index_ < privateMethodStart_) {
   1511      return BindingKind::Synthetic;
   1512    }
   1513    return BindingKind::PrivateMethod;
   1514  }
   1515 
   1516  js::frontend::NameLocation nameLocation() const {
   1517    using js::frontend::NameLocation;
   1518 
   1519    BindingKind bindKind = kind();
   1520    BindingLocation bl = location();
   1521    switch (bl.kind()) {
   1522      case BindingLocation::Kind::Global:
   1523        return NameLocation::Global(bindKind);
   1524      case BindingLocation::Kind::Argument:
   1525        return NameLocation::ArgumentSlot(bl.argumentSlot());
   1526      case BindingLocation::Kind::Frame:
   1527        return NameLocation::FrameSlot(bindKind, bl.slot());
   1528      case BindingLocation::Kind::Environment:
   1529        return NameLocation::EnvironmentCoordinate(bindKind, 0, bl.slot());
   1530      case BindingLocation::Kind::Import:
   1531        return NameLocation::Import();
   1532      case BindingLocation::Kind::NamedLambdaCallee:
   1533        return NameLocation::NamedLambdaCallee();
   1534    }
   1535    MOZ_CRASH("Bad BindingKind");
   1536  }
   1537 
   1538  bool isTopLevelFunction() const {
   1539    MOZ_ASSERT(!done());
   1540    bool result = names_[index_].isTopLevelFunction();
   1541    MOZ_ASSERT_IF(result, kind() == BindingKind::Var);
   1542    return result;
   1543  }
   1544 
   1545  bool hasArgumentSlot() const {
   1546    MOZ_ASSERT(!done());
   1547    if (hasFormalParameterExprs()) {
   1548      return false;
   1549    }
   1550    return index_ >= positionalFormalStart_ &&
   1551           index_ < nonPositionalFormalStart_;
   1552  }
   1553 
   1554  uint16_t argumentSlot() const {
   1555    MOZ_ASSERT(canHaveArgumentSlots());
   1556    return mozilla::AssertedCast<uint16_t>(index_);
   1557  }
   1558 
   1559  uint32_t nextFrameSlot() const {
   1560    MOZ_ASSERT(canHaveFrameSlots());
   1561    return frameSlot_;
   1562  }
   1563 
   1564  uint32_t nextEnvironmentSlot() const {
   1565    MOZ_ASSERT(canHaveEnvironmentSlots());
   1566    return environmentSlot_;
   1567  }
   1568 };
   1569 
   1570 template <typename NameT>
   1571 class AbstractBindingIter;
   1572 
   1573 template <>
   1574 class AbstractBindingIter<JSAtom> : public BaseAbstractBindingIter<JSAtom> {
   1575  using Base = BaseAbstractBindingIter<JSAtom>;
   1576 
   1577 public:
   1578  AbstractBindingIter(ScopeKind kind, BaseScopeData* data,
   1579                      uint32_t firstFrameSlot);
   1580 
   1581  explicit AbstractBindingIter(Scope* scope);
   1582  explicit AbstractBindingIter(JSScript* script);
   1583 
   1584  using Base::Base;
   1585 
   1586  inline void trace(JSTracer* trc) {
   1587    TraceNullableBindingNames(trc, names_, length_);
   1588  }
   1589 };
   1590 
   1591 template <>
   1592 class AbstractBindingIter<frontend::TaggedParserAtomIndex>
   1593    : public BaseAbstractBindingIter<frontend::TaggedParserAtomIndex> {
   1594  using Base = BaseAbstractBindingIter<frontend::TaggedParserAtomIndex>;
   1595 
   1596 public:
   1597  explicit AbstractBindingIter(const frontend::ScopeStencilRef& ref);
   1598 
   1599  using Base::Base;
   1600 };
   1601 
   1602 void DumpBindings(JSContext* cx, Scope* scope);
   1603 JSAtom* FrameSlotName(JSScript* script, jsbytecode* pc);
   1604 
   1605 SharedShape* EmptyEnvironmentShape(JSContext* cx, const JSClass* cls,
   1606                                   uint32_t numSlots, ObjectFlags objectFlags);
   1607 
   1608 template <class T>
   1609 SharedShape* EmptyEnvironmentShape(JSContext* cx) {
   1610  return EmptyEnvironmentShape(cx, &T::class_, T::RESERVED_SLOTS,
   1611                               T::OBJECT_FLAGS);
   1612 }
   1613 
   1614 //
   1615 // PositionalFormalParameterIter is a refinement BindingIter that only iterates
   1616 // over positional formal parameters of a function.
   1617 //
   1618 template <typename NameT>
   1619 class BasePositionalFormalParamterIter : public AbstractBindingIter<NameT> {
   1620  using Base = AbstractBindingIter<NameT>;
   1621 
   1622 protected:
   1623  void settle() {
   1624    if (this->index_ >= this->nonPositionalFormalStart_) {
   1625      this->index_ = this->length_;
   1626    }
   1627  }
   1628 
   1629 public:
   1630  using Base::Base;
   1631 
   1632  void operator++(int) {
   1633    Base::operator++(1);
   1634    settle();
   1635  }
   1636 
   1637  bool isDestructured() const { return !this->name(); }
   1638 };
   1639 
   1640 template <typename NameT>
   1641 class AbstractPositionalFormalParameterIter;
   1642 
   1643 template <>
   1644 class AbstractPositionalFormalParameterIter<JSAtom>
   1645    : public BasePositionalFormalParamterIter<JSAtom> {
   1646  using Base = BasePositionalFormalParamterIter<JSAtom>;
   1647 
   1648 public:
   1649  explicit AbstractPositionalFormalParameterIter(Scope* scope);
   1650  explicit AbstractPositionalFormalParameterIter(JSScript* script);
   1651 
   1652  using Base::Base;
   1653 };
   1654 
   1655 template <>
   1656 class AbstractPositionalFormalParameterIter<frontend::TaggedParserAtomIndex>
   1657    : public BasePositionalFormalParamterIter<frontend::TaggedParserAtomIndex> {
   1658  using Base =
   1659      BasePositionalFormalParamterIter<frontend::TaggedParserAtomIndex>;
   1660 
   1661 public:
   1662  AbstractPositionalFormalParameterIter(
   1663      FunctionScope::AbstractData<frontend::TaggedParserAtomIndex>& data,
   1664      bool hasParameterExprs)
   1665      : Base(data, hasParameterExprs) {
   1666    settle();
   1667  }
   1668 
   1669  using Base::Base;
   1670 };
   1671 
   1672 using PositionalFormalParameterIter =
   1673    AbstractPositionalFormalParameterIter<JSAtom>;
   1674 
   1675 //
   1676 // Iterator for walking the scope chain.
   1677 //
   1678 // It may be placed in GC containers; for example:
   1679 //
   1680 //   for (Rooted<ScopeIter> si(cx, ScopeIter(scope)); si; si++) {
   1681 //     use(si);
   1682 //     SomeMayGCOperation();
   1683 //     use(si);
   1684 //   }
   1685 //
   1686 class MOZ_STACK_CLASS ScopeIter {
   1687  Scope* scope_;
   1688 
   1689 public:
   1690  explicit ScopeIter(Scope* scope) : scope_(scope) {}
   1691 
   1692  explicit ScopeIter(JSScript* script);
   1693 
   1694  explicit ScopeIter(const ScopeIter& si) = default;
   1695 
   1696  bool done() const { return !scope_; }
   1697 
   1698  explicit operator bool() const { return !done(); }
   1699 
   1700  void operator++(int) {
   1701    MOZ_ASSERT(!done());
   1702    scope_ = scope_->enclosing();
   1703  }
   1704 
   1705  Scope* scope() const {
   1706    MOZ_ASSERT(!done());
   1707    return scope_;
   1708  }
   1709 
   1710  ScopeKind kind() const {
   1711    MOZ_ASSERT(!done());
   1712    return scope_->kind();
   1713  }
   1714 
   1715  // Returns the shape of the environment if it is known. It is possible to
   1716  // hasSyntacticEnvironment and to have no known shape, e.g., eval.
   1717  SharedShape* environmentShape() const { return scope()->environmentShape(); }
   1718 
   1719  // Returns whether this scope has a syntactic environment (i.e., an
   1720  // Environment that isn't a non-syntactic With or NonSyntacticVariables)
   1721  // on the environment chain.
   1722  bool hasSyntacticEnvironment() const;
   1723 
   1724  void trace(JSTracer* trc) {
   1725    if (scope_) {
   1726      TraceRoot(trc, &scope_, "scope iter scope");
   1727    }
   1728  }
   1729 };
   1730 
   1731 //
   1732 // Specializations of Rooted containers for the iterators.
   1733 //
   1734 
   1735 template <typename Wrapper>
   1736 class WrappedPtrOperations<BindingIter, Wrapper> {
   1737  const BindingIter& iter() const {
   1738    return static_cast<const Wrapper*>(this)->get();
   1739  }
   1740 
   1741 public:
   1742  bool done() const { return iter().done(); }
   1743  explicit operator bool() const { return !done(); }
   1744  bool isLast() const { return iter().isLast(); }
   1745  bool canHaveArgumentSlots() const { return iter().canHaveArgumentSlots(); }
   1746  bool canHaveFrameSlots() const { return iter().canHaveFrameSlots(); }
   1747  bool canHaveEnvironmentSlots() const {
   1748    return iter().canHaveEnvironmentSlots();
   1749  }
   1750  JSAtom* name() const { return iter().name(); }
   1751  bool closedOver() const { return iter().closedOver(); }
   1752  BindingLocation location() const { return iter().location(); }
   1753  BindingKind kind() const { return iter().kind(); }
   1754  bool isTopLevelFunction() const { return iter().isTopLevelFunction(); }
   1755  bool hasArgumentSlot() const { return iter().hasArgumentSlot(); }
   1756  uint16_t argumentSlot() const { return iter().argumentSlot(); }
   1757  uint32_t nextFrameSlot() const { return iter().nextFrameSlot(); }
   1758  uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); }
   1759 };
   1760 
   1761 template <typename Wrapper>
   1762 class MutableWrappedPtrOperations<BindingIter, Wrapper>
   1763    : public WrappedPtrOperations<BindingIter, Wrapper> {
   1764  BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); }
   1765 
   1766 public:
   1767  void operator++(int) { iter().operator++(1); }
   1768 };
   1769 
   1770 template <typename Wrapper>
   1771 class WrappedPtrOperations<ScopeIter, Wrapper> {
   1772  const ScopeIter& iter() const {
   1773    return static_cast<const Wrapper*>(this)->get();
   1774  }
   1775 
   1776 public:
   1777  bool done() const { return iter().done(); }
   1778  explicit operator bool() const { return !done(); }
   1779  Scope* scope() const { return iter().scope(); }
   1780  ScopeKind kind() const { return iter().kind(); }
   1781  SharedShape* environmentShape() const { return iter().environmentShape(); }
   1782  bool hasSyntacticEnvironment() const {
   1783    return iter().hasSyntacticEnvironment();
   1784  }
   1785 };
   1786 
   1787 template <typename Wrapper>
   1788 class MutableWrappedPtrOperations<ScopeIter, Wrapper>
   1789    : public WrappedPtrOperations<ScopeIter, Wrapper> {
   1790  ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); }
   1791 
   1792 public:
   1793  void operator++(int) { iter().operator++(1); }
   1794 };
   1795 
   1796 SharedShape* CreateEnvironmentShape(JSContext* cx, BindingIter& bi,
   1797                                    const JSClass* cls, uint32_t numSlots,
   1798                                    ObjectFlags objectFlags);
   1799 
   1800 SharedShape* CreateEnvironmentShapeForSyntheticModule(
   1801    JSContext* cx, const JSClass* cls, uint32_t numSlots,
   1802    Handle<ModuleObject*> module);
   1803 
   1804 SharedShape* EmptyEnvironmentShape(JSContext* cx, const JSClass* cls,
   1805                                   uint32_t numSlots, ObjectFlags objectFlags);
   1806 
   1807 static inline size_t GetOffsetOfParserScopeDataTrailingNames(ScopeKind kind) {
   1808  switch (kind) {
   1809    // FunctionScope
   1810    case ScopeKind::Function:
   1811      return GetOffsetOfScopeDataTrailingNames<FunctionScope::ParserData>();
   1812 
   1813    // VarScope
   1814    case ScopeKind::FunctionBodyVar:
   1815      return GetOffsetOfScopeDataTrailingNames<VarScope::ParserData>();
   1816 
   1817    // LexicalScope
   1818    case ScopeKind::Lexical:
   1819    case ScopeKind::SimpleCatch:
   1820    case ScopeKind::Catch:
   1821    case ScopeKind::NamedLambda:
   1822    case ScopeKind::StrictNamedLambda:
   1823    case ScopeKind::FunctionLexical:
   1824      return GetOffsetOfScopeDataTrailingNames<LexicalScope::ParserData>();
   1825 
   1826    // ClassBodyScope
   1827    case ScopeKind::ClassBody:
   1828      return GetOffsetOfScopeDataTrailingNames<ClassBodyScope::ParserData>();
   1829 
   1830    // EvalScope
   1831    case ScopeKind::Eval:
   1832    case ScopeKind::StrictEval:
   1833      return GetOffsetOfScopeDataTrailingNames<EvalScope::ParserData>();
   1834 
   1835    // GlobalScope
   1836    case ScopeKind::Global:
   1837    case ScopeKind::NonSyntactic:
   1838      return GetOffsetOfScopeDataTrailingNames<GlobalScope::ParserData>();
   1839 
   1840    // ModuleScope
   1841    case ScopeKind::Module:
   1842      return GetOffsetOfScopeDataTrailingNames<ModuleScope::ParserData>();
   1843 
   1844    // WasmInstanceScope
   1845    case ScopeKind::WasmInstance:
   1846      return GetOffsetOfScopeDataTrailingNames<WasmInstanceScope::ParserData>();
   1847 
   1848    // WasmFunctionScope
   1849    case ScopeKind::WasmFunction:
   1850      return GetOffsetOfScopeDataTrailingNames<WasmFunctionScope::ParserData>();
   1851 
   1852    // WithScope doesn't have ScopeData.
   1853    case ScopeKind::With:
   1854    default:
   1855      MOZ_CRASH("Unexpected ScopeKind");
   1856  }
   1857 
   1858  return 0;
   1859 }
   1860 
   1861 inline size_t SizeOfParserScopeData(ScopeKind kind, uint32_t length) {
   1862  return GetOffsetOfParserScopeDataTrailingNames(kind) +
   1863         sizeof(AbstractBindingName<frontend::TaggedParserAtomIndex>) * length;
   1864 }
   1865 
   1866 inline mozilla::Span<AbstractBindingName<frontend::TaggedParserAtomIndex>>
   1867 GetParserScopeDataTrailingNames(
   1868    ScopeKind kind,
   1869    AbstractBaseScopeData<frontend::TaggedParserAtomIndex>* data) {
   1870  return mozilla::Span(
   1871      reinterpret_cast<AbstractBindingName<frontend::TaggedParserAtomIndex>*>(
   1872          uintptr_t(data) + GetOffsetOfParserScopeDataTrailingNames(kind)),
   1873      data->length);
   1874 }
   1875 
   1876 }  // namespace js
   1877 
   1878 namespace JS {
   1879 
   1880 template <>
   1881 struct GCPolicy<js::ScopeKind> : public IgnoreGCPolicy<js::ScopeKind> {};
   1882 
   1883 template <typename T>
   1884 using ScopeDataGCPolicy = NonGCPointerPolicy<T>;
   1885 
   1886 #define DEFINE_SCOPE_DATA_GCPOLICY(Data)              \
   1887  template <>                                         \
   1888  struct MapTypeToRootKind<Data*> {                   \
   1889    static const RootKind kind = RootKind::Traceable; \
   1890  };                                                  \
   1891  template <>                                         \
   1892  struct GCPolicy<Data*> : public ScopeDataGCPolicy<Data*> {}
   1893 
   1894 DEFINE_SCOPE_DATA_GCPOLICY(js::LexicalScope::RuntimeData);
   1895 DEFINE_SCOPE_DATA_GCPOLICY(js::ClassBodyScope::RuntimeData);
   1896 DEFINE_SCOPE_DATA_GCPOLICY(js::FunctionScope::RuntimeData);
   1897 DEFINE_SCOPE_DATA_GCPOLICY(js::VarScope::RuntimeData);
   1898 DEFINE_SCOPE_DATA_GCPOLICY(js::GlobalScope::RuntimeData);
   1899 DEFINE_SCOPE_DATA_GCPOLICY(js::EvalScope::RuntimeData);
   1900 DEFINE_SCOPE_DATA_GCPOLICY(js::ModuleScope::RuntimeData);
   1901 DEFINE_SCOPE_DATA_GCPOLICY(js::WasmFunctionScope::RuntimeData);
   1902 DEFINE_SCOPE_DATA_GCPOLICY(js::WasmInstanceScope::RuntimeData);
   1903 
   1904 #undef DEFINE_SCOPE_DATA_GCPOLICY
   1905 
   1906 namespace ubi {
   1907 
   1908 template <>
   1909 class Concrete<js::Scope> : TracerConcrete<js::Scope> {
   1910 protected:
   1911  explicit Concrete(js::Scope* ptr) : TracerConcrete<js::Scope>(ptr) {}
   1912 
   1913 public:
   1914  static void construct(void* storage, js::Scope* ptr) {
   1915    new (storage) Concrete(ptr);
   1916  }
   1917 
   1918  CoarseType coarseType() const final { return CoarseType::Script; }
   1919 
   1920  Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
   1921 
   1922  const char16_t* typeName() const override { return concreteTypeName; }
   1923  static const char16_t concreteTypeName[];
   1924 };
   1925 
   1926 }  // namespace ubi
   1927 }  // namespace JS
   1928 
   1929 #endif  // vm_Scope_h