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