Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / frontend / ObjectEmitter.h
blob7d3f749f47f5d0c47c9085eb2a74423cd85f0229
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_ObjectEmitter_h
8 #define frontend_ObjectEmitter_h
10 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS, MOZ_ALWAYS_INLINE, MOZ_RAII
11 #include "mozilla/Maybe.h" // Maybe
13 #include <stddef.h> // size_t
14 #include <stdint.h> // uint32_t
16 #include "frontend/EmitterScope.h" // EmitterScope
17 #include "frontend/NameOpEmitter.h" // NameOpEmitter
18 #include "frontend/ParseNode.h" // AccessorType
19 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
20 #include "frontend/TDZCheckCache.h" // TDZCheckCache
21 #include "vm/Opcodes.h" // JSOp
22 #include "vm/Scope.h" // LexicalScope
24 namespace js {
26 namespace frontend {
28 struct BytecodeEmitter;
29 class SharedContext;
31 // Class for emitting bytecode for object and class properties.
32 // See ObjectEmitter and ClassEmitter for usage.
33 class MOZ_STACK_CLASS PropertyEmitter {
34 public:
35 enum class Kind {
36 // Prototype property.
37 Prototype,
39 // Class static property.
40 Static
43 protected:
44 BytecodeEmitter* bce_;
46 // True if the object is class.
47 // Set by ClassEmitter.
48 bool isClass_ = false;
50 // True if the property is class static method.
51 bool isStatic_ = false;
53 // True if the property has computed or index key.
54 bool isIndexOrComputed_ = false;
56 #ifdef DEBUG
57 // The state of this emitter.
59 // +-------+
60 // | Start |-+
61 // +-------+ |
62 // |
63 // +---------+
64 // |
65 // | +------------------------------------------------------------+
66 // | | |
67 // | | [normal property/method/accessor] |
68 // | v prepareForPropValue +-----------+ +------+ |
69 // +->+----------------------->| PropValue |-+ +->| Init |-+
70 // | +-----------+ | | +------+
71 // | | |
72 // | +-----------------------------------+ +-----------+
73 // | | |
74 // | +-+---------------------------------------+ |
75 // | | | |
76 // | | [method with super] | |
77 // | | emitInitHomeObject +-------------+ v |
78 // | +--------------------->| InitHomeObj |->+ |
79 // | +-------------+ | |
80 // | | |
81 // | +-------------------------------------- + |
82 // | | |
83 // | | emitInit |
84 // | +------------------------------------------------------>+
85 // | ^
86 // | [optimized private non-static method] |
87 // | prepareForPrivateMethod +--------------------+ |
88 // +---------------------------->| PrivateMethodValue |-+ |
89 // | +--------------------+ | |
90 // | | |
91 // | +-------------------------------------------------+ |
92 // | | |
93 // | +-+---------------------------------------------+ |
94 // | | | |
95 // | | [method with super | |
96 // | | emitInitHomeObject +-----------------+ v |
97 // | +--------------------->| InitHomeObjFor- |----+ |
98 // | | PrivateMethod | | |
99 // | +-----------------+ | |
100 // | | |
101 // | +---------------------------------------------+ |
102 // | | |
103 // | | skipInit |
104 // | +------------------------------------------------------>+
105 // | ^
106 // | [private static method] |
107 // | prepareForPrivateStaticMethod +---------------------+ |
108 // +--------------------------------->| PrivateStaticMethod |-+ |
109 // | +---------------------+ | |
110 // | | |
111 // | +-------------------------------------------------------+ |
112 // | | |
113 // | +-+-------------------------------------------------+ |
114 // | | | |
115 // | | [method with super | |
116 // | | emitInitHomeObject +---------------------+ v |
117 // | +--------------------->| InitHomeObjFor- |----+ |
118 // | | PrivateStaticMethod | | |
119 // | +---------------------+ | |
120 // | | |
121 // | +-----------------------------------------------+ |
122 // | | |
123 // | | emitPrivateStaticMethod |
124 // | +---------------------------------------------------->+
125 // | ^
126 // | [index property/method/accessor] |
127 // | prepareForIndexPropKey +----------+ |
128 // +-------------------------->| IndexKey |-+ |
129 // | +----------+ | |
130 // | | |
131 // | +-------------------------------------+ |
132 // | | |
133 // | | prepareForIndexPropValue +------------+ |
134 // | +------------------------->| IndexValue |-+ |
135 // | +------------+ | |
136 // | | |
137 // | +---------------------------------------+ |
138 // | | |
139 // | +-+--------------------------------------------------+ |
140 // | | | |
141 // | | [method with super] | |
142 // | | emitInitHomeObject +---------------------+ v |
143 // | +--------------------->| InitHomeObjForIndex |---->+ |
144 // | +---------------------+ | |
145 // | | |
146 // | +--------------------------------------------------+ |
147 // | | |
148 // | | emitInitIndexOrComputed |
149 // | +---------------------------------------------------->+
150 // | ^
151 // | [computed property/method/accessor] |
152 // | prepareForComputedPropKey +-------------+ |
153 // +----------------------------->| ComputedKey |-+ |
154 // | +-------------+ | |
155 // | | |
156 // | +-------------------------------------------+ |
157 // | | |
158 // | | prepareForComputedPropValue +---------------+ |
159 // | +---------------------------->| ComputedValue |-+ |
160 // | +---------------+ | |
161 // | | |
162 // | +---------------------------------------------+ |
163 // | | |
164 // | +-+--------------------------------------------------+ |
165 // | | | |
166 // | | [method with super] | |
167 // | | emitInitHomeObject +------------------------+ v |
168 // | +--------------------->| InitHomeObjForComputed |->+ |
169 // | +------------------------+ | |
170 // | | |
171 // | +--------------------------------------------------+ |
172 // | | |
173 // | | emitInitIndexOrComputed |
174 // | +---------------------------------------------------->+
175 // | ^
176 // | |
177 // | [__proto__] |
178 // | prepareForProtoValue +------------+ emitMutateProto |
179 // +------------------------>| ProtoValue |-------------------->+
180 // | +------------+ ^
181 // | |
182 // | [...prop] |
183 // | prepareForSpreadOperand +---------------+ emitSpread |
184 // +-------------------------->| SpreadOperand |----------------+
185 // +---------------+
186 enum class PropertyState {
187 // The initial state.
188 Start,
190 // After calling prepareForPropValue.
191 PropValue,
193 // After calling emitInitHomeObject, from PropValue.
194 InitHomeObj,
196 // After calling prepareForPrivateMethod.
197 PrivateMethodValue,
199 // After calling emitInitHomeObject, from PrivateMethod.
200 InitHomeObjForPrivateMethod,
202 // After calling prepareForPrivateStaticMethod.
203 PrivateStaticMethod,
205 // After calling emitInitHomeObject, from PrivateStaticMethod.
206 InitHomeObjForPrivateStaticMethod,
208 // After calling prepareForIndexPropKey.
209 IndexKey,
211 // prepareForIndexPropValue.
212 IndexValue,
214 // After calling emitInitHomeObject, from IndexValue.
215 InitHomeObjForIndex,
217 // After calling prepareForComputedPropKey.
218 ComputedKey,
220 // prepareForComputedPropValue.
221 ComputedValue,
223 // After calling emitInitHomeObject, from ComputedValue.
224 InitHomeObjForComputed,
226 // After calling prepareForProtoValue.
227 ProtoValue,
229 // After calling prepareForSpreadOperand.
230 SpreadOperand,
232 // After calling one of emitInit, emitInitIndexOrComputed, emitMutateProto,
233 // or emitSpread.
234 Init,
236 PropertyState propertyState_ = PropertyState::Start;
237 #endif
239 public:
240 explicit PropertyEmitter(BytecodeEmitter* bce);
242 // Parameters are the offset in the source code for each character below:
244 // { __proto__: protoValue }
245 // ^
246 // |
247 // keyPos
248 [[nodiscard]] bool prepareForProtoValue(uint32_t keyPos);
249 [[nodiscard]] bool emitMutateProto();
251 // { ...obj }
252 // ^
253 // |
254 // spreadPos
255 [[nodiscard]] bool prepareForSpreadOperand(uint32_t spreadPos);
256 [[nodiscard]] bool emitSpread();
258 // { key: value }
259 // ^
260 // |
261 // keyPos
262 [[nodiscard]] bool prepareForPropValue(uint32_t keyPos, Kind kind);
264 [[nodiscard]] bool prepareForPrivateMethod();
266 [[nodiscard]] bool prepareForPrivateStaticMethod(uint32_t keyPos);
268 // { 1: value }
269 // ^
270 // |
271 // keyPos
272 [[nodiscard]] bool prepareForIndexPropKey(uint32_t keyPos, Kind kind);
273 [[nodiscard]] bool prepareForIndexPropValue();
275 // { [ key ]: value }
276 // ^
277 // |
278 // keyPos
279 [[nodiscard]] bool prepareForComputedPropKey(uint32_t keyPos, Kind kind);
280 [[nodiscard]] bool prepareForComputedPropValue();
282 [[nodiscard]] bool emitInitHomeObject();
284 // @param key
285 // Property key
286 [[nodiscard]] bool emitInit(AccessorType accessorType,
287 TaggedParserAtomIndex key);
289 [[nodiscard]] bool emitInitIndexOrComputed(AccessorType accessorType);
291 [[nodiscard]] bool emitPrivateStaticMethod(AccessorType accessorType);
293 [[nodiscard]] bool skipInit();
295 private:
296 [[nodiscard]] MOZ_ALWAYS_INLINE bool prepareForProp(uint32_t keyPos,
297 bool isStatic,
298 bool isComputed);
300 // @param op
301 // Opcode for initializing property
302 // @param key
303 // Atom of the property if the property key is not computed
304 [[nodiscard]] bool emitInit(JSOp op, TaggedParserAtomIndex key);
305 [[nodiscard]] bool emitInitIndexOrComputed(JSOp op);
307 [[nodiscard]] bool emitPopClassConstructor();
310 // Class for emitting bytecode for object literal.
312 // Usage: (check for the return value is omitted for simplicity)
314 // `{}`
315 // ObjectEmitter oe(this);
316 // oe.emitObject(0);
317 // oe.emitEnd();
319 // `{ prop: 10 }`
320 // ObjectEmitter oe(this);
321 // oe.emitObject(1);
323 // oe.prepareForPropValue(offset_of_prop);
324 // emit(10);
325 // oe.emitInitProp(atom_of_prop);
327 // oe.emitEnd();
329 // `{ prop: function() {} }`, when property value is anonymous function
330 // ObjectEmitter oe(this);
331 // oe.emitObject(1);
333 // oe.prepareForPropValue(offset_of_prop);
334 // emit(function);
335 // oe.emitInitProp(atom_of_prop);
337 // oe.emitEnd();
339 // `{ get prop() { ... }, set prop(v) { ... } }`
340 // ObjectEmitter oe(this);
341 // oe.emitObject(2);
343 // oe.prepareForPropValue(offset_of_prop);
344 // emit(function_for_getter);
345 // oe.emitInitGetter(atom_of_prop);
347 // oe.prepareForPropValue(offset_of_prop);
348 // emit(function_for_setter);
349 // oe.emitInitSetter(atom_of_prop);
351 // oe.emitEnd();
353 // `{ 1: 10, get 2() { ... }, set 3(v) { ... } }`
354 // ObjectEmitter oe(this);
355 // oe.emitObject(3);
357 // oe.prepareForIndexPropKey(offset_of_prop);
358 // emit(1);
359 // oe.prepareForIndexPropValue();
360 // emit(10);
361 // oe.emitInitIndexedProp();
363 // oe.prepareForIndexPropKey(offset_of_opening_bracket);
364 // emit(2);
365 // oe.prepareForIndexPropValue();
366 // emit(function_for_getter);
367 // oe.emitInitIndexGetter();
369 // oe.prepareForIndexPropKey(offset_of_opening_bracket);
370 // emit(3);
371 // oe.prepareForIndexPropValue();
372 // emit(function_for_setter);
373 // oe.emitInitIndexSetter();
375 // oe.emitEnd();
377 // `{ [prop1]: 10, get [prop2]() { ... }, set [prop3](v) { ... } }`
378 // ObjectEmitter oe(this);
379 // oe.emitObject(3);
381 // oe.prepareForComputedPropKey(offset_of_opening_bracket);
382 // emit(prop1);
383 // oe.prepareForComputedPropValue();
384 // emit(10);
385 // oe.emitInitComputedProp();
387 // oe.prepareForComputedPropKey(offset_of_opening_bracket);
388 // emit(prop2);
389 // oe.prepareForComputedPropValue();
390 // emit(function_for_getter);
391 // oe.emitInitComputedGetter();
393 // oe.prepareForComputedPropKey(offset_of_opening_bracket);
394 // emit(prop3);
395 // oe.prepareForComputedPropValue();
396 // emit(function_for_setter);
397 // oe.emitInitComputedSetter();
399 // oe.emitEnd();
401 // `{ __proto__: obj }`
402 // ObjectEmitter oe(this);
403 // oe.emitObject(1);
404 // oe.prepareForProtoValue(offset_of___proto__);
405 // emit(obj);
406 // oe.emitMutateProto();
407 // oe.emitEnd();
409 // `{ ...obj }`
410 // ObjectEmitter oe(this);
411 // oe.emitObject(1);
412 // oe.prepareForSpreadOperand(offset_of_triple_dots);
413 // emit(obj);
414 // oe.emitSpread();
415 // oe.emitEnd();
417 class MOZ_STACK_CLASS ObjectEmitter : public PropertyEmitter {
418 private:
419 #ifdef DEBUG
420 // The state of this emitter.
422 // +-------+ emitObject +--------+
423 // | Start |----------->| Object |-+
424 // +-------+ +--------+ |
425 // |
426 // +-----------------------------+
427 // |
428 // | (do PropertyEmitter operation) emitEnd +-----+
429 // +-------------------------------+--------->| End |
430 // +-----+
431 enum class ObjectState {
432 // The initial state.
433 Start,
435 // After calling emitObject.
436 Object,
438 // After calling emitEnd.
439 End,
441 ObjectState objectState_ = ObjectState::Start;
442 #endif
444 public:
445 explicit ObjectEmitter(BytecodeEmitter* bce);
447 [[nodiscard]] bool emitObject(size_t propertyCount);
448 // Same as `emitObject()`, but start with an empty template object already on
449 // the stack.
450 [[nodiscard]] bool emitObjectWithTemplateOnStack();
451 [[nodiscard]] bool emitEnd();
454 // Save and restore the strictness.
455 // Used by class declaration/expression to temporarily enable strict mode.
456 class MOZ_RAII AutoSaveLocalStrictMode {
457 SharedContext* sc_;
458 bool savedStrictness_;
460 public:
461 explicit AutoSaveLocalStrictMode(SharedContext* sc);
462 ~AutoSaveLocalStrictMode();
464 // Force restore the strictness now.
465 void restore();
468 // Class for emitting bytecode for JS class.
470 // Usage: (check for the return value is omitted for simplicity)
472 // `class { constructor() { ... } }`
473 // ClassEmitter ce(this);
474 // ce.emitScope(scopeBindings);
475 // ce.emitClass(nullptr, nullptr, false);
477 // emit(function_for_constructor);
478 // ce.emitInitConstructor(/* needsHomeObject = */ false);
480 // ce.emitEnd(ClassEmitter::Kind::Expression);
482 // `class X { constructor() { ... } }`
483 // ClassEmitter ce(this);
484 // ce.emitScope(scopeBindings);
485 // ce.emitClass(atom_of_X, nullptr, false);
487 // emit(function_for_constructor);
488 // ce.emitInitConstructor(/* needsHomeObject = */ false);
490 // ce.emitEnd(ClassEmitter::Kind::Expression);
492 // `class X extends Y { constructor() { ... } }`
493 // ClassEmitter ce(this);
494 // ce.emitScope(scopeBindings);
496 // emit(Y);
497 // ce.emitDerivedClass(atom_of_X, nullptr, false);
499 // emit(function_for_constructor);
500 // ce.emitInitConstructor(/* needsHomeObject = */ false);
502 // ce.emitEnd(ClassEmitter::Kind::Expression);
504 // `class X extends Y { constructor() { ... super.f(); ... } }`
505 // ClassEmitter ce(this);
506 // ce.emitScope(scopeBindings);
508 // emit(Y);
509 // ce.emitDerivedClass(atom_of_X, nullptr, false);
511 // emit(function_for_constructor);
512 // // pass true if constructor contains super.prop access
513 // ce.emitInitConstructor(/* needsHomeObject = */ true);
515 // ce.emitEnd(ClassEmitter::Kind::Expression);
517 // `class X extends Y { field0 = expr0; ... }`
518 // ClassEmitter ce(this);
519 // ce.emitScope(scopeBindings);
520 // emit(Y);
521 // ce.emitDerivedClass(atom_of_X, nullptr, false);
523 // ce.prepareForMemberInitializers(fields.length());
524 // for (auto field : fields) {
525 // emit(field.initializer_method());
526 // ce.emitStoreMemberInitializer();
527 // }
528 // ce.emitMemberInitializersEnd();
530 // emit(function_for_constructor);
531 // ce.emitInitConstructor(/* needsHomeObject = */ false);
532 // ce.emitEnd(ClassEmitter::Kind::Expression);
534 // `class X { field0 = super.method(); ... }`
535 // // after emitClass/emitDerivedClass
536 // ce.prepareForMemberInitializers(1);
537 // for (auto field : fields) {
538 // emit(field.initializer_method());
539 // if (field.initializer_contains_super_or_eval()) {
540 // ce.emitMemberInitializerHomeObject();
541 // }
542 // ce.emitStoreMemberInitializer();
543 // }
544 // ce.emitMemberInitializersEnd();
546 // `m() {}` in class
547 // // after emitInitConstructor
548 // ce.prepareForPropValue(offset_of_m);
549 // emit(function_for_m);
550 // ce.emitInitProp(atom_of_m);
552 // `m() { super.f(); }` in class
553 // // after emitInitConstructor
554 // ce.prepareForPropValue(offset_of_m);
555 // emit(function_for_m);
556 // ce.emitInitHomeObject();
557 // ce.emitInitProp(atom_of_m);
559 // `async m() { super.f(); }` in class
560 // // after emitInitConstructor
561 // ce.prepareForPropValue(offset_of_m);
562 // emit(function_for_m);
563 // ce.emitInitHomeObject();
564 // ce.emitInitProp(atom_of_m);
566 // `get p() { super.f(); }` in class
567 // // after emitInitConstructor
568 // ce.prepareForPropValue(offset_of_p);
569 // emit(function_for_p);
570 // ce.emitInitHomeObject();
571 // ce.emitInitGetter(atom_of_m);
573 // `static m() {}` in class
574 // // after emitInitConstructor
575 // ce.prepareForPropValue(offset_of_m,
576 // PropertyEmitter::Kind::Static);
577 // emit(function_for_m);
578 // ce.emitInitProp(atom_of_m);
580 // `static get [p]() { super.f(); }` in class
581 // // after emitInitConstructor
582 // ce.prepareForComputedPropValue(offset_of_m,
583 // PropertyEmitter::Kind::Static);
584 // emit(p);
585 // ce.prepareForComputedPropValue();
586 // emit(function_for_m);
587 // ce.emitInitHomeObject();
588 // ce.emitInitComputedGetter();
590 class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter {
591 public:
592 enum class Kind {
593 // Class expression.
594 Expression,
596 // Class declaration.
597 Declaration,
600 private:
601 // Pseudocode for class declarations:
603 // class extends BaseExpression {
604 // constructor() { ... }
605 // ...
606 // }
609 // if defined <BaseExpression> {
610 // let heritage = BaseExpression;
612 // if (heritage !== null) {
613 // funProto = heritage;
614 // objProto = heritage.prototype;
615 // } else {
616 // funProto = %FunctionPrototype%;
617 // objProto = null;
618 // }
619 // } else {
620 // objProto = %ObjectPrototype%;
621 // }
623 // let homeObject = ObjectCreate(objProto);
625 // if defined <constructor> {
626 // if defined <BaseExpression> {
627 // cons = DefineMethod(<constructor>, proto=homeObject,
628 // funProto=funProto);
629 // } else {
630 // cons = DefineMethod(<constructor>, proto=homeObject);
631 // }
632 // } else {
633 // if defined <BaseExpression> {
634 // cons = DefaultDerivedConstructor(proto=homeObject,
635 // funProto=funProto);
636 // } else {
637 // cons = DefaultConstructor(proto=homeObject);
638 // }
639 // }
641 // cons.prototype = homeObject;
642 // homeObject.constructor = cons;
644 // EmitPropertyList(...)
646 bool isDerived_ = false;
648 mozilla::Maybe<TDZCheckCache> tdzCache_;
649 mozilla::Maybe<EmitterScope> innerScope_;
650 mozilla::Maybe<TDZCheckCache> bodyTdzCache_;
651 mozilla::Maybe<EmitterScope> bodyScope_;
652 AutoSaveLocalStrictMode strictMode_;
654 #ifdef DEBUG
655 // The state of this emitter.
657 // clang-format off
658 // +-------+
659 // | Start |-+------------------------>+--+------------------------------>+--+
660 // +-------+ | ^ | ^ |
661 // | [has scope] | | [has body scope] | |
662 // | emitScope +-------+ | | emitBodyScope +-----------+ | |
663 // +-------------->| Scope |-+ +---------------->| BodyScope |-+ |
664 // +-------+ +-----------+ |
665 // |
666 // +-----------------------------------------------------------------------+
667 // |
668 // | emitClass +-------+
669 // +-+----------------->+->| Class |-+
670 // | ^ +-------+ |
671 // | emitDerivedClass | |
672 // +------------------+ |
673 // |
674 // +-------------------------------+
675 // |
676 // |
677 // | prepareForMemberInitializers(isStatic = false)
678 // +---------------+
679 // | |
680 // | +--------v-------------------+
681 // | | InstanceMemberInitializers |
682 // | +----------------------------+
683 // | |
684 // | emitMemberInitializersEnd
685 // | |
686 // | +--------v----------------------+
687 // | | InstanceMemberInitializersEnd |
688 // | +-------------------------------+
689 // | |
690 // +<--------------+
691 // |
692 // | emitInitConstructor +-----------------+
693 // +-------------------------------->| InitConstructor |-+
694 // +-----------------+ |
695 // |
696 // |
697 // |
698 // +-----------------------------------------------------+
699 // |
700 // | prepareForMemberInitializers(isStatic = true)
701 // +---------------+
702 // | |
703 // | +--------v-----------------+
704 // | | StaticMemberInitializers |
705 // | +--------------------------+
706 // | |
707 // | | emitMemberInitializersEnd
708 // | |
709 // | +--------v--------------------+
710 // | | StaticMemberInitializersEnd |
711 // | +-----------------------------+
712 // | |
713 // +<--------------+
714 // |
715 // | (do PropertyEmitter operation)
716 // +--------------------------------+
717 // |
718 // +-------------+ emitBinding |
719 // | BoundName |<-----------------+
720 // +--+----------+
721 // |
722 // | emitEnd
723 // |
724 // +--v----+
725 // | End |
726 // +-------+
728 // clang-format on
729 enum class ClassState {
730 // The initial state.
731 Start,
733 // After calling emitScope.
734 Scope,
736 // After calling emitBodyScope.
737 BodyScope,
739 // After calling emitClass or emitDerivedClass.
740 Class,
742 // After calling emitInitConstructor.
743 InitConstructor,
745 // After calling prepareForMemberInitializers(isStatic = false).
746 InstanceMemberInitializers,
748 // After calling emitMemberInitializersEnd.
749 InstanceMemberInitializersEnd,
751 // After calling prepareForMemberInitializers(isStatic = true).
752 StaticMemberInitializers,
754 // After calling emitMemberInitializersEnd.
755 StaticMemberInitializersEnd,
757 // After calling emitBinding.
758 BoundName,
760 // After calling emitEnd.
761 End,
763 ClassState classState_ = ClassState::Start;
765 // The state of the members emitter.
767 // clang-format off
769 // +-------+
770 // | Start +<-----------------------------+
771 // +-------+ |
772 // | |
773 // | prepareForMemberInitializer | emitStoreMemberInitializer
774 // v |
775 // +-------------+ |
776 // | Initializer +------------------------->+
777 // +-------------+ |
778 // | |
779 // | emitMemberInitializerHomeObject |
780 // v |
781 // +---------------------------+ |
782 // | InitializerWithHomeObject +------------+
783 // +---------------------------+
785 // clang-format on
786 enum class MemberState {
787 // After calling prepareForMemberInitializers
788 // and 0 or more calls to emitStoreMemberInitializer.
789 Start,
791 // After calling prepareForMemberInitializer
792 Initializer,
794 // After calling emitMemberInitializerHomeObject
795 InitializerWithHomeObject,
797 MemberState memberState_ = MemberState::Start;
799 size_t numInitializers_ = 0;
800 #endif
802 TaggedParserAtomIndex name_;
803 TaggedParserAtomIndex nameForAnonymousClass_;
804 bool hasNameOnStack_ = false;
805 mozilla::Maybe<NameOpEmitter> initializersAssignment_;
806 size_t initializerIndex_ = 0;
808 public:
809 explicit ClassEmitter(BytecodeEmitter* bce);
811 bool emitScope(LexicalScope::ParserData* scopeBindings);
812 bool emitBodyScope(ClassBodyScope::ParserData* scopeBindings);
814 // @param name
815 // Name of the class (nullptr if this is anonymous class)
816 // @param nameForAnonymousClass
817 // Statically inferred name of the class (only for anonymous classes)
818 // @param hasNameOnStack
819 // If true the name is on the stack (only for anonymous classes)
820 [[nodiscard]] bool emitClass(TaggedParserAtomIndex name,
821 TaggedParserAtomIndex nameForAnonymousClass,
822 bool hasNameOnStack);
823 [[nodiscard]] bool emitDerivedClass(
824 TaggedParserAtomIndex name, TaggedParserAtomIndex nameForAnonymousClass,
825 bool hasNameOnStack);
827 // @param needsHomeObject
828 // True if the constructor contains `super.foo`
829 [[nodiscard]] bool emitInitConstructor(bool needsHomeObject);
831 [[nodiscard]] bool prepareForMemberInitializers(size_t numInitializers,
832 bool isStatic);
833 [[nodiscard]] bool prepareForMemberInitializer();
834 [[nodiscard]] bool emitMemberInitializerHomeObject(bool isStatic);
835 [[nodiscard]] bool emitStoreMemberInitializer();
836 [[nodiscard]] bool emitMemberInitializersEnd();
838 [[nodiscard]] bool emitBinding();
840 #ifdef ENABLE_DECORATORS
841 // TODO!: When we've enabled decorators, update the states and transition
842 // diagram to reflect this new state.
843 [[nodiscard]] bool prepareForDecorators();
844 #endif
846 [[nodiscard]] bool emitEnd(Kind kind);
848 private:
849 [[nodiscard]] bool initProtoAndCtor();
851 [[nodiscard]] bool leaveBodyAndInnerScope();
854 } /* namespace frontend */
855 } /* namespace js */
857 #endif /* frontend_ObjectEmitter_h */