LCOV - code coverage report
Current view: top level - js/src/frontend - BytecodeEmitter.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 107 20.6 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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/Attributes.h"
      13             : 
      14             : #include "ds/InlineTable.h"
      15             : #include "frontend/BCEParserHandle.h"
      16             : #include "frontend/EitherParser.h"
      17             : #include "frontend/SharedContext.h"
      18             : #include "frontend/SourceNotes.h"
      19             : #include "vm/BytecodeUtil.h"
      20             : #include "vm/Interpreter.h"
      21             : #include "vm/Iteration.h"
      22             : #include "vm/JSContext.h"
      23             : #include "vm/JSScript.h"
      24             : 
      25             : namespace js {
      26             : namespace frontend {
      27             : 
      28           0 : class CGConstList {
      29             :     Vector<Value> list;
      30             :   public:
      31           0 :     explicit CGConstList(JSContext* cx) : list(cx) {}
      32           0 :     MOZ_MUST_USE bool append(const Value& v) {
      33           0 :         MOZ_ASSERT_IF(v.isString(), v.toString()->isAtom());
      34           0 :         return list.append(v);
      35             :     }
      36           0 :     size_t length() const { return list.length(); }
      37             :     void finish(ConstArray* array);
      38             : };
      39             : 
      40             : struct CGObjectList {
      41             :     uint32_t            length;     /* number of emitted so far objects */
      42             :     ObjectBox*          lastbox;   /* last emitted object */
      43             : 
      44           0 :     CGObjectList() : length(0), lastbox(nullptr) {}
      45             : 
      46             :     unsigned add(ObjectBox* objbox);
      47             :     void finish(ObjectArray* array);
      48             : };
      49             : 
      50           0 : struct MOZ_STACK_CLASS CGScopeList {
      51             :     Rooted<GCVector<Scope*>> vector;
      52             : 
      53           0 :     explicit CGScopeList(JSContext* cx)
      54           0 :       : vector(cx, GCVector<Scope*>(cx))
      55           0 :     { }
      56             : 
      57           0 :     bool append(Scope* scope) { return vector.append(scope); }
      58           0 :     uint32_t length() const { return vector.length(); }
      59             :     void finish(ScopeArray* array);
      60             : };
      61             : 
      62           0 : struct CGTryNoteList {
      63             :     Vector<JSTryNote> list;
      64           0 :     explicit CGTryNoteList(JSContext* cx) : list(cx) {}
      65             : 
      66             :     MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
      67           0 :     size_t length() const { return list.length(); }
      68             :     void finish(TryNoteArray* array);
      69             : };
      70             : 
      71             : struct CGScopeNote : public ScopeNote
      72             : {
      73             :     // The end offset. Used to compute the length; may need adjusting first if
      74             :     // in the prologue.
      75             :     uint32_t end;
      76             : 
      77             :     // Is the start offset in the prologue?
      78             :     bool startInPrologue;
      79             : 
      80             :     // Is the end offset in the prologue?
      81             :     bool endInPrologue;
      82             : };
      83             : 
      84           0 : struct CGScopeNoteList {
      85             :     Vector<CGScopeNote> list;
      86           0 :     explicit CGScopeNoteList(JSContext* cx) : list(cx) {}
      87             : 
      88             :     MOZ_MUST_USE bool append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
      89             :                              uint32_t parent);
      90             :     void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
      91           0 :     size_t length() const { return list.length(); }
      92             :     void finish(ScopeNoteArray* array, uint32_t prologueLength);
      93             : };
      94             : 
      95           0 : struct CGYieldAndAwaitOffsetList {
      96             :     Vector<uint32_t> list;
      97             :     uint32_t numYields;
      98             :     uint32_t numAwaits;
      99           0 :     explicit CGYieldAndAwaitOffsetList(JSContext* cx) : list(cx), numYields(0), numAwaits(0) {}
     100             : 
     101           0 :     MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
     102           0 :     size_t length() const { return list.length(); }
     103             :     void finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength);
     104             : };
     105             : 
     106             : // Have a few inline elements, so as to avoid heap allocation for tiny
     107             : // sequences.  See bug 1390526.
     108             : typedef Vector<jsbytecode, 64> BytecodeVector;
     109             : typedef Vector<jssrcnote, 64> SrcNotesVector;
     110             : 
     111             : // Linked list of jump instructions that need to be patched. The linked list is
     112             : // stored in the bytes of the incomplete bytecode that will be patched, so no
     113             : // extra memory is needed, and patching the instructions destroys the list.
     114             : //
     115             : // Example:
     116             : //
     117             : //     JumpList brList;
     118             : //     if (!emitJump(JSOP_IFEQ, &brList))
     119             : //         return false;
     120             : //     ...
     121             : //     JumpTarget label;
     122             : //     if (!emitJumpTarget(&label))
     123             : //         return false;
     124             : //     ...
     125             : //     if (!emitJump(JSOP_GOTO, &brList))
     126             : //         return false;
     127             : //     ...
     128             : //     patchJumpsToTarget(brList, label);
     129             : //
     130             : //                 +-> -1
     131             : //                 |
     132             : //                 |
     133             : //    ifeq ..   <+ +                +-+   ifeq ..
     134             : //    ..         |                  |     ..
     135             : //  label:       |                  +-> label:
     136             : //    jumptarget |                  |     jumptarget
     137             : //    ..         |                  |     ..
     138             : //    goto .. <+ +                  +-+   goto .. <+
     139             : //             |                                   |
     140             : //             |                                   |
     141             : //             +                                   +
     142             : //           brList                              brList
     143             : //
     144             : //       |                                  ^
     145             : //       +------- patchJumpsToTarget -------+
     146             : //
     147             : 
     148             : // Offset of a jump target instruction, used for patching jump instructions.
     149             : struct JumpTarget {
     150             :     ptrdiff_t offset;
     151             : };
     152             : 
     153             : struct JumpList {
     154             :     // -1 is used to mark the end of jump lists.
     155           0 :     JumpList() : offset(-1) {}
     156             :     ptrdiff_t offset;
     157             : 
     158             :     // Add a jump instruction to the list.
     159             :     void push(jsbytecode* code, ptrdiff_t jumpOffset);
     160             : 
     161             :     // Patch all jump instructions in this list to jump to `target`.  This
     162             :     // clobbers the list.
     163             :     void patchAll(jsbytecode* code, JumpTarget target);
     164             : };
     165             : 
     166             : // Used to control whether JSOP_CALL_IGNORES_RV is emitted for function calls.
     167             : enum class ValueUsage {
     168             :     // Assume the value of the current expression may be used. This is always
     169             :     // correct but prohibits JSOP_CALL_IGNORES_RV.
     170             :     WantValue,
     171             : 
     172             :     // Pass this when emitting an expression if the expression's value is
     173             :     // definitely unused by later instructions. You must make sure the next
     174             :     // instruction is JSOP_POP, a jump to a JSOP_POP, or something similar.
     175             :     IgnoreValue
     176             : };
     177             : 
     178           0 : struct MOZ_STACK_CLASS BytecodeEmitter
     179             : {
     180             :     class TDZCheckCache;
     181             :     class NestableControl;
     182             :     class EmitterScope;
     183             : 
     184             :     SharedContext* const sc;      /* context shared between parsing and bytecode generation */
     185             : 
     186             :     JSContext* const cx;
     187             : 
     188             :     BytecodeEmitter* const parent;  /* enclosing function or global context */
     189             : 
     190             :     Rooted<JSScript*> script;       /* the JSScript we're ultimately producing */
     191             : 
     192             :     Rooted<LazyScript*> lazyScript; /* the lazy script if mode is LazyFunction,
     193             :                                         nullptr otherwise. */
     194             : 
     195           0 :     struct EmitSection {
     196             :         BytecodeVector code;        /* bytecode */
     197             :         SrcNotesVector notes;       /* source notes, see below */
     198             :         ptrdiff_t   lastNoteOffset; /* code offset for last source note */
     199             : 
     200             :         // Line number for srcnotes.
     201             :         //
     202             :         // WARNING: If this becomes out of sync with already-emitted srcnotes,
     203             :         // we can get undefined behavior.
     204             :         uint32_t    currentLine;
     205             : 
     206             :         // Zero-based column index on currentLine of last SRC_COLSPAN-annotated
     207             :         // opcode.
     208             :         //
     209             :         // WARNING: If this becomes out of sync with already-emitted srcnotes,
     210             :         // we can get undefined behavior.
     211             :         uint32_t    lastColumn;
     212             : 
     213             :         JumpTarget lastTarget;      // Last jump target emitted.
     214             : 
     215             :         EmitSection(JSContext* cx, uint32_t lineNum)
     216           0 :           : code(cx), notes(cx), lastNoteOffset(0), currentLine(lineNum), lastColumn(0),
     217           0 :             lastTarget{ -1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH) }
     218             :         {}
     219             :     };
     220             :     EmitSection prologue, main, *current;
     221             : 
     222             :     // Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be initialized.
     223             :     // Use |parser| instead.
     224             :     mozilla::Maybe<EitherParser> ep_;
     225             :     BCEParserHandle *parser;
     226             : 
     227             :     PooledMapPtr<AtomIndexMap> atomIndices; /* literals indexed for mapping */
     228             :     unsigned        firstLine;      /* first line, for JSScript::initFromEmitter */
     229             : 
     230             :     uint32_t        maxFixedSlots;  /* maximum number of fixed frame slots so far */
     231             :     uint32_t        maxStackDepth;  /* maximum number of expression stack slots so far */
     232             : 
     233             :     int32_t         stackDepth;     /* current stack depth in script frame */
     234             : 
     235             :     unsigned        emitLevel;      /* emitTree recursion level */
     236             : 
     237             :     uint32_t        bodyScopeIndex; /* index into scopeList of the body scope */
     238             : 
     239             :     EmitterScope*    varEmitterScope;
     240             :     NestableControl* innermostNestableControl;
     241             :     EmitterScope*    innermostEmitterScope_;
     242             :     TDZCheckCache*   innermostTDZCheckCache;
     243             : 
     244             : #ifdef DEBUG
     245             :     bool unstableEmitterScope;
     246             : 
     247             :     friend class AutoCheckUnstableEmitterScope;
     248             : #endif
     249             : 
     250           0 :     EmitterScope* innermostEmitterScope() const {
     251           0 :         MOZ_ASSERT(!unstableEmitterScope);
     252           0 :         return innermostEmitterScopeNoCheck();
     253             :     }
     254             :     EmitterScope* innermostEmitterScopeNoCheck() const {
     255             :         return innermostEmitterScope_;
     256             :     }
     257             : 
     258             :     CGConstList      constList;      /* constants to be included with the script */
     259             :     CGObjectList     objectList;     /* list of emitted objects */
     260             :     CGScopeList      scopeList;      /* list of emitted scopes */
     261             :     CGTryNoteList    tryNoteList;    /* list of emitted try notes */
     262             :     CGScopeNoteList  scopeNoteList;  /* list of emitted block scope notes */
     263             : 
     264             :     /*
     265             :      * For each yield or await op, map the yield and await index (stored as
     266             :      * bytecode operand) to the offset of the next op.
     267             :      */
     268             :     CGYieldAndAwaitOffsetList yieldAndAwaitOffsetList;
     269             : 
     270             :     uint16_t        typesetCount;   /* Number of JOF_TYPESET opcodes generated */
     271             : 
     272             :     bool            hasSingletons:1;    /* script contains singleton initializer JSOP_OBJECT */
     273             : 
     274             :     bool            hasTryFinally:1;    /* script contains finally block */
     275             : 
     276             :     bool            emittingRunOnceLambda:1; /* true while emitting a lambda which is only
     277             :                                                 expected to run once. */
     278             : 
     279             :     bool isRunOnceLambda();
     280             : 
     281             :     enum EmitterMode {
     282             :         Normal,
     283             : 
     284             :         /*
     285             :          * Emit JSOP_GETINTRINSIC instead of JSOP_GETNAME and assert that
     286             :          * JSOP_GETNAME and JSOP_*GNAME don't ever get emitted. See the comment
     287             :          * for the field |selfHostingMode| in Parser.h for details.
     288             :          */
     289             :         SelfHosting,
     290             : 
     291             :         /*
     292             :          * Check the static scope chain of the root function for resolving free
     293             :          * variable accesses in the script.
     294             :          */
     295             :         LazyFunction
     296             :     };
     297             : 
     298             :     const EmitterMode emitterMode;
     299             : 
     300             :     MOZ_INIT_OUTSIDE_CTOR uint32_t scriptStartOffset;
     301             :     bool scriptStartOffsetSet;
     302             : 
     303             :     // The end location of a function body that is being emitted.
     304             :     MOZ_INIT_OUTSIDE_CTOR uint32_t functionBodyEndPos;
     305             :     // Whether functionBodyEndPos was set.
     306             :     bool functionBodyEndPosSet;
     307             : 
     308             :     /*
     309             :      * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
     310             :      * space above their tempMark points. This means that you cannot alloc from
     311             :      * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
     312             :      * destruction.
     313             :      */
     314             :   private:
     315             :     // Internal constructor, for delegation use only.
     316             :     BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc, HandleScript script,
     317             :                     Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode);
     318             : 
     319             :     void initFromBodyPosition(TokenPos bodyPosition);
     320             : 
     321             :   public:
     322             : 
     323             :     BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* parser, SharedContext* sc,
     324             :                     HandleScript script, Handle<LazyScript*> lazyScript, uint32_t lineNum,
     325             :                     EmitterMode emitterMode = Normal);
     326             : 
     327             :     BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser, SharedContext* sc,
     328             :                     HandleScript script, Handle<LazyScript*> lazyScript, uint32_t lineNum,
     329             :                     EmitterMode emitterMode = Normal);
     330             : 
     331             :     template<typename CharT>
     332           0 :     BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, CharT>* parser,
     333             :                     SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript,
     334             :                     uint32_t lineNum, EmitterMode emitterMode = Normal)
     335             :       : BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript,
     336           0 :                         lineNum, emitterMode)
     337           0 :     {}
     338             : 
     339             :     // An alternate constructor that uses a TokenPos for the starting
     340             :     // line and that sets functionBodyEndPos as well.
     341           0 :     BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* parser, SharedContext* sc,
     342             :                     HandleScript script, Handle<LazyScript*> lazyScript, TokenPos bodyPosition,
     343             :                     EmitterMode emitterMode = Normal)
     344           0 :         : BytecodeEmitter(parent, parser, sc, script, lazyScript,
     345           0 :                           parser->errorReporter().lineAt(bodyPosition.begin),
     346           0 :                           emitterMode)
     347             :     {
     348           0 :         initFromBodyPosition(bodyPosition);
     349           0 :     }
     350             : 
     351           0 :     BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser, SharedContext* sc,
     352             :                     HandleScript script, Handle<LazyScript*> lazyScript, TokenPos bodyPosition,
     353             :                     EmitterMode emitterMode = Normal)
     354           0 :         : BytecodeEmitter(parent, parser, sc, script, lazyScript,
     355           0 :                           parser.errorReporter().lineAt(bodyPosition.begin),
     356           0 :                           emitterMode)
     357             :     {
     358           0 :         initFromBodyPosition(bodyPosition);
     359           0 :     }
     360             : 
     361             :     template<typename CharT>
     362           0 :     BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, CharT>* parser,
     363             :                     SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript,
     364             :                     TokenPos bodyPosition, EmitterMode emitterMode = Normal)
     365             :       : BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript,
     366           0 :                         bodyPosition, emitterMode)
     367           0 :     {}
     368             : 
     369             :     MOZ_MUST_USE bool init();
     370             : 
     371             :     template <typename T>
     372             :     T* findInnermostNestableControl() const;
     373             : 
     374             :     template <typename T, typename Predicate /* (T*) -> bool */>
     375             :     T* findInnermostNestableControl(Predicate predicate) const;
     376             : 
     377             :     NameLocation lookupName(JSAtom* name);
     378             : 
     379             :     // To implement Annex B and the formal parameter defaults scope semantics
     380             :     // requires accessing names that would otherwise be shadowed. This method
     381             :     // returns the access location of a name that is known to be bound in a
     382             :     // target scope.
     383             :     mozilla::Maybe<NameLocation> locationOfNameBoundInScope(JSAtom* name, EmitterScope* target);
     384             : 
     385             :     // Get the location of a name known to be bound in the function scope,
     386             :     // starting at the source scope.
     387             :     mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(JSAtom* name,
     388             :                                                                     EmitterScope* source);
     389             : 
     390             :     mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(JSAtom* name) {
     391           0 :         return locationOfNameBoundInFunctionScope(name, innermostEmitterScope());
     392             :     }
     393             : 
     394           0 :     void setVarEmitterScope(EmitterScope* emitterScope) {
     395           0 :         MOZ_ASSERT(emitterScope);
     396           0 :         MOZ_ASSERT(!varEmitterScope);
     397           0 :         varEmitterScope = emitterScope;
     398           0 :     }
     399             : 
     400           0 :     Scope* outermostScope() const { return scopeList.vector[0]; }
     401             :     Scope* innermostScope() const;
     402             : 
     403             :     MOZ_ALWAYS_INLINE
     404           0 :     MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, uint32_t* indexp) {
     405           0 :         MOZ_ASSERT(atomIndices);
     406           0 :         AtomIndexMap::AddPtr p = atomIndices->lookupForAdd(atom);
     407           0 :         if (p) {
     408           0 :             *indexp = p->value();
     409           0 :             return true;
     410             :         }
     411             : 
     412           0 :         uint32_t index = atomIndices->count();
     413           0 :         if (!atomIndices->add(p, atom, index)) {
     414           0 :             ReportOutOfMemory(cx);
     415           0 :             return false;
     416             :         }
     417             : 
     418           0 :         *indexp = index;
     419           0 :         return true;
     420             :     }
     421             : 
     422             :     bool isInLoop();
     423             :     MOZ_MUST_USE bool checkSingletonContext();
     424             : 
     425             :     // Check whether our function is in a run-once context (a toplevel
     426             :     // run-one script or a run-once lambda).
     427             :     MOZ_MUST_USE bool checkRunOnceContext();
     428             : 
     429             :     bool needsImplicitThis();
     430             : 
     431             :     void tellDebuggerAboutCompiledScript(JSContext* cx);
     432             : 
     433           0 :     BytecodeVector& code() const { return current->code; }
     434           0 :     jsbytecode* code(ptrdiff_t offset) const { return current->code.begin() + offset; }
     435           0 :     ptrdiff_t offset() const { return current->code.end() - current->code.begin(); }
     436           0 :     ptrdiff_t prologueOffset() const { return prologue.code.end() - prologue.code.begin(); }
     437           0 :     void switchToMain() { current = &main; }
     438           0 :     void switchToPrologue() { current = &prologue; }
     439           0 :     bool inPrologue() const { return current == &prologue; }
     440             : 
     441           0 :     SrcNotesVector& notes() const {
     442             :         // Prologue shouldn't have source notes.
     443           0 :         MOZ_ASSERT(!inPrologue());
     444      699259 :         return current->notes;
     445             :     }
     446      515023 :     ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
     447           0 :     unsigned currentLine() const { return current->currentLine; }
     448             : 
     449             :     // Check if the last emitted opcode is a jump target.
     450             :     bool lastOpcodeIsJumpTarget() const {
     451         397 :         return offset() - current->lastTarget.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
     452             :     }
     453             : 
     454             :     // JumpTarget should not be part of the emitted statement, as they can be
     455             :     // aliased by multiple statements. If we included the jump target as part of
     456             :     // the statement we might have issues where the enclosing statement might
     457             :     // not contain all the opcodes of the enclosed statements.
     458         397 :     ptrdiff_t lastNonJumpTargetOffset() const {
     459           0 :         return lastOpcodeIsJumpTarget() ? current->lastTarget.offset : offset();
     460             :     }
     461             : 
     462             :     void setFunctionBodyEndPos(TokenPos pos) {
     463       25676 :         functionBodyEndPos = pos.end;
     464           0 :         functionBodyEndPosSet = true;
     465             :     }
     466             : 
     467             :     void setScriptStartOffsetIfUnset(TokenPos pos) {
     468       25676 :         if (!scriptStartOffsetSet) {
     469       13448 :             scriptStartOffset = pos.begin;
     470       13448 :             scriptStartOffsetSet = true;
     471             :         }
     472             :     }
     473             : 
     474             :     void reportError(ParseNode* pn, unsigned errorNumber, ...);
     475             :     bool reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...);
     476             : 
     477             :     // If pn contains a useful expression, return true with *answer set to true.
     478             :     // If pn contains a useless expression, return true with *answer set to
     479             :     // false. Return false on error.
     480             :     //
     481             :     // The caller should initialize *answer to false and invoke this function on
     482             :     // an expression statement or similar subtree to decide whether the tree
     483             :     // could produce code that has any side effects.  For an expression
     484             :     // statement, we define useless code as code with no side effects, because
     485             :     // the main effect, the value left on the stack after the code executes,
     486             :     // will be discarded by a pop bytecode.
     487             :     MOZ_MUST_USE bool checkSideEffects(ParseNode* pn, bool* answer);
     488             : 
     489             : #ifdef DEBUG
     490             :     MOZ_MUST_USE bool checkStrictOrSloppy(JSOp op);
     491             : #endif
     492             : 
     493             :     // Append a new source note of the given type (and therefore size) to the
     494             :     // notes dynamic array, updating noteCount. Return the new note's index
     495             :     // within the array pointed at by current->notes as outparam.
     496             :     MOZ_MUST_USE bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
     497             :     MOZ_MUST_USE bool newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp = nullptr);
     498             :     MOZ_MUST_USE bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
     499             :                                   unsigned* indexp = nullptr);
     500             : 
     501             :     void copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes);
     502             :     MOZ_MUST_USE bool setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset);
     503             : 
     504             :     // NB: this function can add at most one extra extended delta note.
     505             :     MOZ_MUST_USE bool addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta);
     506             : 
     507             :     // Finish taking source notes in cx's notePool. If successful, the final
     508             :     // source note count is stored in the out outparam.
     509             :     MOZ_MUST_USE bool finishTakingSrcNotes(uint32_t* out);
     510             : 
     511             :     // Control whether emitTree emits a line number note.
     512             :     enum EmitLineNumberNote {
     513             :         EMIT_LINENOTE,
     514             :         SUPPRESS_LINENOTE
     515             :     };
     516             : 
     517             :     // Emit code for the tree rooted at pn.
     518             :     MOZ_MUST_USE bool emitTree(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue,
     519             :                                EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
     520             : 
     521             :     // Emit code for the tree rooted at pn with its own TDZ cache.
     522             :     MOZ_MUST_USE bool emitTreeInBranch(ParseNode* pn,
     523             :                                        ValueUsage valueUsage = ValueUsage::WantValue);
     524             : 
     525             :     // Emit global, eval, or module code for tree rooted at body. Always
     526             :     // encompasses the entire source.
     527             :     MOZ_MUST_USE bool emitScript(ParseNode* body);
     528             : 
     529             :     // Emit function code for the tree rooted at body.
     530             :     MOZ_MUST_USE bool emitFunctionScript(ParseNode* body);
     531             : 
     532             :     // If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
     533             :     // reserve a type set to store its result.
     534             :     void checkTypeSet(JSOp op);
     535             : 
     536             :     void updateDepth(ptrdiff_t target);
     537             :     MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
     538             :     MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
     539             : 
     540             :     JSOp strictifySetNameOp(JSOp op);
     541             : 
     542             :     MOZ_MUST_USE bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
     543             : 
     544             :     // Emit one bytecode.
     545             :     MOZ_MUST_USE bool emit1(JSOp op);
     546             : 
     547             :     // Emit two bytecodes, an opcode (op) with a byte of immediate operand
     548             :     // (op1).
     549             :     MOZ_MUST_USE bool emit2(JSOp op, uint8_t op1);
     550             : 
     551             :     // Emit three bytecodes, an opcode with two bytes of immediate operands.
     552             :     MOZ_MUST_USE bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
     553             : 
     554             :     // Helper to emit JSOP_DUPAT. The argument is the value's depth on the
     555             :     // JS stack, as measured from the top.
     556             :     MOZ_MUST_USE bool emitDupAt(unsigned slotFromTop);
     557             : 
     558             :     // Helper to emit JSOP_POP or JSOP_POPN.
     559             :     MOZ_MUST_USE bool emitPopN(unsigned n);
     560             : 
     561             :     // Helper to emit JSOP_CHECKISOBJ.
     562             :     MOZ_MUST_USE bool emitCheckIsObj(CheckIsObjectKind kind);
     563             : 
     564             :     // Helper to emit JSOP_CHECKISCALLABLE.
     565             :     MOZ_MUST_USE bool emitCheckIsCallable(CheckIsCallableKind kind);
     566             : 
     567             :     // Push whether the value atop of the stack is non-undefined and non-null.
     568             :     MOZ_MUST_USE bool emitPushNotUndefinedOrNull();
     569             : 
     570             :     // Emit a bytecode followed by an uint16 immediate operand stored in
     571             :     // big-endian order.
     572             :     MOZ_MUST_USE bool emitUint16Operand(JSOp op, uint32_t operand);
     573             : 
     574             :     // Emit a bytecode followed by an uint32 immediate operand.
     575             :     MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
     576             : 
     577             :     // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
     578             :     MOZ_MUST_USE bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
     579             : 
     580             :     MOZ_MUST_USE bool emitNumberOp(double dval);
     581             : 
     582             :     MOZ_MUST_USE bool emitThisLiteral(ParseNode* pn);
     583             :     MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
     584             :     MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn);
     585             :     MOZ_MUST_USE bool emitSetThis(ParseNode* pn);
     586             :     MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn();
     587             : 
     588             :     // Handle jump opcodes and jump targets.
     589             :     MOZ_MUST_USE bool emitJumpTarget(JumpTarget* target);
     590             :     MOZ_MUST_USE bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
     591             :     MOZ_MUST_USE bool emitJump(JSOp op, JumpList* jump);
     592             :     MOZ_MUST_USE bool emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump,
     593             :                                        JumpTarget* fallthrough);
     594             :     void patchJumpsToTarget(JumpList jump, JumpTarget target);
     595             :     MOZ_MUST_USE bool emitJumpTargetAndPatch(JumpList jump);
     596             : 
     597             :     MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
     598             :     MOZ_MUST_USE bool emitCallIncDec(ParseNode* incDec);
     599             : 
     600             :     MOZ_MUST_USE bool emitLoopHead(ParseNode* nextpn, JumpTarget* top);
     601             :     MOZ_MUST_USE bool emitLoopEntry(ParseNode* nextpn, JumpList entryJump);
     602             : 
     603             :     MOZ_MUST_USE bool emitGoto(NestableControl* target, JumpList* jumplist,
     604             :                                SrcNoteType noteType = SRC_NULL);
     605             : 
     606             :     MOZ_MUST_USE bool emitIndex32(JSOp op, uint32_t index);
     607             :     MOZ_MUST_USE bool emitIndexOp(JSOp op, uint32_t index);
     608             : 
     609             :     MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);
     610             :     MOZ_MUST_USE bool emitAtomOp(ParseNode* pn, JSOp op);
     611             : 
     612             :     MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
     613             :     MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count);
     614             : 
     615             :     MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
     616             :     MOZ_MUST_USE bool emitInternedObjectOp(uint32_t index, JSOp op);
     617             :     MOZ_MUST_USE bool emitObjectOp(ObjectBox* objbox, JSOp op);
     618             :     MOZ_MUST_USE bool emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op);
     619             :     MOZ_MUST_USE bool emitRegExp(uint32_t index);
     620             : 
     621             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
     622             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
     623             : 
     624             :     MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset);
     625             : 
     626             :     MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
     627             : 
     628             :     MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
     629             :                                        PropListType type);
     630             : 
     631             :     // To catch accidental misuse, emitUint16Operand/emit3 assert that they are
     632             :     // not used to unconditionally emit JSOP_GETLOCAL. Variable access should
     633             :     // instead be emitted using EmitVarOp. In special cases, when the caller
     634             :     // definitely knows that a given local slot is unaliased, this function may be
     635             :     // used as a non-asserting version of emitUint16Operand.
     636             :     MOZ_MUST_USE bool emitLocalOp(JSOp op, uint32_t slot);
     637             : 
     638             :     MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
     639             :     MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
     640             : 
     641             :     MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name, const NameLocation& loc,
     642             :                                             bool callContext = false);
     643             :     MOZ_MUST_USE bool emitGetNameAtLocationForCompoundAssignment(JSAtom* name,
     644             :                                                                  const NameLocation& loc);
     645      128581 :     MOZ_MUST_USE bool emitGetName(JSAtom* name, bool callContext = false) {
     646      257160 :         return emitGetNameAtLocation(name, lookupName(name), callContext);
     647             :     }
     648             :     MOZ_MUST_USE bool emitGetName(ParseNode* pn, bool callContext = false);
     649             : 
     650             :     template <typename RHSEmitter>
     651             :     MOZ_MUST_USE bool emitSetOrInitializeNameAtLocation(HandleAtom name, const NameLocation& loc,
     652             :                                                         RHSEmitter emitRhs, bool initialize);
     653             :     template <typename RHSEmitter>
     654       31125 :     MOZ_MUST_USE bool emitSetOrInitializeName(HandleAtom name, RHSEmitter emitRhs,
     655             :                                               bool initialize)
     656             :     {
     657           0 :         return emitSetOrInitializeNameAtLocation(name, lookupName(name), emitRhs, initialize);
     658             :     }
     659             :     template <typename RHSEmitter>
     660        5319 :     MOZ_MUST_USE bool emitSetName(ParseNode* pn, RHSEmitter emitRhs) {
     661       10638 :         RootedAtom name(cx, pn->name());
     662           0 :         return emitSetName(name, emitRhs);
     663             :     }
     664             :     template <typename RHSEmitter>
     665             :     MOZ_MUST_USE bool emitSetName(HandleAtom name, RHSEmitter emitRhs) {
     666           0 :         return emitSetOrInitializeName(name, emitRhs, false);
     667             :     }
     668             :     template <typename RHSEmitter>
     669       17464 :     MOZ_MUST_USE bool emitInitializeName(ParseNode* pn, RHSEmitter emitRhs) {
     670       34928 :         RootedAtom name(cx, pn->name());
     671           0 :         return emitInitializeName(name, emitRhs);
     672             :     }
     673             :     template <typename RHSEmitter>
     674             :     MOZ_MUST_USE bool emitInitializeName(HandleAtom name, RHSEmitter emitRhs) {
     675       25763 :         return emitSetOrInitializeName(name, emitRhs, true);
     676             :     }
     677             : 
     678             :     MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc);
     679             : 
     680             :     MOZ_MUST_USE bool emitNameIncDec(ParseNode* pn);
     681             : 
     682             :     MOZ_MUST_USE bool emitDeclarationList(ParseNode* decls);
     683             :     MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* decls, ParseNode* decl,
     684             :                                             ParseNode* initializer);
     685             : 
     686             :     MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
     687             :     MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
     688             : 
     689             :     MOZ_MUST_USE bool emitPrepareIteratorResult();
     690             :     MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
     691             :     MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
     692             : 
     693             :     MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() {
     694         782 :         return emitGetDotGeneratorInScope(*innermostEmitterScope());
     695             :     }
     696             :     MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope);
     697             : 
     698             :     MOZ_MUST_USE bool emitInitialYield(ParseNode* pn);
     699             :     MOZ_MUST_USE bool emitYield(ParseNode* pn);
     700             :     MOZ_MUST_USE bool emitYieldOp(JSOp op);
     701             :     MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
     702             :     MOZ_MUST_USE bool emitAwaitInInnermostScope() {
     703        1231 :         return emitAwaitInScope(*innermostEmitterScope());
     704             :     }
     705             :     MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn);
     706             :     MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope);
     707             : 
     708             :     MOZ_MUST_USE bool emitPropLHS(ParseNode* pn);
     709             :     MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op);
     710             :     MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
     711             : 
     712             :     MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow);
     713             :     MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
     714             :                                        bool isGenerator);
     715             : 
     716             :     MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName);
     717             : 
     718             :     // Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
     719             :     // opcode onto the stack in the right order. In the case of SETELEM, the
     720             :     // value to be assigned must already be pushed.
     721             :     enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign, Ref };
     722             :     MOZ_MUST_USE bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
     723             : 
     724             :     MOZ_MUST_USE bool emitElemOpBase(JSOp op);
     725             :     MOZ_MUST_USE bool emitElemOp(ParseNode* pn, JSOp op);
     726             :     MOZ_MUST_USE bool emitElemIncDec(ParseNode* pn);
     727             : 
     728             :     MOZ_MUST_USE bool emitCatch(ParseNode* pn);
     729             :     MOZ_MUST_USE bool emitIf(ParseNode* pn);
     730             :     MOZ_MUST_USE bool emitWith(ParseNode* pn);
     731             : 
     732             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn);
     733             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn);
     734             :     MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
     735             :                                            EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
     736             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(ParseNode* pn);
     737             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(ParseNode* pn);
     738             : 
     739             :     enum DestructuringFlavor {
     740             :         // Destructuring into a declaration.
     741             :         DestructuringDeclaration,
     742             : 
     743             :         // Destructuring into a formal parameter, when the formal parameters
     744             :         // contain an expression that might be evaluated, and thus require
     745             :         // this destructuring to assign not into the innermost scope that
     746             :         // contains the function body's vars, but into its enclosing scope for
     747             :         // parameter expressions.
     748             :         DestructuringFormalParameterInVarScope,
     749             : 
     750             :         // Destructuring as part of an AssignmentExpression.
     751             :         DestructuringAssignment
     752             :     };
     753             : 
     754             :     // emitDestructuringLHSRef emits the lhs expression's reference.
     755             :     // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|.
     756             :     // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|.
     757             :     // If there's nothing to evaluate for the reference, it emits nothing.
     758             :     // |emitted| parameter receives the number of values pushed onto the stack.
     759             :     MOZ_MUST_USE bool emitDestructuringLHSRef(ParseNode* target, size_t* emitted);
     760             : 
     761             :     // emitSetOrInitializeDestructuring assumes the lhs expression's reference
     762             :     // and the to-be-destructured value has been pushed on the stack.  It emits
     763             :     // code to destructure a single lhs expression (either a name or a compound
     764             :     // []/{} expression).
     765             :     MOZ_MUST_USE bool emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav);
     766             : 
     767             :     // emitDestructuringObjRestExclusionSet emits the property exclusion set
     768             :     // for the rest-property in an object pattern.
     769             :     MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ParseNode* pattern);
     770             : 
     771             :     // emitDestructuringOps assumes the to-be-destructured value has been
     772             :     // pushed on the stack and emits code to destructure each part of a [] or
     773             :     // {} lhs expression.
     774             :     MOZ_MUST_USE bool emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav);
     775             :     MOZ_MUST_USE bool emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav);
     776             :     MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav);
     777             : 
     778             :     enum class CopyOption {
     779             :         Filtered, Unfiltered
     780             :     };
     781             : 
     782             :     // Calls either the |CopyDataProperties| or the
     783             :     // |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or
     784             :     // two in the latter case) elements from the stack.
     785             :     MOZ_MUST_USE bool emitCopyDataProperties(CopyOption option);
     786             : 
     787             :     // emitIterator expects the iterable to already be on the stack.
     788             :     // It will replace that stack value with the corresponding iterator
     789             :     MOZ_MUST_USE bool emitIterator();
     790             : 
     791             :     MOZ_MUST_USE bool emitAsyncIterator();
     792             : 
     793             :     // Pops iterator from the top of the stack. Pushes the result of |.next()|
     794             :     // onto the stack.
     795             :     MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync,
     796             :                                        bool allowSelfHosted = false);
     797             :     MOZ_MUST_USE bool emitIteratorCloseInScope(EmitterScope& currentScope,
     798             :                                                IteratorKind iterKind = IteratorKind::Sync,
     799             :                                                CompletionKind completionKind = CompletionKind::Normal,
     800             :                                                bool allowSelfHosted = false);
     801             :     MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync,
     802             :                                                         CompletionKind completionKind = CompletionKind::Normal,
     803             :                                                         bool allowSelfHosted = false) {
     804         318 :         return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, completionKind,
     805         318 :                                         allowSelfHosted);
     806             :     }
     807             : 
     808             :     template <typename InnerEmitter>
     809             :     MOZ_MUST_USE bool wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth,
     810             :                                                                 InnerEmitter emitter);
     811             : 
     812             :     // Check if the value on top of the stack is "undefined". If so, replace
     813             :     // that value on the stack with the value defined by |defaultExpr|.
     814             :     // |pattern| is a lhs node of the default expression.  If it's an
     815             :     // identifier and |defaultExpr| is an anonymous function, |SetFunctionName|
     816             :     // is called at compile time.
     817             :     MOZ_MUST_USE bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern);
     818             : 
     819             :     MOZ_MUST_USE bool setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name);
     820             : 
     821             :     MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
     822             :     MOZ_MUST_USE bool emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern);
     823             : 
     824             :     MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn);
     825             :     MOZ_MUST_USE bool emitTemplateString(ParseNode* pn);
     826             :     MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rhs);
     827             : 
     828             :     MOZ_MUST_USE bool emitReturn(ParseNode* pn);
     829             :     MOZ_MUST_USE bool emitExpressionStatement(ParseNode* pn);
     830             :     MOZ_MUST_USE bool emitStatementList(ParseNode* pn);
     831             : 
     832             :     MOZ_MUST_USE bool emitDeleteName(ParseNode* pn);
     833             :     MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn);
     834             :     MOZ_MUST_USE bool emitDeleteElement(ParseNode* pn);
     835             :     MOZ_MUST_USE bool emitDeleteExpression(ParseNode* pn);
     836             : 
     837             :     // |op| must be JSOP_TYPEOF or JSOP_TYPEOFEXPR.
     838             :     MOZ_MUST_USE bool emitTypeof(ParseNode* node, JSOp op);
     839             : 
     840             :     MOZ_MUST_USE bool emitUnary(ParseNode* pn);
     841             :     MOZ_MUST_USE bool emitRightAssociative(ParseNode* pn);
     842             :     MOZ_MUST_USE bool emitLeftAssociative(ParseNode* pn);
     843             :     MOZ_MUST_USE bool emitLogical(ParseNode* pn);
     844             :     MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn,
     845             :                                        ValueUsage valueUsage = ValueUsage::WantValue);
     846             : 
     847             :     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn);
     848             : 
     849             :     MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional,
     850             :                                                 ValueUsage valueUsage = ValueUsage::WantValue);
     851             : 
     852             :     bool isRestParameter(ParseNode* pn);
     853             : 
     854             :     MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue);
     855             :     MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn);
     856             :     MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn);
     857             :     MOZ_MUST_USE bool emitSelfHostedForceInterpreter();
     858             :     MOZ_MUST_USE bool emitSelfHostedAllowContentIter(ParseNode* pn);
     859             :     MOZ_MUST_USE bool emitSelfHostedDefineDataProperty(ParseNode* pn);
     860             :     MOZ_MUST_USE bool emitSelfHostedGetPropertySuper(ParseNode* pn);
     861             :     MOZ_MUST_USE bool emitSelfHostedHasOwn(ParseNode* pn);
     862             : 
     863             :     MOZ_MUST_USE bool emitDo(ParseNode* pn);
     864             :     MOZ_MUST_USE bool emitWhile(ParseNode* pn);
     865             : 
     866             :     MOZ_MUST_USE bool emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope = nullptr);
     867             :     MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
     868             :     MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
     869             :     MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
     870             : 
     871             :     MOZ_MUST_USE bool emitInitializeForInOrOfTarget(ParseNode* forHead);
     872             : 
     873             :     MOZ_MUST_USE bool emitBreak(PropertyName* label);
     874             :     MOZ_MUST_USE bool emitContinue(PropertyName* label);
     875             : 
     876             :     MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ParseNode* pn);
     877             :     MOZ_MUST_USE bool emitFunctionFormalParameters(ParseNode* pn);
     878             :     MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
     879             :     MOZ_MUST_USE bool emitFunctionBody(ParseNode* pn);
     880             :     MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn);
     881             : 
     882             :     // Emit bytecode for the spread operator.
     883             :     //
     884             :     // emitSpread expects the current index (I) of the array, the array itself
     885             :     // and the iterator to be on the stack in that order (iterator on the bottom).
     886             :     // It will pop the iterator and I, then iterate over the iterator by calling
     887             :     // |.next()| and put the results into the I-th element of array with
     888             :     // incrementing I, then push the result I (it will be original I +
     889             :     // iteration count). The stack after iteration will look like |ARRAY INDEX|.
     890             :     MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false);
     891             : 
     892             :     MOZ_MUST_USE bool emitClass(ParseNode* pn);
     893             :     MOZ_MUST_USE bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
     894             :     MOZ_MUST_USE bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
     895             :     MOZ_MUST_USE bool emitSuperElemOperands(ParseNode* pn,
     896             :                                             EmitElemOption opts = EmitElemOption::Get);
     897             :     MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
     898             : 
     899             :     MOZ_MUST_USE bool emitCallee(ParseNode* callee, ParseNode* call, bool* callop);
     900             : 
     901             :     MOZ_MUST_USE bool emitPipeline(ParseNode* pn);
     902             : 
     903             :     MOZ_MUST_USE bool emitExportDefault(ParseNode* pn);
     904             : };
     905             : 
     906             : class MOZ_RAII AutoCheckUnstableEmitterScope {
     907             : #ifdef DEBUG
     908             :     bool prev_;
     909             :     BytecodeEmitter* bce_;
     910             : #endif
     911             : 
     912             :   public:
     913             :     AutoCheckUnstableEmitterScope() = delete;
     914             :     explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce)
     915             : #ifdef DEBUG
     916           0 :       : bce_(bce)
     917             : #endif
     918             :     {
     919             : #ifdef DEBUG
     920       12846 :         prev_ = bce_->unstableEmitterScope;
     921       12846 :         bce_->unstableEmitterScope = true;
     922             : #endif
     923             :     }
     924             :     ~AutoCheckUnstableEmitterScope() {
     925             : #ifdef DEBUG
     926             :         bce_->unstableEmitterScope = prev_;
     927             : #endif
     928             :     }
     929             : };
     930             : 
     931             : } /* namespace frontend */
     932             : } /* namespace js */
     933             : 
     934             : #endif /* frontend_BytecodeEmitter_h */

Generated by: LCOV version 1.13-14-ga5dd952