tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */