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"
12 #include "vm/SharedStencil.h" // GCThingIndex
17 struct BytecodeEmitter
;
18 class TaggedParserAtomIndex
;
19 enum class ValueUsage
;
21 // Class for emitting bytecode for property operation.
23 // Usage: (check for the return value is omitted for simplicity)
26 // PropOpEmitter poe(this,
27 // PropOpEmitter::Kind::Get,
28 // PropOpEmitter::ObjKind::Other);
29 // poe.prepareForObj();
31 // poe.emitGet(atom_of_prop);
34 // PropOpEmitter poe(this,
35 // PropOpEmitter::Kind::Get,
36 // PropOpEmitter::ObjKind::Super);
37 // poe.prepareForObj();
39 // poe.emitGet(atom_of_prop);
42 // PropOpEmitter poe(this,
43 // PropOpEmitter::Kind::Call,
44 // PropOpEmitter::ObjKind::Other);
45 // poe.prepareForObj();
47 // poe.emitGet(atom_of_prop);
51 // PropOpEmitter poe(this,
52 // PropOpEmitter::Kind::Call,
53 // PropOpEmitter::ObjKind::Other);
54 // poe.prepareForObj();
56 // poe.emitGet(atom_of_prop);
60 // PropOpEmitter poe(this,
61 // PropOpEmitter::Kind::Delete,
62 // PropOpEmitter::ObjKind::Other);
63 // poe.prepareForObj();
65 // poe.emitDelete(atom_of_prop);
67 // `delete super.prop;`
68 // PropOpEmitter poe(this,
69 // PropOpEmitter::Kind::Delete,
70 // PropOpEmitter::ObjKind::Other);
71 // poe.emitDelete(atom_of_prop);
74 // PropOpEmitter poe(this,
75 // PropOpEmitter::Kind::PostIncrement,
76 // PropOpEmitter::ObjKind::Other);
77 // poe.prepareForObj();
79 // poe.emitIncDec(atom_of_prop);
81 // `obj.prop = value;`
82 // PropOpEmitter poe(this,
83 // PropOpEmitter::Kind::SimpleAssignment,
84 // PropOpEmitter::ObjKind::Other);
85 // poe.prepareForObj();
87 // poe.prepareForRhs();
89 // poe.emitAssignment(atom_of_prop);
91 // `obj.prop += value;`
92 // PropOpEmitter poe(this,
93 // PropOpEmitter::Kind::CompoundAssignment,
94 // PropOpEmitter::ObjKind::Other);
95 // poe.prepareForObj();
97 // poe.emitGet(atom_of_prop);
98 // poe.prepareForRhs();
100 // emit_add_op_here();
101 // poe.emitAssignment(nullptr); // nullptr for CompoundAssignment
103 class MOZ_STACK_CLASS PropOpEmitter
{
117 enum class ObjKind
{ Super
, Other
};
120 BytecodeEmitter
* bce_
;
125 // The index for the property name's atom.
126 GCThingIndex propAtomIndex_
;
129 // The state of this emitter.
132 // +----------------------------+
134 // +-------+ | prepareForObj +-----+ |
135 // | Start |-+-------------->| Obj |-+ |
136 // +-------+ +-----+ | |
138 // +---------------------------------+ |
143 // | emitGet +-----+ |
144 // +---------->| Get | |
148 // | emitDelete +--------+ |
149 // +------------->| Delete | |
152 // | [PostIncrement] |
153 // | [PreIncrement] |
154 // | [PostDecrement] |
155 // | [PreDecrement] |
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 or skipObjAndRhs.
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();
240 [[nodiscard
]] bool skipObjAndRhs();
242 [[nodiscard
]] bool emitDelete(TaggedParserAtomIndex prop
);
244 // `prop` can be nullptr for CompoundAssignment.
245 [[nodiscard
]] bool emitAssignment(TaggedParserAtomIndex prop
);
247 [[nodiscard
]] bool emitIncDec(TaggedParserAtomIndex prop
,
248 ValueUsage valueUsage
);
251 } /* namespace frontend */
254 #endif /* frontend_PropOpEmitter_h */