BytecodeEmitter.h (46685B)
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 /* JS bytecode generation. */ 8 9 #ifndef frontend_BytecodeEmitter_h 10 #define frontend_BytecodeEmitter_h 11 12 #include "mozilla/Assertions.h" // MOZ_ASSERT 13 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS, MOZ_ALWAYS_INLINE, MOZ_NEVER_INLINE, MOZ_RAII 14 #include "mozilla/Maybe.h" // mozilla::Maybe, mozilla::Some 15 #include "mozilla/Saturate.h" // mozilla::SaturateUint8 16 #include "mozilla/Span.h" // mozilla::Span 17 18 #include <stddef.h> // ptrdiff_t 19 #include <stdint.h> // uint16_t, uint32_t 20 21 #include "frontend/AbstractScopePtr.h" // ScopeIndex 22 #include "frontend/BytecodeSection.h" // BytecodeSection, PerScriptData, GCThingList 23 #include "frontend/DestructuringFlavor.h" // DestructuringFlavor 24 #include "frontend/EitherParser.h" // EitherParser 25 #include "frontend/IteratorKind.h" // IteratorKind 26 #include "frontend/JumpList.h" // JumpList, JumpTarget 27 #include "frontend/NameAnalysisTypes.h" // NameLocation 28 #include "frontend/NameCollections.h" // AtomIndexMap 29 #include "frontend/ParseNode.h" // ParseNode and subclasses 30 #include "frontend/Parser.h" // Parser, PropListType 31 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex, ParserAtom 32 #include "frontend/ScriptIndex.h" // ScriptIndex 33 #include "frontend/SelfHostedIter.h" // SelfHostedIter 34 #include "frontend/SourceNotes.h" // SrcNoteType 35 #include "frontend/ValueUsage.h" // ValueUsage 36 #include "js/AllocPolicy.h" // ReportOutOfMemory 37 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin 38 #include "js/TypeDecls.h" // jsbytecode 39 #include "vm/BuiltinObjectKind.h" // BuiltinObjectKind 40 #include "vm/CheckIsObjectKind.h" // CheckIsObjectKind 41 #include "vm/CompletionKind.h" // CompletionKind 42 #include "vm/FunctionPrefixKind.h" // FunctionPrefixKind 43 #include "vm/GeneratorResumeKind.h" // GeneratorResumeKind 44 #include "vm/Opcodes.h" // JSOp 45 #include "vm/SharedStencil.h" // GCThingIndex, MemberInitializers 46 #include "vm/StencilEnums.h" // TryNoteKind 47 #include "vm/ThrowMsgKind.h" // ThrowMsgKind, ThrowCondition 48 49 namespace js { 50 51 class FrontendContext; 52 struct ConstantCompareOperand; 53 54 namespace frontend { 55 56 class BytecodeOffset; 57 class CallOrNewEmitter; 58 class ClassEmitter; 59 class DestructuringLHSRef; 60 class ElemOpEmitter; 61 class EmitterScope; 62 class ErrorReporter; 63 class FullParseHandler; 64 class NestableControl; 65 class PrivateOpEmitter; 66 class PropertyEmitter; 67 class PropOpEmitter; 68 class OptionalEmitter; 69 class SharedContext; 70 class TDZCheckCache; 71 class TryEmitter; 72 73 struct TokenPos; 74 75 enum class ValueIsOnStack { Yes, No }; 76 77 // [SMDOC] Bytecode emission 78 // 79 // Bytecode emitter class and helper classes for generating bytecode and related 80 // stencil data from AST generated by JS parser. 81 // 82 // 83 // BytecodeEmitter 84 // --------------- 85 // 86 // BytecodeEmitter receives an AST, and utilizes helper classes to generate the 87 // bytecode sequence, and related stencil data. 88 // 89 // BytecodeEmitter can be nested, in order to emit inner non-lazy function 90 // scripts. 91 // 92 // 93 // Bytecode structures 94 // ------------------- 95 // 96 // While bytecode is being emitted, it is separated into 2 parts, the prologue 97 // and the main part. The prologue part contains instantiation of the declared 98 // variables, functions, and special names in function. The main part contains 99 // the remaining part of the bytecode. 100 // 101 // The generated bytecode is stored into the following 2 classes, before 102 // converting them into stencil data (See ImmutableScriptData and 103 // BytecodeEmitter::createImmutableScriptData): 104 // 105 // * BytecodeSection 106 // * PerScriptData 107 // 108 // BytecodeSection stores the bytecode sequence and data directly associated 109 // with opcode or index inside the bytecode sequence. 110 // 111 // PerScriptData contains data referred from the bytecode, that is mostly the 112 // list of GC things. 113 // 114 // 115 // Bindings 116 // -------- 117 // 118 // # Scope and bindings 119 // 120 // When emitting AST node that's associated with a given scope, EmitterScope is 121 // allocated to store/cache the bindings information. 122 // 123 // This information is used when emitting an opcode that accesses bindings, to 124 // determine where the binding is stored, and how the binding should be 125 // accessed, including which opcode to use and what operand to use for it. 126 // 127 // 128 // # Temporal Dead Zone (TDZ) check cache 129 // 130 // The spec requires TDZ check for all lexical variable access, but emitting 131 // TDZ check for all operation increases the bytecode size and affects the 132 // performance. TDZCheckCache is a cache to optimize away unnecessary TDZ check 133 // operations. 134 // 135 // See comments for TDZCheckCache for more details. 136 // 137 // 138 // Control structures 139 // ------------------ 140 // 141 // # Jump list 142 // 143 // When emitting jump-related bytecode (if-else, break/continue, try-catch), 144 // forward jump is tracked by JumpList class, in order to patch the jump 145 // after the jump target is emitted. 146 // 147 // See the comment above JumpList class for mode details. 148 // 149 // 150 // # Loop and label 151 // 152 // Control structure related to break/continue is handled by NestableControl and 153 // its subclasses. Those classes handle jump with labelled and un-labelled 154 // break/continue, stack balancing around them, TDZ check cache for the 155 // loop's basic block, and association between the control and the scope. 156 // 157 // 158 // Emitter helpers 159 // --------------- 160 // 161 // Bytecode sequence or structure specific to certain syntax (e.g. if, for, try) 162 // are handled by emitter helper classes. 163 // 164 // Each emitter helper is defined in *Emitter.{cpp,h} in this directory. 165 // 166 // Emitter helpers should meet the following requirements: 167 // * helper classes should be ParseNode-agnostic 168 // * helper classes shouldn't contain `JS::Rooted` field, given they can be 169 // held in `mozilla::Maybe` in the consumer or other helper classes 170 // * instantiation (ctor/dtor) of the emitter helper class shouldn't 171 // modify BytecodeEmitter, except for nestable controls 172 // * instantiation (ctor/dtor) of the emitter helper class shouldn't 173 // read BytecodeEmitter field that can change before the first method call. 174 // Such data should be explicitly passed as parameter, or be accessed inside 175 // the method 176 // * methods that emits bytecode should be named `emit*` or `prepareFor*` 177 // * methods and their names shouldn't require the consumer knowing the 178 // details of the bytecode sequence/structure that the helper emits 179 // * implicit branch or scope/control handling should be hidden from the 180 // consumer 181 // * If there are multiple operations between bytecode that the consumer 182 // emits, they should be wrapped into single `emit*` or `prepareFor*` 183 // method 184 // e.g. 185 // // Bad! 186 // helper.emitJumpAroundA(); 187 // helper.allocateScopeForA(); 188 // ... // emit bytecode for A here 189 // helper.deallocateScopeForA(); 190 // helper.emitJumpAroundB(); 191 // helper.allocateScopeForB(); 192 // ... // emit bytecode for B here 193 // helper.deallocateScopeForB(); 194 // helper.emitJumpTarget(); 195 // 196 // // Good! 197 // helper.prepareForA(); 198 // ... // emit bytecode for A here 199 // helper.prepareForB(); 200 // ... // emit bytecode for B here 201 // helper.emitEnd(); 202 // * helper classes should track state transition and assert it in each 203 // method call, to avoid misuse 204 // * it's recommended to defer receiving parameter until the parameter value 205 // is actually used in the method, instead of receiving and storing them 206 // into instance fields 207 // 208 // See comment block above each helper class for more details and example usage. 209 210 struct MOZ_STACK_CLASS BytecodeEmitter { 211 // Context shared between parsing and bytecode generation. 212 SharedContext* const sc = nullptr; 213 214 FrontendContext* const fc = nullptr; 215 216 // Enclosing function or global context. 217 BytecodeEmitter* const parent = nullptr; 218 219 BytecodeSection bytecodeSection_; 220 221 static constexpr unsigned LastSrcNoteIsNotLineOnly = unsigned(-1); 222 223 unsigned lastLineOnlySrcNoteIndex = LastSrcNoteIsNotLineOnly; 224 225 public: 226 BytecodeSection& bytecodeSection() { return bytecodeSection_; } 227 const BytecodeSection& bytecodeSection() const { return bytecodeSection_; } 228 229 private: 230 PerScriptData perScriptData_; 231 232 public: 233 PerScriptData& perScriptData() { return perScriptData_; } 234 const PerScriptData& perScriptData() const { return perScriptData_; } 235 236 private: 237 // switchToMain sets this to the bytecode offset of the main section. 238 mozilla::Maybe<uint32_t> mainOffset_ = {}; 239 240 // Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be 241 // initialized. 242 mozilla::Maybe<EitherParser> ep_ = {}; 243 244 const ErrorReporter& errorReporter_; 245 246 public: 247 CompilationState& compilationState; 248 249 uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */ 250 251 // Index into scopeList of the body scope. 252 GCThingIndex bodyScopeIndex = ScopeNote::NoScopeIndex; 253 254 EmitterScope* varEmitterScope = nullptr; 255 NestableControl* innermostNestableControl = nullptr; 256 EmitterScope* innermostEmitterScope_ = nullptr; 257 TDZCheckCache* innermostTDZCheckCache = nullptr; 258 259 // When compiling in self-hosted mode, we have special intrinsics that act as 260 // decorators for exported functions. To keeps things simple, we only allow 261 // these to target the last top-level function emitted. This field tracks that 262 // function. 263 FunctionBox* prevSelfHostedTopLevelFunction = nullptr; 264 265 #ifdef DEBUG 266 bool unstableEmitterScope = false; 267 268 friend class AutoCheckUnstableEmitterScope; 269 #endif 270 271 const ErrorReporter& errorReporter() const { return errorReporter_; } 272 273 ParserAtomsTable& parserAtoms() { return compilationState.parserAtoms; } 274 const ParserAtomsTable& parserAtoms() const { 275 return compilationState.parserAtoms; 276 } 277 278 EmitterScope* innermostEmitterScope() const { 279 MOZ_ASSERT(!unstableEmitterScope); 280 return innermostEmitterScopeNoCheck(); 281 } 282 EmitterScope* innermostEmitterScopeNoCheck() const { 283 return innermostEmitterScope_; 284 } 285 286 // When parsing internal code such as self-hosted functions or synthetic 287 // class constructors, we do not emit breakpoint and srcnote data since there 288 // is no direcly corresponding user-visible sources. 289 const bool suppressBreakpointsAndSourceNotes = false; 290 291 // Script contains finally block. 292 bool hasTryFinally = false; 293 294 enum EmitterMode { 295 Normal, 296 297 // Emit JSOp::GetIntrinsic instead of JSOp::GetName and assert that 298 // JSOp::GetName and JSOp::*GName don't ever get emitted. See the comment 299 // for the field |selfHostingMode| in Parser.h for details. 300 SelfHosting, 301 302 // Check the static scope chain of the root function for resolving free 303 // variable accesses in the script. 304 LazyFunction 305 }; 306 307 const EmitterMode emitterMode = Normal; 308 309 mozilla::Maybe<uint32_t> scriptStartOffset = {}; 310 311 // The end location of a function body that is being emitted. 312 mozilla::Maybe<uint32_t> functionBodyEndPos = {}; 313 314 // Jump target just before the final CheckReturn opcode in a derived class 315 // constructor body. 316 JumpList endOfDerivedClassConstructorBody = {}; 317 318 // Jump target just before the final yield in a generator or async function. 319 JumpList finalYields = {}; 320 321 // In order to heuristically determine the size of the allocation if this is a 322 // constructor function, we track expressions which add properties in the 323 // constructor. 324 mozilla::SaturateUint8 propertyAdditionEstimate = {}; 325 326 /* 327 * Note that BytecodeEmitters are magic: they own the arena "top-of-stack" 328 * space above their tempMark points. This means that you cannot alloc from 329 * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter 330 * destruction. 331 */ 332 private: 333 // Internal constructor, for delegation use only. 334 BytecodeEmitter(BytecodeEmitter* parent, FrontendContext* fc, 335 SharedContext* sc, const ErrorReporter& errorReporter, 336 CompilationState& compilationState, EmitterMode emitterMode); 337 338 void initFromBodyPosition(TokenPos bodyPosition); 339 340 public: 341 BytecodeEmitter(FrontendContext* fc, const EitherParser& parser, 342 SharedContext* sc, CompilationState& compilationState, 343 EmitterMode emitterMode = Normal); 344 345 template <typename Unit> 346 BytecodeEmitter(FrontendContext* fc, Parser<FullParseHandler, Unit>* parser, 347 SharedContext* sc, CompilationState& compilationState, 348 EmitterMode emitterMode = Normal) 349 : BytecodeEmitter(fc, EitherParser(parser), sc, compilationState, 350 emitterMode) {} 351 352 BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc); 353 354 [[nodiscard]] bool init(); 355 [[nodiscard]] bool init(TokenPos bodyPosition); 356 357 template <typename T> 358 T* findInnermostNestableControl() const; 359 360 template <typename T, typename Predicate /* (T*) -> bool */> 361 T* findInnermostNestableControl(Predicate predicate) const; 362 363 NameLocation lookupName(TaggedParserAtomIndex name); 364 365 // See EmitterScope::lookupPrivate for details around brandLoc 366 void lookupPrivate(TaggedParserAtomIndex name, NameLocation& loc, 367 mozilla::Maybe<NameLocation>& brandLoc); 368 369 // To implement Annex B and the formal parameter defaults scope semantics 370 // requires accessing names that would otherwise be shadowed. This method 371 // returns the access location of a name that is known to be bound in a 372 // target scope. 373 mozilla::Maybe<NameLocation> locationOfNameBoundInScope( 374 TaggedParserAtomIndex name, EmitterScope* target); 375 376 // Get the location of a name known to be bound in a given scope, 377 // starting at the source scope. 378 template <typename T> 379 mozilla::Maybe<NameLocation> locationOfNameBoundInScopeType( 380 TaggedParserAtomIndex name, EmitterScope* source); 381 382 // Get the location of a name known to be bound in the function scope, 383 // starting at the source scope. 384 mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope( 385 TaggedParserAtomIndex name) { 386 return locationOfNameBoundInScopeType<FunctionScope>( 387 name, innermostEmitterScope()); 388 } 389 390 mozilla::Maybe<ConstantCompareOperand> parseNodeToConstantCompareOperand( 391 ParseNode* constant); 392 393 void setVarEmitterScope(EmitterScope* emitterScope) { 394 MOZ_ASSERT(emitterScope); 395 MOZ_ASSERT(!varEmitterScope); 396 varEmitterScope = emitterScope; 397 } 398 399 AbstractScopePtr outermostScope() const { 400 return perScriptData().gcThingList().firstScope(); 401 } 402 AbstractScopePtr innermostScope() const; 403 ScopeIndex innermostScopeIndex() const; 404 405 [[nodiscard]] MOZ_ALWAYS_INLINE bool makeAtomIndex( 406 TaggedParserAtomIndex atom, ParserAtom::Atomize atomize, 407 GCThingIndex* indexp) { 408 MOZ_ASSERT(perScriptData().atomIndices()); 409 AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom); 410 if (p) { 411 compilationState.parserAtoms.markAtomize(atom, atomize); 412 *indexp = GCThingIndex(p->value()); 413 return true; 414 } 415 416 GCThingIndex index; 417 if (!perScriptData().gcThingList().append(atom, atomize, &index)) { 418 return false; 419 } 420 421 // `atomIndices()` uses uint32_t instead of GCThingIndex, because 422 // GCThingIndex isn't trivial type. 423 if (!perScriptData().atomIndices()->add(p, atom, index.index)) { 424 ReportOutOfMemory(fc); 425 return false; 426 } 427 428 *indexp = index; 429 return true; 430 } 431 432 bool isInLoop() const; 433 [[nodiscard]] bool checkSingletonContext() const; 434 435 bool needsImplicitThis() const; 436 437 size_t countThisEnvironmentHops() const; 438 [[nodiscard]] bool emitThisEnvironmentCallee(); 439 [[nodiscard]] bool emitSuperBase(); 440 441 uint32_t mainOffset() const { return *mainOffset_; } 442 443 bool inPrologue() const { return mainOffset_.isNothing(); } 444 445 void switchToMain() { 446 MOZ_ASSERT(inPrologue()); 447 mainOffset_.emplace(bytecodeSection().code().length()); 448 } 449 450 void setFunctionBodyEndPos(uint32_t pos) { 451 functionBodyEndPos = mozilla::Some(pos); 452 } 453 454 void setScriptStartOffsetIfUnset(uint32_t pos) { 455 if (scriptStartOffset.isNothing()) { 456 scriptStartOffset = mozilla::Some(pos); 457 } 458 } 459 460 void reportError(ParseNode* pn, unsigned errorNumber, ...) const; 461 void reportError(uint32_t offset, unsigned errorNumber, ...) const; 462 463 // Fill in a ScriptStencil using this BCE data. 464 bool intoScriptStencil(ScriptIndex scriptIndex); 465 466 // If pn contains a useful expression, return true with *answer set to true. 467 // If pn contains a useless expression, return true with *answer set to 468 // false. Return false on error. 469 // 470 // The caller should initialize *answer to false and invoke this function on 471 // an expression statement or similar subtree to decide whether the tree 472 // could produce code that has any side effects. For an expression 473 // statement, we define useless code as code with no side effects, because 474 // the main effect, the value left on the stack after the code executes, 475 // will be discarded by a pop bytecode. 476 [[nodiscard]] bool checkSideEffects(ParseNode* pn, bool* answer) const; 477 478 #ifdef DEBUG 479 [[nodiscard]] bool checkStrictOrSloppy(JSOp op) const; 480 #endif 481 482 // Add TryNote to the tryNoteList array. The start and end offset are 483 // relative to current section. 484 [[nodiscard]] bool addTryNote(TryNoteKind kind, uint32_t stackDepth, 485 BytecodeOffset start, BytecodeOffset end); 486 487 // Indicates the emitter should not generate location or debugger source 488 // notes. This lets us avoid generating notes for non-user code. 489 bool skipLocationSrcNotes() const { 490 return inPrologue() || suppressBreakpointsAndSourceNotes; 491 } 492 bool skipBreakpointSrcNotes() const { 493 return inPrologue() || suppressBreakpointsAndSourceNotes; 494 } 495 496 // Append a new source note of the given type (and therefore size) to the 497 // notes dynamic array, updating noteCount. Return the new note's index 498 // within the array pointed at by current->notes as outparam. 499 [[nodiscard]] bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr); 500 [[nodiscard]] bool newSrcNote2(SrcNoteType type, ptrdiff_t operand, 501 unsigned* indexp = nullptr); 502 [[nodiscard]] bool convertLastNewLineToNewLineColumn( 503 JS::LimitedColumnNumberOneOrigin column); 504 [[nodiscard]] bool convertLastSetLineToSetLineColumn( 505 JS::LimitedColumnNumberOneOrigin column); 506 507 [[nodiscard]] bool newSrcNoteOperand(ptrdiff_t operand); 508 509 // Control whether emitTree emits a line number note. 510 enum EmitLineNumberNote { EMIT_LINENOTE, SUPPRESS_LINENOTE }; 511 512 // Emit code for the tree rooted at pn. 513 [[nodiscard]] bool emitTree(ParseNode* pn, 514 ValueUsage valueUsage = ValueUsage::WantValue, 515 EmitLineNumberNote emitLineNote = EMIT_LINENOTE); 516 517 [[nodiscard]] bool emitOptionalTree( 518 ParseNode* pn, OptionalEmitter& oe, 519 ValueUsage valueUsage = ValueUsage::WantValue); 520 521 [[nodiscard]] bool emitDeclarationInstantiation(ParseNode* body); 522 523 // Emit global, eval, or module code for tree rooted at body. Always 524 // encompasses the entire source. 525 [[nodiscard]] bool emitScript(ParseNode* body); 526 527 // Calculate the `nslots` value for ImmutableScriptData constructor parameter. 528 // Fails if it overflows. 529 [[nodiscard]] bool getNslots(uint32_t* nslots) const; 530 531 // Emit function code for the tree rooted at body. 532 [[nodiscard]] bool emitFunctionScript(FunctionNode* funNode); 533 534 [[nodiscard]] bool markStepBreakpoint(); 535 [[nodiscard]] bool markSimpleBreakpoint(); 536 [[nodiscard]] bool updateLineNumberNotes(uint32_t offset); 537 [[nodiscard]] bool updateSourceCoordNotes(uint32_t offset); 538 [[nodiscard]] bool updateSourceCoordNotesIfNonLiteral(ParseNode* node); 539 540 [[nodiscard]] bool emitCheck(JSOp op, ptrdiff_t delta, 541 BytecodeOffset* offset); 542 543 // Emit one bytecode. 544 [[nodiscard]] bool emit1(JSOp op); 545 546 // Emit two bytecodes, an opcode (op) with a byte of immediate operand 547 // (op1). 548 [[nodiscard]] bool emit2(JSOp op, uint8_t op1); 549 550 // Emit three bytecodes, an opcode with two bytes of immediate operands. 551 [[nodiscard]] bool emit3(JSOp op, jsbytecode op1, jsbytecode op2); 552 553 // Helper to duplicate one or more stack values. |slotFromTop| is the value's 554 // depth on the JS stack, as measured from the top. |count| is the number of 555 // values to duplicate, in theiro original order. 556 [[nodiscard]] bool emitDupAt(unsigned slotFromTop, unsigned count = 1); 557 558 // Helper to emit JSOp::Pop or JSOp::PopN. 559 [[nodiscard]] bool emitPopN(unsigned n); 560 561 // Helper to emit JSOp::Swap or JSOp::Pick. 562 [[nodiscard]] bool emitPickN(uint8_t n); 563 564 // Helper to emit JSOp::Swap or JSOp::Unpick. 565 [[nodiscard]] bool emitUnpickN(uint8_t n); 566 567 // Helper to emit JSOp::CheckIsObj. 568 [[nodiscard]] bool emitCheckIsObj(CheckIsObjectKind kind); 569 570 // Helper to emit JSOp::BuiltinObject. 571 [[nodiscard]] bool emitBuiltinObject(BuiltinObjectKind kind); 572 573 // Emit a bytecode followed by an uint16 immediate operand stored in 574 // big-endian order. 575 [[nodiscard]] bool emitUint16Operand(JSOp op, uint32_t operand); 576 577 // Emit a bytecode followed by an uint32 immediate operand. 578 [[nodiscard]] bool emitUint32Operand(JSOp op, uint32_t operand); 579 580 // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand. 581 [[nodiscard]] bool emitN(JSOp op, size_t extra, 582 BytecodeOffset* offset = nullptr); 583 584 [[nodiscard]] bool emitDouble(double dval); 585 [[nodiscard]] bool emitNumberOp(double dval); 586 587 [[nodiscard]] bool emitBigIntOp(BigIntLiteral* bigint); 588 589 [[nodiscard]] bool emitThisLiteral(ThisLiteral* pn); 590 [[nodiscard]] bool emitGetFunctionThis(NameNode* thisName); 591 [[nodiscard]] bool emitGetThisForSuperBase(UnaryNode* superBase); 592 [[nodiscard]] bool emitSetThis(BinaryNode* setThisNode); 593 [[nodiscard]] bool emitCheckDerivedClassConstructorReturn(); 594 595 private: 596 [[nodiscard]] bool emitNewTarget(); 597 598 public: 599 [[nodiscard]] bool emitNewTarget(NewTargetNode* pn); 600 [[nodiscard]] bool emitNewTarget(CallNode* pn); 601 602 // Handle jump opcodes and jump targets. 603 [[nodiscard]] bool emitJumpTargetOp(JSOp op, BytecodeOffset* off); 604 [[nodiscard]] bool emitJumpTarget(JumpTarget* target); 605 [[nodiscard]] bool emitJumpNoFallthrough(JSOp op, JumpList* jump); 606 [[nodiscard]] bool emitJump(JSOp op, JumpList* jump); 607 void patchJumpsToTarget(JumpList jump, JumpTarget target); 608 [[nodiscard]] bool emitJumpTargetAndPatch(JumpList jump); 609 610 [[nodiscard]] bool emitCall( 611 JSOp op, uint16_t argc, 612 const mozilla::Maybe<uint32_t>& sourceCoordOffset); 613 [[nodiscard]] bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr); 614 [[nodiscard]] bool emitCallIncDec(UnaryNode* incDec); 615 616 uint32_t getOffsetForLoop(ParseNode* nextpn) const; 617 618 enum class GotoKind { Break, Continue }; 619 [[nodiscard]] bool emitGoto(NestableControl* target, GotoKind kind); 620 621 [[nodiscard]] bool emitGCIndexOp(JSOp op, GCThingIndex index); 622 623 [[nodiscard]] bool emitAtomOp(JSOp op, TaggedParserAtomIndex atom); 624 [[nodiscard]] bool emitAtomOp(JSOp op, GCThingIndex atomIndex); 625 626 [[nodiscard]] bool emitStringOp(JSOp op, TaggedParserAtomIndex atom); 627 [[nodiscard]] bool emitStringOp(JSOp op, GCThingIndex atomIndex); 628 629 [[nodiscard]] bool emitArrayLiteral(ListNode* array); 630 [[nodiscard]] bool emitArray(ListNode* array); 631 [[nodiscard]] bool emitSpreadIntoArray(UnaryNode* elem); 632 633 [[nodiscard]] bool emitInternedScopeOp(GCThingIndex index, JSOp op); 634 [[nodiscard]] bool emitInternedObjectOp(GCThingIndex index, JSOp op); 635 [[nodiscard]] bool emitRegExp(GCThingIndex index); 636 637 [[nodiscard]] MOZ_NEVER_INLINE bool emitFunction(FunctionNode* funNode, 638 bool needsProto = false); 639 [[nodiscard]] MOZ_NEVER_INLINE bool emitObject(ListNode* objNode); 640 641 [[nodiscard]] bool emitHoistedFunctionsInList(ListNode* stmtList); 642 643 // Can we use the object-literal writer either in singleton-object mode (with 644 // values) or in template mode (field names only, no values) for the property 645 // list? 646 void isPropertyListObjLiteralCompatible(ListNode* obj, bool* withValues, 647 bool* withoutValues) const; 648 bool isArrayObjLiteralCompatible(ListNode* array) const; 649 650 [[nodiscard]] bool emitPropertyList(ListNode* obj, PropertyEmitter& pe, 651 PropListType type); 652 653 [[nodiscard]] bool emitPropertyListObjLiteral(ListNode* obj, JSOp op, 654 bool useObjLiteralValues); 655 656 [[nodiscard]] bool emitDestructuringRestExclusionSetObjLiteral( 657 ListNode* pattern); 658 659 [[nodiscard]] bool emitObjLiteralArray(ListNode* array); 660 661 // Is a field value JSOp::Object-compatible? 662 [[nodiscard]] bool isRHSObjLiteralCompatible(ParseNode* value) const; 663 664 [[nodiscard]] bool emitObjLiteralValue(ObjLiteralWriter& writer, 665 ParseNode* value); 666 667 mozilla::Maybe<MemberInitializers> setupMemberInitializers( 668 ListNode* classMembers, FieldPlacement placement) const; 669 [[nodiscard]] bool emitCreateFieldKeys(ListNode* obj, 670 FieldPlacement placement); 671 [[nodiscard]] bool emitCreateMemberInitializers(ClassEmitter& ce, 672 ListNode* obj, 673 FieldPlacement placement 674 #ifdef ENABLE_DECORATORS 675 , 676 bool hasHeritage 677 #endif 678 ); 679 const MemberInitializers& findMemberInitializersForCall() const; 680 [[nodiscard]] bool emitInitializeInstanceMembers( 681 bool isDerivedClassConstructor); 682 [[nodiscard]] bool emitInitializeStaticFields(ListNode* classMembers); 683 684 [[nodiscard]] bool emitPrivateMethodInitializers(ClassEmitter& ce, 685 ListNode* obj); 686 [[nodiscard]] bool emitPrivateMethodInitializer( 687 ClassMethod* classMethod, TaggedParserAtomIndex storedMethodAtom); 688 689 // To catch accidental misuse, emitUint16Operand/emit3 assert that they are 690 // not used to unconditionally emit JSOp::GetLocal. Variable access should 691 // instead be emitted using EmitVarOp. In special cases, when the caller 692 // definitely knows that a given local slot is unaliased, this function may be 693 // used as a non-asserting version of emitUint16Operand. 694 [[nodiscard]] bool emitLocalOp(JSOp op, uint32_t slot); 695 696 [[nodiscard]] bool emitArgOp(JSOp op, uint16_t slot); 697 [[nodiscard]] bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec); 698 699 [[nodiscard]] bool emitGetNameAtLocation(TaggedParserAtomIndex name, 700 const NameLocation& loc); 701 [[nodiscard]] bool emitGetName(TaggedParserAtomIndex name) { 702 return emitGetNameAtLocation(name, lookupName(name)); 703 } 704 [[nodiscard]] bool emitGetName(NameNode* name); 705 [[nodiscard]] bool emitGetPrivateName(NameNode* name); 706 [[nodiscard]] bool emitGetPrivateName(TaggedParserAtomIndex name); 707 708 [[nodiscard]] bool emitTDZCheckIfNeeded(TaggedParserAtomIndex name, 709 const NameLocation& loc, 710 ValueIsOnStack isOnStack); 711 712 [[nodiscard]] bool emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage); 713 714 [[nodiscard]] bool emitDeclarationList(ListNode* declList); 715 [[nodiscard]] bool emitSingleDeclaration(ListNode* declList, NameNode* decl, 716 ParseNode* initializer); 717 [[nodiscard]] bool emitAssignmentRhs(ParseNode* rhs, 718 TaggedParserAtomIndex anonFunctionName); 719 [[nodiscard]] bool emitAssignmentRhs(uint8_t offset); 720 721 [[nodiscard]] bool emitPrepareIteratorResult(); 722 [[nodiscard]] bool emitFinishIteratorResult(bool done); 723 724 // Convert and add `writer` data to stencil. 725 // Iff it suceeds, `outIndex` out parameter is initialized to the index of the 726 // object in GC things vector. 727 [[nodiscard]] bool addObjLiteralData(ObjLiteralWriter& writer, 728 GCThingIndex* outIndex); 729 730 [[nodiscard]] bool emitGetDotGeneratorInInnermostScope() { 731 return emitGetDotGeneratorInScope(*innermostEmitterScope()); 732 } 733 [[nodiscard]] bool emitGetDotGeneratorInScope(EmitterScope& currentScope); 734 735 [[nodiscard]] bool allocateResumeIndex(BytecodeOffset offset, 736 uint32_t* resumeIndex); 737 [[nodiscard]] bool allocateResumeIndexRange( 738 mozilla::Span<BytecodeOffset> offsets, uint32_t* firstResumeIndex); 739 740 [[nodiscard]] bool emitInitialYield(UnaryNode* yieldNode); 741 [[nodiscard]] bool emitYield(UnaryNode* yieldNode); 742 [[nodiscard]] bool emitYieldOp(JSOp op); 743 [[nodiscard]] bool emitYieldStar(ParseNode* iter); 744 [[nodiscard]] bool emitAwaitInInnermostScope() { 745 return emitAwaitInScope(*innermostEmitterScope()); 746 } 747 [[nodiscard]] bool emitAwaitInInnermostScope(UnaryNode* awaitNode); 748 [[nodiscard]] bool emitAwaitInScope(EmitterScope& currentScope); 749 750 [[nodiscard]] bool emitPushResumeKind(GeneratorResumeKind kind); 751 752 [[nodiscard]] bool emitPropLHS(PropertyAccess* prop); 753 [[nodiscard]] bool emitPropIncDec(UnaryNode* incDec, ValueUsage valueUsage); 754 755 [[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName); 756 757 // Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem 758 // opcode onto the stack in the right order. In the case of SetElem, the 759 // value to be assigned must already be pushed. 760 enum class EmitElemOption { Get, Call, IncDec, CompoundAssign, Ref }; 761 [[nodiscard]] bool emitElemOperands(PropertyByValue* elem, 762 EmitElemOption opts); 763 764 [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, 765 ElemOpEmitter& eoe); 766 [[nodiscard]] bool emitElemOpBase(JSOp op); 767 768 [[nodiscard]] bool emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage); 769 [[nodiscard]] bool emitObjAndPrivateName(PrivateMemberAccess* elem, 770 ElemOpEmitter& eoe); 771 [[nodiscard]] bool emitPrivateIncDec(UnaryNode* incDec, 772 ValueUsage valueUsage); 773 774 [[nodiscard]] bool emitCatch(BinaryNode* catchClause); 775 [[nodiscard]] bool emitIf(TernaryNode* ifNode); 776 [[nodiscard]] bool emitWith(BinaryNode* withNode); 777 778 [[nodiscard]] MOZ_NEVER_INLINE bool emitLabeledStatement( 779 const LabeledStatement* labeledStmt); 780 [[nodiscard]] MOZ_NEVER_INLINE bool emitLexicalScope( 781 LexicalScopeNode* lexicalScope); 782 [[nodiscard]] bool emitLexicalScopeBody( 783 ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE); 784 [[nodiscard]] MOZ_NEVER_INLINE bool emitSwitch(SwitchStatement* switchStmt); 785 [[nodiscard]] MOZ_NEVER_INLINE bool emitTry(TryNode* tryNode); 786 787 [[nodiscard]] bool emitJumpToFinally(JumpList* jump, uint32_t idx); 788 789 // emitDestructuringLHSRef emits the lhs expression's reference. 790 // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|. 791 // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|. 792 // If there's nothing to evaluate for the reference, it emits nothing. 793 [[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target, 794 DestructuringFlavor flav, 795 DestructuringLHSRef& lref); 796 797 // emitSetOrInitializeDestructuring assumes the lhs expression's reference 798 // and the to-be-destructured value has been pushed on the stack. It emits 799 // code to destructure a single lhs expression (either a name or a compound 800 // []/{} expression). 801 [[nodiscard]] bool emitSetOrInitializeDestructuring( 802 ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref); 803 804 // emitDestructuringObjRestExclusionSet emits the property exclusion set 805 // for the rest-property in an object pattern. 806 [[nodiscard]] bool emitDestructuringObjRestExclusionSet(ListNode* pattern, 807 uint8_t setSize); 808 809 // emitDestructuringOps assumes the to-be-destructured value has been 810 // pushed on the stack and emits code to destructure each part of a [] or 811 // {} lhs expression. 812 [[nodiscard]] bool emitDestructuringOps(ListNode* pattern, 813 DestructuringFlavor flav, 814 SelfHostedIter selfHostedIter); 815 [[nodiscard]] bool emitDestructuringOpsArray(ListNode* pattern, 816 DestructuringFlavor flav, 817 SelfHostedIter selfHostedIter); 818 [[nodiscard]] bool emitDestructuringOpsObject(ListNode* pattern, 819 DestructuringFlavor flav); 820 821 enum class CopyOption { Filtered, Unfiltered }; 822 823 // Calls either the |CopyDataProperties| or the 824 // |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or 825 // two in the latter case) elements from the stack. 826 [[nodiscard]] bool emitCopyDataProperties(CopyOption option); 827 828 JSOp getIterCallOp(JSOp callOp, SelfHostedIter selfHostedIter) const; 829 830 // Push the operands for emit(Async)Iterator onto the stack. 831 [[nodiscard]] bool emitIterable(ParseNode* value, 832 SelfHostedIter selfHostedIter, 833 IteratorKind iterKind = IteratorKind::Sync); 834 835 // emitIterator expects the iterable to already be on the stack. 836 // It will replace that stack value with the corresponding iterator 837 [[nodiscard]] bool emitIterator(SelfHostedIter selfHostedIter); 838 839 [[nodiscard]] bool emitAsyncIterator(SelfHostedIter selfHostedIter); 840 841 // Pops iterator from the top of the stack. Pushes the result of |.next()| 842 // onto the stack. 843 [[nodiscard]] bool emitIteratorNext( 844 const mozilla::Maybe<uint32_t>& callSourceCoordOffset, IteratorKind kind, 845 SelfHostedIter selfHostedIter); 846 [[nodiscard]] bool emitIteratorCloseInScope(EmitterScope& currentScope, 847 IteratorKind iterKind, 848 CompletionKind completionKind, 849 SelfHostedIter selfHostedIter); 850 [[nodiscard]] bool emitIteratorCloseInInnermostScope( 851 IteratorKind iterKind, CompletionKind completionKind, 852 SelfHostedIter selfHostedIter) { 853 return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, 854 completionKind, selfHostedIter); 855 } 856 857 template <typename InnerEmitter> 858 [[nodiscard]] bool wrapWithDestructuringTryNote(int32_t iterDepth, 859 InnerEmitter emitter); 860 861 [[nodiscard]] bool defineHoistedTopLevelFunctions(ParseNode* body); 862 863 // Check if the value on top of the stack is "undefined". If so, replace 864 // that value on the stack with the value defined by |defaultExpr|. 865 // |pattern| is a lhs node of the default expression. If it's an 866 // identifier and |defaultExpr| is an anonymous function, |SetFunctionName| 867 // is called at compile time. 868 [[nodiscard]] bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern); 869 870 [[nodiscard]] bool emitAnonymousFunctionWithName(ParseNode* node, 871 TaggedParserAtomIndex name); 872 873 [[nodiscard]] bool emitAnonymousFunctionWithComputedName( 874 ParseNode* node, FunctionPrefixKind prefixKind); 875 876 void setFunName(FunctionBox* fun, TaggedParserAtomIndex name) const; 877 [[nodiscard]] bool emitInitializer(ParseNode* initializer, 878 ParseNode* pattern); 879 880 [[nodiscard]] bool emitCallSiteObjectArray(ObjLiteralWriter& writer, 881 ListNode* cookedOrRaw, 882 ParseNode* head, uint32_t count); 883 [[nodiscard]] bool emitCallSiteObject(CallSiteNode* callSiteObj); 884 [[nodiscard]] bool emitTemplateString(ListNode* templateString); 885 [[nodiscard]] bool emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, 886 ParseNode* rhs); 887 [[nodiscard]] bool emitShortCircuitAssignment(AssignmentNode* node); 888 889 [[nodiscard]] bool emitReturn(UnaryNode* returnNode); 890 [[nodiscard]] bool finishReturn(BytecodeOffset setRvalOffset); 891 892 [[nodiscard]] bool emitExpressionStatement(UnaryNode* exprStmt); 893 [[nodiscard]] bool emitStatementList(ListNode* stmtList); 894 895 [[nodiscard]] bool emitDeleteName(UnaryNode* deleteNode); 896 [[nodiscard]] bool emitDeleteProperty(UnaryNode* deleteNode); 897 [[nodiscard]] bool emitDeleteElement(UnaryNode* deleteNode); 898 [[nodiscard]] bool emitDeleteExpression(UnaryNode* deleteNode); 899 900 // Optional methods which emit Optional Jump Target 901 [[nodiscard]] bool emitOptionalChain(UnaryNode* expr, ValueUsage valueUsage); 902 [[nodiscard]] bool emitCalleeAndThisForOptionalChain(UnaryNode* expr, 903 CallNode* callNode, 904 CallOrNewEmitter& cone); 905 [[nodiscard]] bool emitDeleteOptionalChain(UnaryNode* deleteNode); 906 907 // Optional methods which emit a shortCircuit jump. They need to be called by 908 // a method which emits an Optional Jump Target, see below. 909 [[nodiscard]] bool emitOptionalDotExpression(PropertyAccessBase* expr, 910 PropOpEmitter& poe, bool isSuper, 911 OptionalEmitter& oe); 912 [[nodiscard]] bool emitOptionalElemExpression(PropertyByValueBase* elem, 913 ElemOpEmitter& eoe, 914 bool isSuper, 915 OptionalEmitter& oe); 916 [[nodiscard]] bool emitOptionalPrivateExpression( 917 PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe, 918 OptionalEmitter& oe); 919 [[nodiscard]] bool emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, 920 ValueUsage valueUsage); 921 [[nodiscard]] bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, 922 OptionalEmitter& oe); 923 [[nodiscard]] bool emitDeleteElementInOptChain(PropertyByValueBase* elemExpr, 924 OptionalEmitter& oe); 925 926 // |op| must be JSOp::Typeof or JSOp::TypeofExpr. 927 [[nodiscard]] bool emitTypeof(UnaryNode* typeofNode, JSOp op); 928 929 [[nodiscard]] bool tryEmitTypeofEq(ListNode* node, bool* emitted); 930 931 [[nodiscard]] bool emitUnary(UnaryNode* unaryNode); 932 [[nodiscard]] bool emitRightAssociative(ListNode* node); 933 [[nodiscard]] bool tryEmitConstantEq(ListNode* node, JSOp op, bool* emitted); 934 [[nodiscard]] bool emitLeftAssociative(ListNode* node); 935 [[nodiscard]] bool emitPrivateInExpr(ListNode* node); 936 [[nodiscard]] bool emitShortCircuit(ListNode* node, ValueUsage valueUsage); 937 [[nodiscard]] bool emitSequenceExpr(ListNode* node, ValueUsage valueUsage); 938 939 [[nodiscard]] MOZ_NEVER_INLINE bool emitIncOrDec(UnaryNode* incDec, 940 ValueUsage valueUsage); 941 942 [[nodiscard]] bool emitConditionalExpression( 943 ConditionalExpression& conditional, ValueUsage valueUsage); 944 945 [[nodiscard]] ParseNode* getCoordNode(ParseNode* callNode, 946 ParseNode* calleeNode, JSOp op, 947 ListNode* argsList) const; 948 949 [[nodiscard]] bool emitArguments(ListNode* argsList, bool isCall, 950 bool isSpread, CallOrNewEmitter& cone); 951 [[nodiscard]] bool emitCallOrNew(CallNode* callNode, ValueUsage valueUsage); 952 [[nodiscard]] bool emitDebugCheckSelfHosted(); 953 [[nodiscard]] bool emitSelfHostedCallFunction(CallNode* callNode, JSOp op); 954 [[nodiscard]] bool emitSelfHostedResumeGenerator(CallNode* callNode); 955 [[nodiscard]] bool emitSelfHostedForceInterpreter(); 956 [[nodiscard]] bool emitSelfHostedAllowContentIter(CallNode* callNode); 957 [[nodiscard]] bool emitSelfHostedAllowContentIterWith(CallNode* callNode); 958 [[nodiscard]] bool emitSelfHostedAllowContentIterWithNext(CallNode* callNode); 959 [[nodiscard]] bool emitSelfHostedDefineDataProperty(CallNode* callNode); 960 [[nodiscard]] bool emitSelfHostedGetPropertySuper(CallNode* callNode); 961 [[nodiscard]] bool emitSelfHostedHasOwn(CallNode* callNode); 962 [[nodiscard]] bool emitSelfHostedToNumeric(CallNode* callNode); 963 [[nodiscard]] bool emitSelfHostedToString(CallNode* callNode); 964 [[nodiscard]] bool emitSelfHostedIsNullOrUndefined(CallNode* callNode); 965 [[nodiscard]] bool emitSelfHostedIteratorClose(CallNode* callNode); 966 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructor(CallNode* callNode); 967 [[nodiscard]] bool emitSelfHostedGetBuiltinPrototype(CallNode* callNode); 968 [[nodiscard]] bool emitSelfHostedGetBuiltinSymbol(CallNode* callNode); 969 [[nodiscard]] bool emitSelfHostedSetIsInlinableLargeFunction( 970 CallNode* callNode); 971 [[nodiscard]] bool emitSelfHostedSetCanonicalName(CallNode* callNode); 972 [[nodiscard]] bool emitSelfHostedArgumentsLength(CallNode* callNode); 973 [[nodiscard]] bool emitSelfHostedGetArgument(CallNode* callNode); 974 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 975 enum class DisposalKind : bool { Sync, Async }; 976 [[nodiscard]] bool emitSelfHostedDisposeResources(CallNode* callNode, 977 DisposalKind kind); 978 #endif 979 #ifdef DEBUG 980 void assertSelfHostedExpectedTopLevel(ParseNode* node); 981 void assertSelfHostedUnsafeGetReservedSlot(ListNode* argsList); 982 void assertSelfHostedUnsafeSetReservedSlot(ListNode* argsList); 983 #endif 984 985 [[nodiscard]] bool emitDo(BinaryNode* doNode); 986 [[nodiscard]] bool emitWhile(BinaryNode* whileNode); 987 988 [[nodiscard]] bool emitFor( 989 ForNode* forNode, const EmitterScope* headLexicalEmitterScope = nullptr); 990 [[nodiscard]] bool emitCStyleFor(ForNode* forNode, 991 const EmitterScope* headLexicalEmitterScope); 992 [[nodiscard]] bool emitForIn(ForNode* forNode, 993 const EmitterScope* headLexicalEmitterScope); 994 [[nodiscard]] bool emitForOf(ForNode* forNode, 995 const EmitterScope* headLexicalEmitterScope); 996 997 [[nodiscard]] bool emitInitializeForInOrOfTarget(TernaryNode* forHead); 998 999 [[nodiscard]] bool emitBreak(TaggedParserAtomIndex label); 1000 [[nodiscard]] bool emitContinue(TaggedParserAtomIndex label); 1001 1002 [[nodiscard]] bool emitFunctionFormalParameters(ParamsBodyNode* paramsBody); 1003 [[nodiscard]] bool emitInitializeFunctionSpecialNames(); 1004 [[nodiscard]] bool emitLexicalInitialization(NameNode* name); 1005 [[nodiscard]] bool emitLexicalInitialization(TaggedParserAtomIndex name); 1006 1007 // Emit bytecode for the array spread operator. 1008 // 1009 // emitSpread expects some values representing the spread target (an array), 1010 // the iterator and its next() method to be on the stack in that order 1011 // (iterator's next() on the bottom). 1012 // When emitSpread() finishes, the stack only contains the spread target and 1013 // the final index. 1014 [[nodiscard]] bool emitSpread(SelfHostedIter selfHostedIter); 1015 1016 enum class ClassNameKind { 1017 // The class name is defined through its BindingIdentifier, if present. 1018 BindingName, 1019 1020 // The class is anonymous and has a statically inferred name. 1021 InferredName, 1022 1023 // The class is anonymous and has a dynamically computed name. 1024 ComputedName 1025 }; 1026 1027 [[nodiscard]] bool emitClass( 1028 ClassNode* classNode, ClassNameKind nameKind = ClassNameKind::BindingName, 1029 TaggedParserAtomIndex nameForAnonymousClass = 1030 TaggedParserAtomIndex::null()); 1031 1032 [[nodiscard]] bool emitSuperElemOperands( 1033 PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get); 1034 [[nodiscard]] bool emitSuperGetElem(PropertyByValue* elem, 1035 bool isCall = false); 1036 1037 [[nodiscard]] bool emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, 1038 CallOrNewEmitter& cone); 1039 1040 [[nodiscard]] bool emitOptionalCalleeAndThis(ParseNode* callee, 1041 CallNode* call, 1042 CallOrNewEmitter& cone, 1043 OptionalEmitter& oe); 1044 1045 [[nodiscard]] bool emitExportDefault(BinaryNode* exportNode); 1046 1047 [[nodiscard]] bool emitReturnRval() { return emit1(JSOp::RetRval); } 1048 1049 [[nodiscard]] bool emitCheckPrivateField(ThrowCondition throwCondition, 1050 ThrowMsgKind msgKind) { 1051 return emit3(JSOp::CheckPrivateField, uint8_t(throwCondition), 1052 uint8_t(msgKind)); 1053 } 1054 1055 [[nodiscard]] bool emitNewPrivateName(TaggedParserAtomIndex bindingName, 1056 TaggedParserAtomIndex symbolName); 1057 1058 template <class ClassMemberType> 1059 [[nodiscard]] bool emitNewPrivateNames(ListNode* classMembers); 1060 1061 [[nodiscard]] bool emitNewPrivateNames(TaggedParserAtomIndex privateBrandName, 1062 ListNode* classMembers); 1063 1064 [[nodiscard]] js::UniquePtr<ImmutableScriptData> createImmutableScriptData(); 1065 1066 #if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) 1067 [[nodiscard]] bool emitCheckIsCallable(); 1068 #endif 1069 1070 private: 1071 [[nodiscard]] SelfHostedIter getSelfHostedIterFor(ParseNode* parseNode) const; 1072 1073 [[nodiscard]] bool emitSelfHostedGetBuiltinConstructorOrPrototype( 1074 CallNode* callNode, bool isConstructor); 1075 1076 public: 1077 #if defined(DEBUG) || defined(JS_JITSPEW) 1078 void dumpAtom(TaggedParserAtomIndex index) const; 1079 #endif 1080 }; 1081 1082 class MOZ_RAII AutoCheckUnstableEmitterScope { 1083 #ifdef DEBUG 1084 bool prev_; 1085 BytecodeEmitter* bce_; 1086 #endif 1087 1088 public: 1089 AutoCheckUnstableEmitterScope() = delete; 1090 explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce) 1091 #ifdef DEBUG 1092 : bce_(bce) 1093 #endif 1094 { 1095 #ifdef DEBUG 1096 prev_ = bce_->unstableEmitterScope; 1097 bce_->unstableEmitterScope = true; 1098 #endif 1099 } 1100 ~AutoCheckUnstableEmitterScope() { 1101 #ifdef DEBUG 1102 bce_->unstableEmitterScope = prev_; 1103 #endif 1104 } 1105 }; 1106 1107 } /* namespace frontend */ 1108 } /* namespace js */ 1109 1110 #endif /* frontend_BytecodeEmitter_h */