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