Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / frontend / NameAnalysisTypes.h
blobd2f44c170c23f4969fde4c0f0b6dc3b4c1c9ecc8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef frontend_NameAnalysisTypes_h
8 #define frontend_NameAnalysisTypes_h
10 #include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_CRASH
11 #include "mozilla/Casting.h" // mozilla::AssertedCast
13 #include <stdint.h> // uint8_t, uint16_t, uint32_t
15 #include "vm/BindingKind.h" // BindingKind, BindingLocation
16 #include "vm/BytecodeFormatFlags.h" // JOF_ENVCOORD
17 #include "vm/BytecodeUtil.h" // ENVCOORD_HOPS_BITS, ENVCOORD_SLOT_BITS, GET_ENVCOORD_HOPS, GET_ENVCOORD_SLOT, ENVCOORD_HOPS_LEN, JOF_OPTYPE, JSOp, LOCALNO_LIMIT
19 namespace js {
21 // An "environment coordinate" describes how to get from head of the
22 // environment chain to a given lexically-enclosing variable. An environment
23 // coordinate has two dimensions:
24 // - hops: the number of environment objects on the scope chain to skip
25 // - slot: the slot on the environment object holding the variable's value
26 class EnvironmentCoordinate {
27 uint32_t hops_;
28 uint32_t slot_;
30 // Technically, hops_/slot_ are ENVCOORD_(HOPS|SLOT)_BITS wide. Since
31 // EnvironmentCoordinate is a temporary value, don't bother with a bitfield as
32 // this only adds overhead.
33 static_assert(ENVCOORD_HOPS_BITS <= 32, "We have enough bits below");
34 static_assert(ENVCOORD_SLOT_BITS <= 32, "We have enough bits below");
36 public:
37 explicit inline EnvironmentCoordinate(jsbytecode* pc)
38 : hops_(GET_ENVCOORD_HOPS(pc)),
39 slot_(GET_ENVCOORD_SLOT(pc + ENVCOORD_HOPS_LEN)) {
40 MOZ_ASSERT(JOF_OPTYPE(JSOp(*pc)) == JOF_ENVCOORD ||
41 JOF_OPTYPE(JSOp(*pc)) == JOF_DEBUGCOORD);
44 EnvironmentCoordinate() = default;
46 void setHops(uint32_t hops) {
47 MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT);
48 hops_ = hops;
51 void setSlot(uint32_t slot) {
52 MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
53 slot_ = slot;
56 uint32_t hops() const {
57 MOZ_ASSERT(hops_ < ENVCOORD_HOPS_LIMIT);
58 return hops_;
61 uint32_t slot() const {
62 MOZ_ASSERT(slot_ < ENVCOORD_SLOT_LIMIT);
63 return slot_;
66 bool operator==(const EnvironmentCoordinate& rhs) const {
67 return hops() == rhs.hops() && slot() == rhs.slot();
71 namespace frontend {
73 enum class ParseGoal : uint8_t { Script, Module };
75 // A detailed kind used for tracking declarations in the Parser. Used for
76 // specific early error semantics and better error messages.
77 enum class DeclarationKind : uint8_t {
78 PositionalFormalParameter,
79 FormalParameter,
80 CoverArrowParameter,
81 Var,
82 Let,
83 Const,
84 Class, // Handled as same as `let` after parsing.
85 Import,
86 BodyLevelFunction,
87 ModuleBodyLevelFunction,
88 LexicalFunction,
89 SloppyLexicalFunction,
90 VarForAnnexBLexicalFunction,
91 SimpleCatchParameter,
92 CatchParameter,
93 PrivateName,
94 Synthetic,
95 PrivateMethod, // slot to store nonstatic private method
98 // Class field kind.
99 enum class FieldPlacement : uint8_t { Unspecified, Instance, Static };
101 static inline BindingKind DeclarationKindToBindingKind(DeclarationKind kind) {
102 switch (kind) {
103 case DeclarationKind::PositionalFormalParameter:
104 case DeclarationKind::FormalParameter:
105 case DeclarationKind::CoverArrowParameter:
106 return BindingKind::FormalParameter;
108 case DeclarationKind::Var:
109 case DeclarationKind::BodyLevelFunction:
110 case DeclarationKind::ModuleBodyLevelFunction:
111 case DeclarationKind::VarForAnnexBLexicalFunction:
112 return BindingKind::Var;
114 case DeclarationKind::Let:
115 case DeclarationKind::Class:
116 case DeclarationKind::LexicalFunction:
117 case DeclarationKind::SloppyLexicalFunction:
118 case DeclarationKind::SimpleCatchParameter:
119 case DeclarationKind::CatchParameter:
120 return BindingKind::Let;
122 case DeclarationKind::Const:
123 return BindingKind::Const;
125 case DeclarationKind::Import:
126 return BindingKind::Import;
128 case DeclarationKind::Synthetic:
129 case DeclarationKind::PrivateName:
130 return BindingKind::Synthetic;
132 case DeclarationKind::PrivateMethod:
133 return BindingKind::PrivateMethod;
136 MOZ_CRASH("Bad DeclarationKind");
139 static inline bool DeclarationKindIsLexical(DeclarationKind kind) {
140 return BindingKindIsLexical(DeclarationKindToBindingKind(kind));
143 // Used in Parser and BytecodeEmitter to track the kind of a private name.
144 enum class PrivateNameKind : uint8_t {
145 None,
146 Field,
147 Method,
148 Getter,
149 Setter,
150 GetterSetter,
153 enum class ClosedOver : bool { No = false, Yes = true };
155 // Used in Parser to track declared names.
156 class DeclaredNameInfo {
157 uint32_t pos_;
158 DeclarationKind kind_;
160 // If the declared name is a binding, whether the binding is closed
161 // over. Its value is meaningless if the declared name is not a binding
162 // (i.e., a 'var' declared name in a non-var scope).
163 bool closedOver_;
165 PrivateNameKind privateNameKind_;
167 // Only updated for private names (see noteDeclaredPrivateName),
168 // tracks if declaration was instance or static to allow issuing
169 // early errors in the case where we mismatch instance and static
170 // private getter/setters.
171 FieldPlacement placement_;
173 public:
174 explicit DeclaredNameInfo(DeclarationKind kind, uint32_t pos,
175 ClosedOver closedOver = ClosedOver::No)
176 : pos_(pos),
177 kind_(kind),
178 closedOver_(bool(closedOver)),
179 privateNameKind_(PrivateNameKind::None),
180 placement_(FieldPlacement::Unspecified) {}
182 // Needed for InlineMap.
183 DeclaredNameInfo() = default;
185 DeclarationKind kind() const { return kind_; }
187 static const uint32_t npos = uint32_t(-1);
189 uint32_t pos() const { return pos_; }
191 void alterKind(DeclarationKind kind) { kind_ = kind; }
193 void setClosedOver() { closedOver_ = true; }
195 bool closedOver() const { return closedOver_; }
197 void setPrivateNameKind(PrivateNameKind privateNameKind) {
198 privateNameKind_ = privateNameKind;
201 void setFieldPlacement(FieldPlacement placement) {
202 MOZ_ASSERT(placement != FieldPlacement::Unspecified);
203 placement_ = placement;
206 PrivateNameKind privateNameKind() const { return privateNameKind_; }
208 FieldPlacement placement() const { return placement_; }
211 // Used in BytecodeEmitter to map names to locations.
212 class NameLocation {
213 public:
214 enum class Kind : uint8_t {
215 // Cannot statically determine where the name lives. Needs to walk the
216 // environment chain to search for the name.
217 Dynamic,
219 // The name lives on the global or is a global lexical binding. Search
220 // for the name on the global scope.
221 Global,
223 // Special mode used only when emitting self-hosted scripts. See
224 // BytecodeEmitter::lookupName.
225 Intrinsic,
227 // In a named lambda, the name is the callee itself.
228 NamedLambdaCallee,
230 // The name is a positional formal parameter name and can be retrieved
231 // directly from the stack using slot_.
232 ArgumentSlot,
234 // The name is not closed over and lives on the frame in slot_.
235 FrameSlot,
237 // The name is closed over and lives on an environment hops_ away in slot_.
238 EnvironmentCoordinate,
240 // The name is closed over and lives on an environment hops_ away in slot_,
241 // where one or more of the environments may be a DebugEnvironmentProxy
242 DebugEnvironmentCoordinate,
244 // An imported name in a module.
245 Import,
247 // Cannot statically determine where the synthesized var for Annex
248 // B.3.3 lives.
249 DynamicAnnexBVar
252 private:
253 // Where the name lives.
254 Kind kind_;
256 // If the name is not Dynamic or DynamicAnnexBVar, the kind of the
257 // binding.
258 BindingKind bindingKind_;
260 // If the name is closed over and accessed via EnvironmentCoordinate, the
261 // number of dynamic environments to skip.
263 // Otherwise UINT8_MAX.
264 uint8_t hops_;
266 // If the name lives on the frame, the slot frame.
268 // If the name is closed over and accessed via EnvironmentCoordinate, the
269 // slot on the environment.
271 // Otherwise 0.
272 uint32_t slot_ : ENVCOORD_SLOT_BITS;
274 static_assert(LOCALNO_BITS == ENVCOORD_SLOT_BITS,
275 "Frame and environment slots must be same sized.");
277 NameLocation(Kind kind, BindingKind bindingKind, uint8_t hops = UINT8_MAX,
278 uint32_t slot = 0)
279 : kind_(kind), bindingKind_(bindingKind), hops_(hops), slot_(slot) {}
281 public:
282 // Default constructor for InlineMap.
283 NameLocation() = default;
285 static NameLocation Dynamic() {
286 return NameLocation(Kind::Dynamic, BindingKind::Import);
289 static NameLocation Global(BindingKind bindKind) {
290 MOZ_ASSERT(bindKind != BindingKind::FormalParameter);
291 return NameLocation(Kind::Global, bindKind);
294 static NameLocation Intrinsic() {
295 return NameLocation(Kind::Intrinsic, BindingKind::Var);
298 static NameLocation NamedLambdaCallee() {
299 return NameLocation(Kind::NamedLambdaCallee,
300 BindingKind::NamedLambdaCallee);
303 static NameLocation ArgumentSlot(uint16_t slot) {
304 return NameLocation(Kind::ArgumentSlot, BindingKind::FormalParameter, 0,
305 slot);
308 static NameLocation FrameSlot(BindingKind bindKind, uint32_t slot) {
309 MOZ_ASSERT(slot < LOCALNO_LIMIT);
310 return NameLocation(Kind::FrameSlot, bindKind, 0, slot);
313 static NameLocation EnvironmentCoordinate(BindingKind bindKind, uint8_t hops,
314 uint32_t slot) {
315 MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
316 return NameLocation(Kind::EnvironmentCoordinate, bindKind, hops, slot);
318 static NameLocation DebugEnvironmentCoordinate(BindingKind bindKind,
319 uint8_t hops, uint32_t slot) {
320 MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
321 return NameLocation(Kind::DebugEnvironmentCoordinate, bindKind, hops, slot);
324 static NameLocation Import() {
325 return NameLocation(Kind::Import, BindingKind::Import);
328 static NameLocation DynamicAnnexBVar() {
329 return NameLocation(Kind::DynamicAnnexBVar, BindingKind::Var);
332 bool operator==(const NameLocation& other) const {
333 return kind_ == other.kind_ && bindingKind_ == other.bindingKind_ &&
334 hops_ == other.hops_ && slot_ == other.slot_;
337 bool operator!=(const NameLocation& other) const { return !(*this == other); }
339 Kind kind() const { return kind_; }
341 uint16_t argumentSlot() const {
342 MOZ_ASSERT(kind_ == Kind::ArgumentSlot);
343 return mozilla::AssertedCast<uint16_t>(slot_);
346 uint32_t frameSlot() const {
347 MOZ_ASSERT(kind_ == Kind::FrameSlot);
348 return slot_;
351 NameLocation addHops(uint8_t more) {
352 MOZ_ASSERT(hops_ < ENVCOORD_HOPS_LIMIT - more);
353 MOZ_ASSERT(kind_ == Kind::EnvironmentCoordinate);
354 return NameLocation(kind_, bindingKind_, hops_ + more, slot_);
357 class EnvironmentCoordinate environmentCoordinate() const {
358 MOZ_ASSERT(kind_ == Kind::EnvironmentCoordinate ||
359 kind_ == Kind::DebugEnvironmentCoordinate);
360 class EnvironmentCoordinate coord;
361 coord.setHops(hops_);
362 coord.setSlot(slot_);
363 return coord;
366 BindingKind bindingKind() const {
367 MOZ_ASSERT(kind_ != Kind::Dynamic);
368 return bindingKind_;
371 bool isLexical() const { return BindingKindIsLexical(bindingKind()); }
373 bool isConst() const { return bindingKind() == BindingKind::Const; }
375 bool isSynthetic() const { return bindingKind() == BindingKind::Synthetic; }
377 bool isPrivateMethod() const {
378 return bindingKind() == BindingKind::PrivateMethod;
381 bool hasKnownSlot() const {
382 return kind_ == Kind::ArgumentSlot || kind_ == Kind::FrameSlot ||
383 kind_ == Kind::EnvironmentCoordinate;
387 } // namespace frontend
388 } // namespace js
390 #endif // frontend_NameAnalysisTypes_h