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_PropOpEmitter_h
8 #define frontend_PropOpEmitter_h
10 #include "mozilla/Attributes.h"
14 #include "vm/SharedStencil.h" // GCThingIndex
19 struct BytecodeEmitter
;
20 class TaggedParserAtomIndex
;
21 enum class ValueUsage
;
23 // Class for emitting bytecode for property operation.
25 // Usage: (check for the return value is omitted for simplicity)
28 // PropOpEmitter poe(this,
29 // PropOpEmitter::Kind::Get,
30 // PropOpEmitter::ObjKind::Other);
31 // poe.prepareForObj();
33 // poe.emitGet(atom_of_prop);
36 // PropOpEmitter poe(this,
37 // PropOpEmitter::Kind::Get,
38 // PropOpEmitter::ObjKind::Super);
39 // poe.prepareForObj();
41 // poe.emitGet(atom_of_prop);
44 // PropOpEmitter poe(this,
45 // PropOpEmitter::Kind::Call,
46 // PropOpEmitter::ObjKind::Other);
47 // poe.prepareForObj();
49 // poe.emitGet(atom_of_prop);
53 // PropOpEmitter poe(this,
54 // PropOpEmitter::Kind::Call,
55 // PropOpEmitter::ObjKind::Other);
56 // poe.prepareForObj();
58 // poe.emitGet(atom_of_prop);
62 // PropOpEmitter poe(this,
63 // PropOpEmitter::Kind::Delete,
64 // PropOpEmitter::ObjKind::Other);
65 // poe.prepareForObj();
67 // poe.emitDelete(atom_of_prop);
69 // `delete super.prop;`
70 // PropOpEmitter poe(this,
71 // PropOpEmitter::Kind::Delete,
72 // PropOpEmitter::ObjKind::Other);
73 // poe.emitDelete(atom_of_prop);
76 // PropOpEmitter poe(this,
77 // PropOpEmitter::Kind::PostIncrement,
78 // PropOpEmitter::ObjKind::Other);
79 // poe.prepareForObj();
81 // poe.emitIncDec(atom_of_prop);
83 // `obj.prop = value;`
84 // PropOpEmitter poe(this,
85 // PropOpEmitter::Kind::SimpleAssignment,
86 // PropOpEmitter::ObjKind::Other);
87 // poe.prepareForObj();
89 // poe.prepareForRhs();
91 // poe.emitAssignment(atom_of_prop);
93 // `obj.prop += value;`
94 // PropOpEmitter poe(this,
95 // PropOpEmitter::Kind::CompoundAssignment,
96 // PropOpEmitter::ObjKind::Other);
97 // poe.prepareForObj();
99 // poe.emitGet(atom_of_prop);
100 // poe.prepareForRhs();
102 // emit_add_op_here();
103 // poe.emitAssignment(nullptr); // nullptr for CompoundAssignment
105 class MOZ_STACK_CLASS PropOpEmitter
{
119 enum class ObjKind
{ Super
, Other
};
122 BytecodeEmitter
* bce_
;
127 // The index for the property name's atom.
128 GCThingIndex propAtomIndex_
;
131 // The state of this emitter.
134 // +-------+ prepareForObj +-----+
135 // | Start |---------------->| Obj |-+
136 // +-------+ +-----+ |
138 // +---------------------------------+
144 // +---------->| Get |
148 // | emitDelete +--------+
149 // +------------->| Delete |
156 // | emitIncDec +--------+
157 // +------------->| IncDec |
160 // | [SimpleAssignment]
162 // | prepareForRhs +-----+
163 // +--------------------->+----------------->| Rhs |-+
167 // | [CompoundAssignment] | |
168 // | emitGet +-----+ | | emitAssignment +------------+
169 // +---------->| Get |----+ + -------------->| Assignment |
170 // +-----+ +------------+
172 // The initial state.
175 // After calling prepareForObj.
178 // After calling emitGet.
181 // After calling emitDelete.
184 // After calling emitIncDec.
187 // After calling prepareForRhs.
190 // After calling emitAssignment.
193 State state_
= State::Start
;
197 PropOpEmitter(BytecodeEmitter
* bce
, Kind kind
, ObjKind objKind
);
200 [[nodiscard
]] bool isCall() const { return kind_
== Kind::Call
; }
202 [[nodiscard
]] bool isSuper() const { return objKind_
== ObjKind::Super
; }
204 [[nodiscard
]] bool isSimpleAssignment() const {
205 return kind_
== Kind::SimpleAssignment
;
208 [[nodiscard
]] bool isPropInit() const { return kind_
== Kind::PropInit
; }
210 [[nodiscard
]] bool isDelete() const { return kind_
== Kind::Delete
; }
212 [[nodiscard
]] bool isCompoundAssignment() const {
213 return kind_
== Kind::CompoundAssignment
;
216 [[nodiscard
]] bool isIncDec() const {
217 return isPostIncDec() || isPreIncDec();
220 [[nodiscard
]] bool isPostIncDec() const {
221 return kind_
== Kind::PostIncrement
|| kind_
== Kind::PostDecrement
;
224 [[nodiscard
]] bool isPreIncDec() const {
225 return kind_
== Kind::PreIncrement
|| kind_
== Kind::PreDecrement
;
228 [[nodiscard
]] bool isInc() const {
229 return kind_
== Kind::PostIncrement
|| kind_
== Kind::PreIncrement
;
232 [[nodiscard
]] bool prepareAtomIndex(TaggedParserAtomIndex prop
);
235 [[nodiscard
]] bool prepareForObj();
237 [[nodiscard
]] bool emitGet(TaggedParserAtomIndex prop
);
239 [[nodiscard
]] bool prepareForRhs();
241 [[nodiscard
]] bool emitDelete(TaggedParserAtomIndex prop
);
243 // `prop` can be nullptr for CompoundAssignment.
244 [[nodiscard
]] bool emitAssignment(TaggedParserAtomIndex prop
);
246 [[nodiscard
]] bool emitIncDec(TaggedParserAtomIndex prop
,
247 ValueUsage valueUsage
);
249 size_t numReferenceSlots() const { return 1 + isSuper(); }
252 } /* namespace frontend */
255 #endif /* frontend_PropOpEmitter_h */