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