PropOpEmitter.h (6972B)
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/. */ 6 7 #ifndef frontend_PropOpEmitter_h 8 #define frontend_PropOpEmitter_h 9 10 #include "mozilla/Attributes.h" 11 12 #include <stddef.h> 13 14 #include "vm/SharedStencil.h" // GCThingIndex 15 16 namespace js { 17 namespace frontend { 18 19 struct BytecodeEmitter; 20 class TaggedParserAtomIndex; 21 enum class ValueUsage; 22 23 // Class for emitting bytecode for property operation. 24 // 25 // Usage: (check for the return value is omitted for simplicity) 26 // 27 // `obj.prop;` 28 // PropOpEmitter poe(this, 29 // PropOpEmitter::Kind::Get, 30 // PropOpEmitter::ObjKind::Other); 31 // poe.prepareForObj(); 32 // emit(obj); 33 // poe.emitGet(atom_of_prop); 34 // 35 // `super.prop;` 36 // PropOpEmitter poe(this, 37 // PropOpEmitter::Kind::Get, 38 // PropOpEmitter::ObjKind::Super); 39 // poe.prepareForObj(); 40 // emit(obj); 41 // poe.emitGet(atom_of_prop); 42 // 43 // `obj.prop();` 44 // PropOpEmitter poe(this, 45 // PropOpEmitter::Kind::Call, 46 // PropOpEmitter::ObjKind::Other); 47 // poe.prepareForObj(); 48 // emit(obj); 49 // poe.emitGet(atom_of_prop); 50 // emit_call_here(); 51 // 52 // `new obj.prop();` 53 // PropOpEmitter poe(this, 54 // PropOpEmitter::Kind::Call, 55 // PropOpEmitter::ObjKind::Other); 56 // poe.prepareForObj(); 57 // emit(obj); 58 // poe.emitGet(atom_of_prop); 59 // emit_call_here(); 60 // 61 // `delete obj.prop;` 62 // PropOpEmitter poe(this, 63 // PropOpEmitter::Kind::Delete, 64 // PropOpEmitter::ObjKind::Other); 65 // poe.prepareForObj(); 66 // emit(obj); 67 // poe.emitDelete(atom_of_prop); 68 // 69 // `delete super.prop;` 70 // PropOpEmitter poe(this, 71 // PropOpEmitter::Kind::Delete, 72 // PropOpEmitter::ObjKind::Other); 73 // poe.emitDelete(atom_of_prop); 74 // 75 // `obj.prop++;` 76 // PropOpEmitter poe(this, 77 // PropOpEmitter::Kind::PostIncrement, 78 // PropOpEmitter::ObjKind::Other); 79 // poe.prepareForObj(); 80 // emit(obj); 81 // poe.emitIncDec(atom_of_prop); 82 // 83 // `obj.prop = value;` 84 // PropOpEmitter poe(this, 85 // PropOpEmitter::Kind::SimpleAssignment, 86 // PropOpEmitter::ObjKind::Other); 87 // poe.prepareForObj(); 88 // emit(obj); 89 // poe.prepareForRhs(); 90 // emit(value); 91 // poe.emitAssignment(atom_of_prop); 92 // 93 // `obj.prop += value;` 94 // PropOpEmitter poe(this, 95 // PropOpEmitter::Kind::CompoundAssignment, 96 // PropOpEmitter::ObjKind::Other); 97 // poe.prepareForObj(); 98 // emit(obj); 99 // poe.emitGet(atom_of_prop); 100 // poe.prepareForRhs(); 101 // emit(value); 102 // emit_add_op_here(); 103 // poe.emitAssignment(nullptr); // nullptr for CompoundAssignment 104 // 105 class MOZ_STACK_CLASS PropOpEmitter { 106 public: 107 enum class Kind { 108 Get, 109 Call, 110 Delete, 111 PostIncrement, 112 PreIncrement, 113 PostDecrement, 114 PreDecrement, 115 SimpleAssignment, 116 PropInit, 117 CompoundAssignment 118 }; 119 enum class ObjKind { Super, Other }; 120 121 private: 122 BytecodeEmitter* bce_; 123 124 Kind kind_; 125 ObjKind objKind_; 126 127 // The index for the property name's atom. 128 GCThingIndex propAtomIndex_; 129 130 #ifdef DEBUG 131 // The state of this emitter. 132 // 133 // 134 // +-------+ prepareForObj +-----+ 135 // | Start |---------------->| Obj |-+ 136 // +-------+ +-----+ | 137 // | 138 // +---------------------------------+ 139 // | 140 // | 141 // | [Get] 142 // | [Call] 143 // | emitGet +-----+ 144 // +---------->| Get | 145 // | +-----+ 146 // | 147 // | [Delete] 148 // | emitDelete +--------+ 149 // +------------->| Delete | 150 // | +--------+ 151 // | 152 // | [PostIncrement] 153 // | [PreIncrement] 154 // | [PostDecrement] 155 // | [PreDecrement] 156 // | emitIncDec +--------+ 157 // +------------->| IncDec | 158 // | +--------+ 159 // | 160 // | [SimpleAssignment] 161 // | [PropInit] 162 // | prepareForRhs +-----+ 163 // +--------------------->+----------------->| Rhs |-+ 164 // | ^ +-----+ | 165 // | | | 166 // | | +---------+ 167 // | [CompoundAssignment] | | 168 // | emitGet +-----+ | | emitAssignment +------------+ 169 // +---------->| Get |----+ + -------------->| Assignment | 170 // +-----+ +------------+ 171 enum class State { 172 // The initial state. 173 Start, 174 175 // After calling prepareForObj. 176 Obj, 177 178 // After calling emitGet. 179 Get, 180 181 // After calling emitDelete. 182 Delete, 183 184 // After calling emitIncDec. 185 IncDec, 186 187 // After calling prepareForRhs. 188 Rhs, 189 190 // After calling emitAssignment. 191 Assignment, 192 }; 193 State state_ = State::Start; 194 #endif 195 196 public: 197 PropOpEmitter(BytecodeEmitter* bce, Kind kind, ObjKind objKind); 198 199 private: 200 [[nodiscard]] bool isCall() const { return kind_ == Kind::Call; } 201 202 [[nodiscard]] bool isSuper() const { return objKind_ == ObjKind::Super; } 203 204 [[nodiscard]] bool isSimpleAssignment() const { 205 return kind_ == Kind::SimpleAssignment; 206 } 207 208 [[nodiscard]] bool isPropInit() const { return kind_ == Kind::PropInit; } 209 210 [[nodiscard]] bool isDelete() const { return kind_ == Kind::Delete; } 211 212 [[nodiscard]] bool isCompoundAssignment() const { 213 return kind_ == Kind::CompoundAssignment; 214 } 215 216 [[nodiscard]] bool isIncDec() const { 217 return isPostIncDec() || isPreIncDec(); 218 } 219 220 [[nodiscard]] bool isPostIncDec() const { 221 return kind_ == Kind::PostIncrement || kind_ == Kind::PostDecrement; 222 } 223 224 [[nodiscard]] bool isPreIncDec() const { 225 return kind_ == Kind::PreIncrement || kind_ == Kind::PreDecrement; 226 } 227 228 [[nodiscard]] bool isInc() const { 229 return kind_ == Kind::PostIncrement || kind_ == Kind::PreIncrement; 230 } 231 232 [[nodiscard]] bool prepareAtomIndex(TaggedParserAtomIndex prop); 233 234 public: 235 [[nodiscard]] bool prepareForObj(); 236 237 [[nodiscard]] bool emitGet(TaggedParserAtomIndex prop); 238 239 [[nodiscard]] bool prepareForRhs(); 240 241 [[nodiscard]] bool emitDelete(TaggedParserAtomIndex prop); 242 243 // `prop` can be nullptr for CompoundAssignment. 244 [[nodiscard]] bool emitAssignment(TaggedParserAtomIndex prop); 245 246 [[nodiscard]] bool emitIncDec(TaggedParserAtomIndex prop, 247 ValueUsage valueUsage); 248 249 size_t numReferenceSlots() const { return 1 + isSuper(); } 250 }; 251 252 } /* namespace frontend */ 253 } /* namespace js */ 254 255 #endif /* frontend_PropOpEmitter_h */