LCOV - code coverage report
Current view: top level - js/src/frontend - BytecodeEmitter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 2182 4180 52.2 %
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             : /*
       8             :  * JS bytecode generation.
       9             :  */
      10             : 
      11             : #include "frontend/BytecodeEmitter.h"
      12             : 
      13             : #include "mozilla/ArrayUtils.h"
      14             : #include "mozilla/DebugOnly.h"
      15             : #include "mozilla/FloatingPoint.h"
      16             : #include "mozilla/Maybe.h"
      17             : #include "mozilla/PodOperations.h"
      18             : 
      19             : #include <string.h>
      20             : 
      21             : #include "jsapi.h"
      22             : #include "jsnum.h"
      23             : #include "jstypes.h"
      24             : #include "jsutil.h"
      25             : 
      26             : #include "ds/Nestable.h"
      27             : #include "frontend/Parser.h"
      28             : #include "vm/BytecodeUtil.h"
      29             : #include "vm/Debugger.h"
      30             : #include "vm/GeneratorObject.h"
      31             : #include "vm/JSAtom.h"
      32             : #include "vm/JSContext.h"
      33             : #include "vm/JSFunction.h"
      34             : #include "vm/JSScript.h"
      35             : #include "vm/Stack.h"
      36             : #include "wasm/AsmJS.h"
      37             : 
      38             : #include "frontend/ParseNode-inl.h"
      39             : #include "vm/EnvironmentObject-inl.h"
      40             : #include "vm/JSAtom-inl.h"
      41             : #include "vm/JSScript-inl.h"
      42             : #include "vm/NativeObject-inl.h"
      43             : 
      44             : using namespace js;
      45             : using namespace js::gc;
      46             : using namespace js::frontend;
      47             : 
      48             : using mozilla::AssertedCast;
      49             : using mozilla::DebugOnly;
      50             : using mozilla::Maybe;
      51             : using mozilla::Nothing;
      52             : using mozilla::NumberEqualsInt32;
      53             : using mozilla::NumberIsInt32;
      54             : using mozilla::PodCopy;
      55             : using mozilla::Some;
      56             : using mozilla::Unused;
      57             : 
      58             : class BreakableControl;
      59             : class LabelControl;
      60             : class LoopControl;
      61             : class ForOfLoopControl;
      62             : class TryFinallyControl;
      63             : 
      64             : static bool
      65           0 : ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn)
      66             : {
      67             :     // The few node types listed below are exceptions to the usual
      68             :     // location-source-note-emitting code in BytecodeEmitter::emitTree().
      69             :     // Single-line `while` loops and C-style `for` loops require careful
      70             :     // handling to avoid strange stepping behavior.
      71             :     // Functions usually shouldn't have location information (bug 1431202).
      72             : 
      73           0 :     ParseNodeKind kind = pn->getKind();
      74           0 :     return kind == ParseNodeKind::While ||
      75           0 :            kind == ParseNodeKind::For ||
      76           0 :            kind == ParseNodeKind::Function;
      77             : }
      78             : 
      79             : // A cache that tracks Temporal Dead Zone (TDZ) checks, so that any use of a
      80             : // lexical variable that's dominated by an earlier use, or by evaluation of its
      81             : // declaration (which will initialize it, perhaps to |undefined|), doesn't have
      82             : // to redundantly check that the lexical variable has been initialized
      83             : //
      84             : // Each basic block should have a TDZCheckCache in scope. Some NestableControl
      85             : // subclasses contain a TDZCheckCache.
      86             : //
      87             : // When a scope containing lexical variables is entered, all such variables are
      88             : // marked as CheckTDZ.  When a lexical variable is accessed, its entry is
      89             : // checked.  If it's CheckTDZ, a JSOP_CHECKLEXICAL is emitted and then the
      90             : // entry is marked DontCheckTDZ.  If it's DontCheckTDZ, no check is emitted
      91             : // because a prior check would have already failed.  Finally, because
      92             : // evaluating a lexical variable declaration initializes it (after any
      93             : // initializer is evaluated), evaluating a lexical declaration marks its entry
      94             : // as DontCheckTDZ.
      95      147837 : class BytecodeEmitter::TDZCheckCache : public Nestable<BytecodeEmitter::TDZCheckCache>
      96             : {
      97             :     PooledMapPtr<CheckTDZMap> cache_;
      98             : 
      99             :     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
     100       69579 :         return cache_ || cache_.acquire(bce->cx);
     101             :     }
     102             : 
     103             :   public:
     104             :     explicit TDZCheckCache(BytecodeEmitter* bce)
     105       74835 :       : Nestable<TDZCheckCache>(&bce->innermostTDZCheckCache),
     106      299340 :         cache_(bce->cx->frontendCollectionPool())
     107             :     { }
     108             : 
     109             :     Maybe<MaybeCheckTDZ> needsTDZCheck(BytecodeEmitter* bce, JSAtom* name);
     110             :     MOZ_MUST_USE bool noteTDZCheck(BytecodeEmitter* bce, JSAtom* name, MaybeCheckTDZ check);
     111             : };
     112             : 
     113        3878 : class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::NestableControl>
     114             : {
     115             :     StatementKind kind_;
     116             : 
     117             :     // The innermost scope when this was pushed.
     118             :     EmitterScope* emitterScope_;
     119             : 
     120             :   protected:
     121             :     NestableControl(BytecodeEmitter* bce, StatementKind kind)
     122        3878 :       : Nestable<NestableControl>(&bce->innermostNestableControl),
     123             :         kind_(kind),
     124        7756 :         emitterScope_(bce->innermostEmitterScopeNoCheck())
     125             :     { }
     126             : 
     127             :   public:
     128             :     using Nestable<NestableControl>::enclosing;
     129             :     using Nestable<NestableControl>::findNearest;
     130             : 
     131             :     StatementKind kind() const {
     132             :         return kind_;
     133             :     }
     134             : 
     135             :     EmitterScope* emitterScope() const {
     136             :         return emitterScope_;
     137             :     }
     138             : 
     139             :     template <typename T>
     140             :     bool is() const;
     141             : 
     142             :     template <typename T>
     143        5743 :     T& as() {
     144           1 :         MOZ_ASSERT(this->is<T>());
     145        5743 :         return static_cast<T&>(*this);
     146             :     }
     147             : };
     148             : 
     149             : // Template specializations are disallowed in different namespaces; specialize
     150             : // all the NestableControl subtypes up front.
     151             : namespace js {
     152             : namespace frontend {
     153             : 
     154             : template <>
     155             : bool
     156           0 : BytecodeEmitter::NestableControl::is<BreakableControl>() const
     157             : {
     158           1 :     return StatementKindIsUnlabeledBreakTarget(kind_) || kind_ == StatementKind::Label;
     159             : }
     160             : 
     161             : template <>
     162             : bool
     163           0 : BytecodeEmitter::NestableControl::is<LabelControl>() const
     164             : {
     165           1 :     return kind_ == StatementKind::Label;
     166             : }
     167             : 
     168             : template <>
     169             : bool
     170           0 : BytecodeEmitter::NestableControl::is<LoopControl>() const
     171             : {
     172           1 :     return StatementKindIsLoop(kind_);
     173             : }
     174             : 
     175             : template <>
     176             : bool
     177           0 : BytecodeEmitter::NestableControl::is<ForOfLoopControl>() const
     178             : {
     179        1407 :     return kind_ == StatementKind::ForOfLoop;
     180             : }
     181             : 
     182             : template <>
     183             : bool
     184           0 : BytecodeEmitter::NestableControl::is<TryFinallyControl>() const
     185             : {
     186           0 :     return kind_ == StatementKind::Try || kind_ == StatementKind::Finally;
     187             : }
     188             : 
     189             : } // namespace frontend
     190             : } // namespace js
     191             : 
     192        5608 : class BreakableControl : public BytecodeEmitter::NestableControl
     193             : {
     194             :   public:
     195             :     // Offset of the last break.
     196             :     JumpList breaks;
     197             : 
     198        2804 :     BreakableControl(BytecodeEmitter* bce, StatementKind kind)
     199        8412 :       : NestableControl(bce, kind)
     200             :     {
     201        5608 :         MOZ_ASSERT(is<BreakableControl>());
     202        2804 :     }
     203             : 
     204             :     MOZ_MUST_USE bool patchBreaks(BytecodeEmitter* bce) {
     205        2561 :         return bce->emitJumpTargetAndPatch(breaks);
     206             :     }
     207             : };
     208             : 
     209           0 : class LabelControl : public BreakableControl
     210             : {
     211             :     RootedAtom label_;
     212             : 
     213             :     // The code offset when this was pushed. Used for effectfulness checking.
     214             :     ptrdiff_t startOffset_;
     215             : 
     216             :   public:
     217             :     LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
     218           0 :       : BreakableControl(bce, StatementKind::Label),
     219             :         label_(bce->cx, label),
     220           0 :         startOffset_(startOffset)
     221             :     { }
     222             : 
     223             :     HandleAtom label() const {
     224           0 :         return label_;
     225             :     }
     226             : 
     227             :     ptrdiff_t startOffset() const {
     228             :         return startOffset_;
     229             :     }
     230             : };
     231             : 
     232        7221 : class LoopControl : public BreakableControl
     233             : {
     234             :     // Loops' children are emitted in dominance order, so they can always
     235             :     // have a TDZCheckCache.
     236             :     BytecodeEmitter::TDZCheckCache tdzCache_;
     237             : 
     238             :     // Stack depth when this loop was pushed on the control stack.
     239             :     int32_t stackDepth_;
     240             : 
     241             :     // The loop nesting depth. Used as a hint to Ion.
     242             :     uint32_t loopDepth_;
     243             : 
     244             :     // Can we OSR into Ion from here? True unless there is non-loop state on the stack.
     245             :     bool canIonOsr_;
     246             : 
     247             :   public:
     248             :     // The target of continue statement jumps, e.g., the update portion of a
     249             :     // for(;;) loop.
     250             :     JumpTarget continueTarget;
     251             : 
     252             :     // Offset of the last continue in the loop.
     253             :     JumpList continues;
     254             : 
     255        2407 :     LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
     256           0 :       : BreakableControl(bce, loopKind),
     257             :         tdzCache_(bce),
     258        7221 :         continueTarget({ -1 })
     259             :     {
     260           0 :         MOZ_ASSERT(is<LoopControl>());
     261             : 
     262        2407 :         LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
     263             : 
     264           0 :         stackDepth_ = bce->stackDepth;
     265        2407 :         loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
     266             : 
     267             :         int loopSlots;
     268        2407 :         if (loopKind == StatementKind::Spread) {
     269             :             // The iterator next method, the iterator, the result array, and
     270             :             // the current array index are on the stack.
     271             :             loopSlots = 4;
     272           0 :         } else if (loopKind == StatementKind::ForOfLoop) {
     273             :             // The iterator next method, the iterator, and the current value
     274             :             // are on the stack.
     275             :             loopSlots = 3;
     276           0 :         } else if (loopKind == StatementKind::ForInLoop) {
     277             :             // The iterator and the current value are on the stack.
     278             :             loopSlots = 2;
     279             :         } else {
     280             :             // No additional loop values are on the stack.
     281         910 :             loopSlots = 0;
     282             :         }
     283             : 
     284        2407 :         MOZ_ASSERT(loopSlots <= stackDepth_);
     285             : 
     286        2407 :         if (enclosingLoop) {
     287         428 :             canIonOsr_ = (enclosingLoop->canIonOsr_ &&
     288         214 :                           stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
     289             :         } else {
     290           0 :             canIonOsr_ = stackDepth_ == loopSlots;
     291             :         }
     292        2407 :     }
     293             : 
     294             :     uint32_t loopDepth() const {
     295             :         return loopDepth_;
     296             :     }
     297             : 
     298             :     bool canIonOsr() const {
     299             :         return canIonOsr_;
     300             :     }
     301             : 
     302        1114 :     MOZ_MUST_USE bool emitSpecialBreakForDone(BytecodeEmitter* bce) {
     303             :         // This doesn't pop stack values, nor handle any other controls.
     304             :         // Should be called on the toplevel of the loop.
     305           0 :         MOZ_ASSERT(bce->stackDepth == stackDepth_);
     306           0 :         MOZ_ASSERT(bce->innermostNestableControl == this);
     307             : 
     308           0 :         if (!bce->newSrcNote(SRC_BREAK))
     309             :             return false;
     310        1114 :         if (!bce->emitJump(JSOP_GOTO, &breaks))
     311             :             return false;
     312             : 
     313           0 :         return true;
     314             :     }
     315             : 
     316        2164 :     MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce) {
     317        2164 :         MOZ_ASSERT(continueTarget.offset != -1);
     318        4328 :         if (!patchBreaks(bce))
     319             :             return false;
     320        2164 :         bce->patchJumpsToTarget(continues, continueTarget);
     321           0 :         return true;
     322             :     }
     323             : };
     324             : 
     325           0 : class TryFinallyControl : public BytecodeEmitter::NestableControl
     326             : {
     327             :     bool emittingSubroutine_;
     328             : 
     329             :   public:
     330             :     // The subroutine when emitting a finally block.
     331             :     JumpList gosubs;
     332             : 
     333        1074 :     TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
     334        1074 :       : NestableControl(bce, kind),
     335        3222 :         emittingSubroutine_(false)
     336             :     {
     337        2148 :         MOZ_ASSERT(is<TryFinallyControl>());
     338        1074 :     }
     339             : 
     340             :     void setEmittingSubroutine() {
     341           0 :         emittingSubroutine_ = true;
     342             :     }
     343             : 
     344             :     bool emittingSubroutine() const {
     345             :         return emittingSubroutine_;
     346             :     }
     347             : };
     348             : 
     349             : static inline void
     350             : MarkAllBindingsClosedOver(LexicalScope::Data& data)
     351             : {
     352             :     TrailingNamesArray& names = data.trailingNames;
     353        5671 :     for (uint32_t i = 0; i < data.length; i++)
     354       10955 :         names[i] = BindingName(names[i].name(), true);
     355             : }
     356             : 
     357             : // A scope that introduces bindings.
     358       69366 : class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterScope>
     359             : {
     360             :     // The cache of bound names that may be looked up in the
     361             :     // scope. Initially populated as the set of names this scope binds. As
     362             :     // names are looked up in enclosing scopes, they are cached on the
     363             :     // current scope.
     364             :     PooledMapPtr<NameLocationMap> nameCache_;
     365             : 
     366             :     // If this scope's cache does not include free names, such as the
     367             :     // global scope, the NameLocation to return.
     368             :     Maybe<NameLocation> fallbackFreeNameLocation_;
     369             : 
     370             :     // True if there is a corresponding EnvironmentObject on the environment
     371             :     // chain, false if all bindings are stored in frame slots on the stack.
     372             :     bool hasEnvironment_;
     373             : 
     374             :     // The number of enclosing environments. Used for error checking.
     375             :     uint8_t environmentChainLength_;
     376             : 
     377             :     // The next usable slot on the frame for not-closed over bindings.
     378             :     //
     379             :     // The initial frame slot when assigning slots to bindings is the
     380             :     // enclosing scope's nextFrameSlot. For the first scope in a frame,
     381             :     // the initial frame slot is 0.
     382             :     uint32_t nextFrameSlot_;
     383             : 
     384             :     // The index in the BytecodeEmitter's interned scope vector, otherwise
     385             :     // ScopeNote::NoScopeIndex.
     386             :     uint32_t scopeIndex_;
     387             : 
     388             :     // If kind is Lexical, Catch, or With, the index in the BytecodeEmitter's
     389             :     // block scope note list. Otherwise ScopeNote::NoScopeNote.
     390             :     uint32_t noteIndex_;
     391             : 
     392             :     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
     393       23123 :         return nameCache_.acquire(bce->cx);
     394             :     }
     395             : 
     396             :     template <typename BindingIter>
     397           0 :     MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce, const BindingIter& bi) {
     398           0 :         if (bi.nextFrameSlot() >= LOCALNO_LIMIT ||
     399       37330 :             bi.nextEnvironmentSlot() >= ENVCOORD_SLOT_LIMIT)
     400             :         {
     401           0 :             bce->reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
     402           0 :             return false;
     403             :         }
     404             :         return true;
     405             :     }
     406             : 
     407           0 :     MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce) {
     408             :         uint32_t hops;
     409       22714 :         if (EmitterScope* emitterScope = enclosing(&bce))
     410       21901 :             hops = emitterScope->environmentChainLength_;
     411             :         else
     412           0 :             hops = bce->sc->compilationEnclosingScope()->environmentChainLength();
     413             : 
     414           0 :         if (hops >= ENVCOORD_HOPS_LIMIT - 1) {
     415           0 :             bce->reportError(nullptr, JSMSG_TOO_DEEP, js_function_str);
     416           0 :             return false;
     417             :         }
     418             : 
     419           0 :         environmentChainLength_ = mozilla::AssertedCast<uint8_t>(hops + 1);
     420       22714 :         return true;
     421             :     }
     422             : 
     423           0 :     void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi) {
     424           0 :         nextFrameSlot_ = bi.nextFrameSlot();
     425           0 :         if (nextFrameSlot_ > bce->maxFixedSlots)
     426           0 :             bce->maxFixedSlots = nextFrameSlot_;
     427           0 :         MOZ_ASSERT_IF(bce->sc->isFunctionBox() &&
     428             :                       (bce->sc->asFunctionBox()->isGenerator() ||
     429             :                        bce->sc->asFunctionBox()->isAsync()),
     430             :                       bce->maxFixedSlots == 0);
     431       19648 :     }
     432             : 
     433           0 :     MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc) {
     434           0 :         NameLocationMap& cache = *nameCache_;
     435           0 :         NameLocationMap::AddPtr p = cache.lookupForAdd(name);
     436           0 :         MOZ_ASSERT(!p);
     437       59923 :         if (!cache.add(p, name, loc)) {
     438           0 :             ReportOutOfMemory(bce->cx);
     439           0 :             return false;
     440             :         }
     441             :         return true;
     442             :     }
     443             : 
     444           0 :     Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce, JSAtom* name) {
     445      955346 :         if (NameLocationMap::Ptr p = nameCache_->lookup(name))
     446      300287 :             return Some(p->value().wrapped);
     447      194525 :         if (fallbackFreeNameLocation_ && nameCanBeFree(bce, name))
     448       17125 :             return fallbackFreeNameLocation_;
     449             :         return Nothing();
     450             :     }
     451             : 
     452             :     friend bool BytecodeEmitter::needsImplicitThis();
     453             : 
     454             :     EmitterScope* enclosing(BytecodeEmitter** bce) const {
     455             :         // There is an enclosing scope with access to the same frame.
     456      117413 :         if (EmitterScope* inFrame = enclosingInFrame())
     457             :             return inFrame;
     458             : 
     459             :         // We are currently compiling the enclosing script, look in the
     460             :         // enclosing BCE.
     461       55013 :         if ((*bce)->parent) {
     462       52406 :             *bce = (*bce)->parent;
     463           0 :             return (*bce)->innermostEmitterScopeNoCheck();
     464             :         }
     465             : 
     466             :         return nullptr;
     467             :     }
     468             : 
     469       23123 :     Scope* enclosingScope(BytecodeEmitter* bce) const {
     470       23123 :         if (EmitterScope* es = enclosing(&bce))
     471       21902 :             return es->scope(bce);
     472             : 
     473             :         // The enclosing script is already compiled or the current script is the
     474             :         // global script.
     475        1221 :         return bce->sc->compilationEnclosingScope();
     476             :     }
     477             : 
     478             :     static bool nameCanBeFree(BytecodeEmitter* bce, JSAtom* name) {
     479             :         // '.generator' cannot be accessed by name.
     480       51375 :         return name != bce->cx->names().dotGenerator;
     481             :     }
     482             : 
     483             :     static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops);
     484             :     NameLocation searchAndCache(BytecodeEmitter* bce, JSAtom* name);
     485             : 
     486             :     template <typename ScopeCreator>
     487             :     MOZ_MUST_USE bool internScope(BytecodeEmitter* bce, ScopeCreator createScope);
     488             :     template <typename ScopeCreator>
     489             :     MOZ_MUST_USE bool internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope);
     490             :     MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
     491             : 
     492             :     MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
     493             :                                              uint32_t slotEnd);
     494             : 
     495             :   public:
     496             :     explicit EmitterScope(BytecodeEmitter* bce)
     497       23123 :       : Nestable<EmitterScope>(&bce->innermostEmitterScope_),
     498       23123 :         nameCache_(bce->cx->frontendCollectionPool()),
     499             :         hasEnvironment_(false),
     500             :         environmentChainLength_(0),
     501             :         nextFrameSlot_(0),
     502             :         scopeIndex_(ScopeNote::NoScopeIndex),
     503      115615 :         noteIndex_(ScopeNote::NoScopeNoteIndex)
     504             :     { }
     505             : 
     506             :     void dump(BytecodeEmitter* bce);
     507             : 
     508             :     MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
     509             :                                    Handle<LexicalScope::Data*> bindings);
     510             :     MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
     511             :     MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
     512             :     MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox);
     513             :     MOZ_MUST_USE bool enterParameterExpressionVar(BytecodeEmitter* bce);
     514             :     MOZ_MUST_USE bool enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc);
     515             :     MOZ_MUST_USE bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
     516             :     MOZ_MUST_USE bool enterModule(BytecodeEmitter* module, ModuleSharedContext* modulesc);
     517             :     MOZ_MUST_USE bool enterWith(BytecodeEmitter* bce);
     518             :     MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce);
     519             : 
     520             :     MOZ_MUST_USE bool leave(BytecodeEmitter* bce, bool nonLocal = false);
     521             : 
     522       83033 :     uint32_t index() const {
     523       83033 :         MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex, "Did you forget to intern a Scope?");
     524       83033 :         return scopeIndex_;
     525             :     }
     526             : 
     527             :     uint32_t noteIndex() const {
     528             :         return noteIndex_;
     529             :     }
     530             : 
     531       67311 :     Scope* scope(const BytecodeEmitter* bce) const {
     532      201935 :         return bce->scopeList.vector[index()];
     533             :     }
     534             : 
     535             :     bool hasEnvironment() const {
     536             :         return hasEnvironment_;
     537             :     }
     538             : 
     539             :     // The first frame slot used.
     540             :     uint32_t frameSlotStart() const {
     541        9664 :         if (EmitterScope* inFrame = enclosingInFrame())
     542        9664 :             return inFrame->nextFrameSlot_;
     543             :         return 0;
     544             :     }
     545             : 
     546             :     // The last frame slot used + 1.
     547             :     uint32_t frameSlotEnd() const {
     548             :         return nextFrameSlot_;
     549             :     }
     550             : 
     551             :     EmitterScope* enclosingInFrame() const {
     552      244032 :         return Nestable<EmitterScope>::enclosing();
     553             :     }
     554             : 
     555           1 :     NameLocation lookup(BytecodeEmitter* bce, JSAtom* name) {
     556      377147 :         if (Maybe<NameLocation> loc = lookupInCache(bce, name))
     557           1 :             return *loc;
     558           1 :         return searchAndCache(bce, name);
     559             :     }
     560             : 
     561             :     Maybe<NameLocation> locationBoundInScope(JSAtom* name, EmitterScope* target);
     562             : };
     563             : 
     564             : void
     565           0 : BytecodeEmitter::EmitterScope::dump(BytecodeEmitter* bce)
     566             : {
     567           0 :     fprintf(stdout, "EmitterScope [%s] %p\n", ScopeKindString(scope(bce)->kind()), this);
     568             : 
     569           0 :     for (NameLocationMap::Range r = nameCache_->all(); !r.empty(); r.popFront()) {
     570           0 :         const NameLocation& l = r.front().value();
     571             : 
     572           0 :         JSAutoByteString bytes;
     573           0 :         if (!AtomToPrintableString(bce->cx, r.front().key(), &bytes))
     574           0 :             return;
     575           0 :         if (l.kind() != NameLocation::Kind::Dynamic)
     576           0 :             fprintf(stdout, "  %s %s ", BindingKindString(l.bindingKind()), bytes.ptr());
     577             :         else
     578           0 :             fprintf(stdout, "  %s ", bytes.ptr());
     579             : 
     580           0 :         switch (l.kind()) {
     581             :           case NameLocation::Kind::Dynamic:
     582           0 :             fprintf(stdout, "dynamic\n");
     583             :             break;
     584             :           case NameLocation::Kind::Global:
     585           0 :             fprintf(stdout, "global\n");
     586             :             break;
     587             :           case NameLocation::Kind::Intrinsic:
     588           0 :             fprintf(stdout, "intrinsic\n");
     589             :             break;
     590             :           case NameLocation::Kind::NamedLambdaCallee:
     591           0 :             fprintf(stdout, "named lambda callee\n");
     592             :             break;
     593             :           case NameLocation::Kind::Import:
     594           0 :             fprintf(stdout, "import\n");
     595             :             break;
     596             :           case NameLocation::Kind::ArgumentSlot:
     597           0 :             fprintf(stdout, "arg slot=%u\n", l.argumentSlot());
     598             :             break;
     599             :           case NameLocation::Kind::FrameSlot:
     600           0 :             fprintf(stdout, "frame slot=%u\n", l.frameSlot());
     601             :             break;
     602             :           case NameLocation::Kind::EnvironmentCoordinate:
     603           0 :             fprintf(stdout, "environment hops=%u slot=%u\n",
     604           0 :                     l.environmentCoordinate().hops(), l.environmentCoordinate().slot());
     605           0 :             break;
     606             :           case NameLocation::Kind::DynamicAnnexBVar:
     607           0 :             fprintf(stdout, "dynamic annex b var\n");
     608             :             break;
     609             :         }
     610             :     }
     611             : 
     612           0 :     fprintf(stdout, "\n");
     613             : }
     614             : 
     615             : template <typename ScopeCreator>
     616             : bool
     617       23123 : BytecodeEmitter::EmitterScope::internScope(BytecodeEmitter* bce, ScopeCreator createScope)
     618             : {
     619       46246 :     RootedScope enclosing(bce->cx, enclosingScope(bce));
     620           0 :     Scope* scope = createScope(bce->cx, enclosing);
     621           0 :     if (!scope)
     622             :         return false;
     623       23123 :     hasEnvironment_ = scope->hasEnvironment();
     624       46246 :     scopeIndex_ = bce->scopeList.length();
     625       46246 :     return bce->scopeList.append(scope);
     626             : }
     627             : 
     628             : template <typename ScopeCreator>
     629             : bool
     630           0 : BytecodeEmitter::EmitterScope::internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope)
     631             : {
     632           0 :     MOZ_ASSERT(bce->bodyScopeIndex == UINT32_MAX, "There can be only one body scope");
     633           0 :     bce->bodyScopeIndex = bce->scopeList.length();
     634       13449 :     return internScope(bce, createScope);
     635             : }
     636             : 
     637             : bool
     638           0 : BytecodeEmitter::EmitterScope::appendScopeNote(BytecodeEmitter* bce)
     639             : {
     640           0 :     MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
     641             :                "Scope notes are not needed for body-level scopes.");
     642       16888 :     noteIndex_ = bce->scopeNoteList.length();
     643       16888 :     return bce->scopeNoteList.append(index(), bce->offset(), bce->inPrologue(),
     644           1 :                                      enclosingInFrame() ? enclosingInFrame()->noteIndex()
     645           1 :                                                         : ScopeNote::NoScopeNoteIndex);
     646             : }
     647             : 
     648             : #ifdef DEBUG
     649             : static bool
     650         573 : NameIsOnEnvironment(Scope* scope, JSAtom* name)
     651             : {
     652           1 :     for (BindingIter bi(scope); bi; bi++) {
     653             :         // If found, the name must already be on the environment or an import,
     654             :         // or else there is a bug in the closed-over name analysis in the
     655             :         // Parser.
     656           0 :         if (bi.name() == name) {
     657           0 :             BindingLocation::Kind kind = bi.location().kind();
     658             : 
     659           0 :             if (bi.hasArgumentSlot()) {
     660           0 :                 JSScript* script = scope->as<FunctionScope>().script();
     661           0 :                 if (!script->strict() && !script->functionHasParameterExprs()) {
     662             :                     // Check for duplicate positional formal parameters.
     663           0 :                     for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
     664           0 :                         if (bi2.name() == name)
     665           0 :                             kind = bi2.location().kind();
     666             :                     }
     667             :                 }
     668             :             }
     669             : 
     670           0 :             return kind == BindingLocation::Kind::Global ||
     671           0 :                    kind == BindingLocation::Kind::Environment ||
     672           0 :                    kind == BindingLocation::Kind::Import;
     673             :         }
     674             :     }
     675             : 
     676             :     // If not found, assume it's on the global or dynamically accessed.
     677           0 :     return true;
     678             : }
     679             : #endif
     680             : 
     681             : /* static */ NameLocation
     682           0 : BytecodeEmitter::EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops)
     683             : {
     684           1 :     for (ScopeIter si(scope); si; si++) {
     685           1 :         MOZ_ASSERT(NameIsOnEnvironment(si.scope(), name));
     686             : 
     687         573 :         bool hasEnv = si.hasSyntacticEnvironment();
     688             : 
     689           1 :         switch (si.kind()) {
     690             :           case ScopeKind::Function:
     691           0 :             if (hasEnv) {
     692           0 :                 JSScript* script = si.scope()->as<FunctionScope>().script();
     693           0 :                 if (script->funHasExtensibleScope())
     694           1 :                     return NameLocation::Dynamic();
     695             : 
     696           0 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     697           0 :                     if (bi.name() != name)
     698           0 :                         continue;
     699             : 
     700           0 :                     BindingLocation bindLoc = bi.location();
     701           0 :                     if (bi.hasArgumentSlot() &&
     702           0 :                         !script->strict() &&
     703           0 :                         !script->functionHasParameterExprs())
     704             :                     {
     705             :                         // Check for duplicate positional formal parameters.
     706           0 :                         for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
     707           0 :                             if (bi2.name() == name)
     708           0 :                                 bindLoc = bi2.location();
     709             :                         }
     710             :                     }
     711             : 
     712           0 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     713           0 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     714             :                 }
     715             :             }
     716             :             break;
     717             : 
     718             :           case ScopeKind::FunctionBodyVar:
     719             :           case ScopeKind::ParameterExpressionVar:
     720             :           case ScopeKind::Lexical:
     721             :           case ScopeKind::NamedLambda:
     722             :           case ScopeKind::StrictNamedLambda:
     723             :           case ScopeKind::SimpleCatch:
     724             :           case ScopeKind::Catch:
     725           0 :             if (hasEnv) {
     726           0 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     727           0 :                     if (bi.name() != name)
     728           0 :                         continue;
     729             : 
     730             :                     // The name must already have been marked as closed
     731             :                     // over. If this assertion is hit, there is a bug in the
     732             :                     // name analysis.
     733           0 :                     BindingLocation bindLoc = bi.location();
     734           0 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     735           0 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     736             :                 }
     737             :             }
     738             :             break;
     739             : 
     740             :           case ScopeKind::Module:
     741           0 :             if (hasEnv) {
     742           0 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     743           0 :                     if (bi.name() != name)
     744           0 :                         continue;
     745             : 
     746           0 :                     BindingLocation bindLoc = bi.location();
     747             : 
     748             :                     // Imports are on the environment but are indirect
     749             :                     // bindings and must be accessed dynamically instead of
     750             :                     // using an EnvironmentCoordinate.
     751           0 :                     if (bindLoc.kind() == BindingLocation::Kind::Import) {
     752           0 :                         MOZ_ASSERT(si.kind() == ScopeKind::Module);
     753           0 :                         return NameLocation::Import();
     754             :                     }
     755             : 
     756           0 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     757           0 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     758             :                 }
     759             :             }
     760             :             break;
     761             : 
     762             :           case ScopeKind::Eval:
     763             :           case ScopeKind::StrictEval:
     764             :             // As an optimization, if the eval doesn't have its own var
     765             :             // environment and its immediate enclosing scope is a global
     766             :             // scope, all accesses are global.
     767           0 :             if (!hasEnv && si.scope()->enclosing()->is<GlobalScope>())
     768           0 :                 return NameLocation::Global(BindingKind::Var);
     769             :             return NameLocation::Dynamic();
     770             : 
     771             :           case ScopeKind::Global:
     772           1 :             return NameLocation::Global(BindingKind::Var);
     773             : 
     774             :           case ScopeKind::With:
     775             :           case ScopeKind::NonSyntactic:
     776             :             return NameLocation::Dynamic();
     777             : 
     778             :           case ScopeKind::WasmInstance:
     779             :           case ScopeKind::WasmFunction:
     780           0 :             MOZ_CRASH("No direct eval inside wasm functions");
     781             :         }
     782             : 
     783           0 :         if (hasEnv) {
     784           0 :             MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT - 1);
     785           0 :             hops++;
     786             :         }
     787             :     }
     788             : 
     789           0 :     MOZ_CRASH("Malformed scope chain");
     790             : }
     791             : 
     792             : NameLocation
     793       41459 : BytecodeEmitter::EmitterScope::searchAndCache(BytecodeEmitter* bce, JSAtom* name)
     794             : {
     795       82917 :     Maybe<NameLocation> loc;
     796           0 :     uint8_t hops = hasEnvironment() ? 1 : 0;
     797           0 :     DebugOnly<bool> inCurrentScript = enclosingInFrame();
     798             : 
     799             :     // Start searching in the current compilation.
     800           0 :     for (EmitterScope* es = enclosing(&bce); es; es = es->enclosing(&bce)) {
     801           0 :         loc = es->lookupInCache(bce, name);
     802       71003 :         if (loc) {
     803       40886 :             if (loc->kind() == NameLocation::Kind::EnvironmentCoordinate)
     804        8422 :                 *loc = loc->addHops(hops);
     805             :             break;
     806             :         }
     807             : 
     808           0 :         if (es->hasEnvironment())
     809           0 :             hops++;
     810             : 
     811             : #ifdef DEBUG
     812       30117 :         if (!es->enclosingInFrame())
     813       34362 :             inCurrentScript = false;
     814             : #endif
     815             :     }
     816             : 
     817             :     // If the name is not found in the current compilation, walk the Scope
     818             :     // chain encompassing the compilation.
     819       41460 :     if (!loc) {
     820           0 :         inCurrentScript = false;
     821           0 :         loc = Some(searchInEnclosingScope(name, bce->sc->compilationEnclosingScope(), hops));
     822             :     }
     823             : 
     824             :     // Each script has its own frame. A free name that is accessed
     825             :     // from an inner script must not be a frame slot access. If this
     826             :     // assertion is hit, it is a bug in the free name analysis in the
     827             :     // parser.
     828       41460 :     MOZ_ASSERT_IF(!inCurrentScript, loc->kind() != NameLocation::Kind::FrameSlot);
     829             : 
     830             :     // It is always correct to not cache the location. Ignore OOMs to make
     831             :     // lookups infallible.
     832           0 :     if (!putNameInCache(bce, name, *loc))
     833           0 :         bce->cx->recoverFromOutOfMemory();
     834             : 
     835       82916 :     return *loc;
     836             : }
     837             : 
     838             : Maybe<NameLocation>
     839       16171 : BytecodeEmitter::EmitterScope::locationBoundInScope(JSAtom* name, EmitterScope* target)
     840             : {
     841             :     // The target scope must be an intra-frame enclosing scope of this
     842             :     // one. Count the number of extra hops to reach it.
     843           0 :     uint8_t extraHops = 0;
     844           0 :     for (EmitterScope* es = this; es != target; es = es->enclosingInFrame()) {
     845        1590 :         if (es->hasEnvironment())
     846           0 :             extraHops++;
     847             :     }
     848             : 
     849             :     // Caches are prepopulated with bound names. So if the name is bound in a
     850             :     // particular scope, it must already be in the cache. Furthermore, don't
     851             :     // consult the fallback location as we only care about binding names.
     852           0 :     Maybe<NameLocation> loc;
     853       64684 :     if (NameLocationMap::Ptr p = target->nameCache_->lookup(name)) {
     854       16080 :         NameLocation l = p->value().wrapped;
     855       16081 :         if (l.kind() == NameLocation::Kind::EnvironmentCoordinate)
     856       13808 :             loc = Some(l.addHops(extraHops));
     857             :         else
     858       22956 :             loc = Some(l);
     859             :     }
     860       16171 :     return loc;
     861             : }
     862             : 
     863             : bool
     864       10013 : BytecodeEmitter::EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
     865             :                                                       uint32_t slotEnd)
     866             : {
     867             :     // Lexical bindings throw ReferenceErrors if they are used before
     868             :     // initialization. See ES6 8.1.1.1.6.
     869             :     //
     870             :     // For completeness, lexical bindings are initialized in ES6 by calling
     871             :     // InitializeBinding, after which touching the binding will no longer
     872             :     // throw reference errors. See 13.1.11, 9.2.13, 13.6.3.4, 13.6.4.6,
     873             :     // 13.6.4.8, 13.14.5, 15.1.8, and 15.2.0.15.
     874       10013 :     if (slotStart != slotEnd) {
     875        8147 :         if (!bce->emit1(JSOP_UNINITIALIZED))
     876             :             return false;
     877           1 :         for (uint32_t slot = slotStart; slot < slotEnd; slot++) {
     878       12510 :             if (!bce->emitLocalOp(JSOP_INITLEXICAL, slot))
     879             :                 return false;
     880             :         }
     881        8147 :         if (!bce->emit1(JSOP_POP))
     882             :             return false;
     883             :     }
     884             : 
     885             :     return true;
     886             : }
     887             : 
     888             : bool
     889           0 : BytecodeEmitter::EmitterScope::deadZoneFrameSlots(BytecodeEmitter* bce)
     890             : {
     891        2440 :     return deadZoneFrameSlotRange(bce, frameSlotStart(), frameSlotEnd());
     892             : }
     893             : 
     894             : bool
     895        8385 : BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
     896             :                                             Handle<LexicalScope::Data*> bindings)
     897             : {
     898        8385 :     MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
     899        8385 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
     900             : 
     901        8385 :     if (!ensureCache(bce))
     902             :         return false;
     903             : 
     904             :     // Marks all names as closed over if the context requires it. This
     905             :     // cannot be done in the Parser as we may not know if the context requires
     906             :     // all bindings to be closed over until after parsing is finished. For
     907             :     // example, legacy generators require all bindings to be closed over but
     908             :     // it is unknown if a function is a legacy generator until the first
     909             :     // 'yield' expression is parsed.
     910             :     //
     911             :     // This is not a problem with other scopes, as all other scopes with
     912             :     // bindings are body-level. At the time of their creation, whether or not
     913             :     // the context requires all bindings to be closed over is already known.
     914           0 :     if (bce->sc->allBindingsClosedOver())
     915        1268 :         MarkAllBindingsClosedOver(*bindings);
     916             : 
     917             :     // Resolve bindings.
     918        8385 :     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
     919        8385 :     uint32_t firstFrameSlot = frameSlotStart();
     920        8385 :     BindingIter bi(*bindings, firstFrameSlot, /* isNamedLambda = */ false);
     921           0 :     for (; bi; bi++) {
     922       13665 :         if (!checkSlotLimits(bce, bi))
     923           0 :             return false;
     924             : 
     925       13665 :         NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
     926       13665 :         if (!putNameInCache(bce, bi.name(), loc))
     927             :             return false;
     928             : 
     929           0 :         if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
     930             :             return false;
     931             :     }
     932             : 
     933        8385 :     updateFrameFixedSlots(bce, bi);
     934             : 
     935             :     // Create and intern the VM scope.
     936             :     auto createScope = [kind, bindings, firstFrameSlot](JSContext* cx,
     937             :                                                         HandleScope enclosing)
     938             :     {
     939             :         return LexicalScope::create(cx, kind, bindings, firstFrameSlot, enclosing);
     940       16770 :     };
     941        8385 :     if (!internScope(bce, createScope))
     942             :         return false;
     943             : 
     944        8385 :     if (ScopeKindIsInBody(kind) && hasEnvironment()) {
     945             :         // After interning the VM scope we can get the scope index.
     946        1906 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHLEXICALENV))
     947             :             return false;
     948             :     }
     949             : 
     950             :     // Lexical scopes need notes to be mapped from a pc.
     951        8385 :     if (!appendScopeNote(bce))
     952             :         return false;
     953             : 
     954             :     // Put frame slots in TDZ. Environment slots are poisoned during
     955             :     // environment creation.
     956             :     //
     957             :     // This must be done after appendScopeNote to be considered in the extent
     958             :     // of the scope.
     959           0 :     if (!deadZoneFrameSlotRange(bce, firstFrameSlot, frameSlotEnd()))
     960             :         return false;
     961             : 
     962        8385 :     return checkEnvironmentChainLength(bce);
     963             : }
     964             : 
     965             : bool
     966           0 : BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
     967             : {
     968        1230 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
     969        2460 :     MOZ_ASSERT(funbox->namedLambdaBindings());
     970             : 
     971           0 :     if (!ensureCache(bce))
     972             :         return false;
     973             : 
     974             :     // See comment in enterLexical about allBindingsClosedOver.
     975           0 :     if (funbox->allBindingsClosedOver())
     976           0 :         MarkAllBindingsClosedOver(*funbox->namedLambdaBindings());
     977             : 
     978           0 :     BindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT, /* isNamedLambda = */ true);
     979        1230 :     MOZ_ASSERT(bi.kind() == BindingKind::NamedLambdaCallee);
     980             : 
     981             :     // The lambda name, if not closed over, is accessed via JSOP_CALLEE and
     982             :     // not a frame slot. Do not update frame slot information.
     983           0 :     NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
     984           0 :     if (!putNameInCache(bce, bi.name(), loc))
     985             :         return false;
     986             : 
     987           0 :     bi++;
     988        1230 :     MOZ_ASSERT(!bi, "There should be exactly one binding in a NamedLambda scope");
     989             : 
     990        1230 :     auto createScope = [funbox](JSContext* cx, HandleScope enclosing) {
     991             :         ScopeKind scopeKind =
     992        2460 :             funbox->strict() ? ScopeKind::StrictNamedLambda : ScopeKind::NamedLambda;
     993           0 :         return LexicalScope::create(cx, scopeKind, funbox->namedLambdaBindings(),
     994        2460 :                                     LOCALNO_LIMIT, enclosing);
     995           0 :     };
     996        1230 :     if (!internScope(bce, createScope))
     997             :         return false;
     998             : 
     999        1230 :     return checkEnvironmentChainLength(bce);
    1000             : }
    1001             : 
    1002             : bool
    1003           0 : BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
    1004             : {
    1005           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1006             : 
    1007           0 :     if (!ensureCache(bce))
    1008             :         return false;
    1009             : 
    1010             :     // Parameter expressions var scopes have no pre-set bindings and are
    1011             :     // always extensible, as they are needed for eval.
    1012           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1013             : 
    1014             :     // Create and intern the VM scope.
    1015           0 :     uint32_t firstFrameSlot = frameSlotStart();
    1016           0 :     auto createScope = [firstFrameSlot](JSContext* cx, HandleScope enclosing) {
    1017           0 :         return VarScope::create(cx, ScopeKind::ParameterExpressionVar,
    1018             :                                 /* data = */ nullptr, firstFrameSlot,
    1019             :                                 /* needsEnvironment = */ true, enclosing);
    1020           0 :     };
    1021           0 :     if (!internScope(bce, createScope))
    1022             :         return false;
    1023             : 
    1024           0 :     MOZ_ASSERT(hasEnvironment());
    1025           0 :     if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1026             :         return false;
    1027             : 
    1028             :     // The extra var scope needs a note to be mapped from a pc.
    1029           0 :     if (!appendScopeNote(bce))
    1030             :         return false;
    1031             : 
    1032           0 :     return checkEnvironmentChainLength(bce);
    1033             : }
    1034             : 
    1035             : bool
    1036           0 : BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox)
    1037             : {
    1038           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1039             : 
    1040             :     // If there are parameter expressions, there is an extra var scope.
    1041           0 :     if (!funbox->hasExtraBodyVarScope())
    1042           0 :         bce->setVarEmitterScope(this);
    1043             : 
    1044           0 :     if (!ensureCache(bce))
    1045             :         return false;
    1046             : 
    1047             :     // Resolve body-level bindings, if there are any.
    1048       13041 :     auto bindings = funbox->functionScopeBindings();
    1049       13041 :     Maybe<uint32_t> lastLexicalSlot;
    1050       13041 :     if (bindings) {
    1051       22474 :         NameLocationMap& cache = *nameCache_;
    1052             : 
    1053           0 :         BindingIter bi(*bindings, funbox->hasParameterExprs);
    1054           0 :         for (; bi; bi++) {
    1055           0 :             if (!checkSlotLimits(bce, bi))
    1056           0 :                 return false;
    1057             : 
    1058       23549 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1059       47099 :             NameLocationMap::AddPtr p = cache.lookupForAdd(bi.name());
    1060             : 
    1061             :             // The only duplicate bindings that occur are simple formal
    1062             :             // parameters, in which case the last position counts, so update the
    1063             :             // location.
    1064       23550 :             if (p) {
    1065           0 :                 MOZ_ASSERT(bi.kind() == BindingKind::FormalParameter);
    1066           0 :                 MOZ_ASSERT(!funbox->hasDestructuringArgs);
    1067           0 :                 MOZ_ASSERT(!funbox->hasRest());
    1068           0 :                 p->value() = loc;
    1069           0 :                 continue;
    1070             :             }
    1071             : 
    1072       47100 :             if (!cache.add(p, bi.name(), loc)) {
    1073           0 :                 ReportOutOfMemory(bce->cx);
    1074           0 :                 return false;
    1075             :             }
    1076             :         }
    1077             : 
    1078       11237 :         updateFrameFixedSlots(bce, bi);
    1079             :     } else {
    1080           0 :         nextFrameSlot_ = 0;
    1081             :     }
    1082             : 
    1083             :     // If the function's scope may be extended at runtime due to sloppy direct
    1084             :     // eval and there is no extra var scope, any names beyond the function
    1085             :     // scope must be accessed dynamically as we don't know if the name will
    1086             :     // become a 'var' binding due to direct eval.
    1087           0 :     if (!funbox->hasParameterExprs && funbox->hasExtensibleScope())
    1088           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1089             : 
    1090             :     // In case of parameter expressions, the parameters are lexical
    1091             :     // bindings and have TDZ.
    1092       13041 :     if (funbox->hasParameterExprs && nextFrameSlot_) {
    1093           0 :         uint32_t paramFrameSlotEnd = 0;
    1094        2812 :         for (BindingIter bi(*bindings, true); bi; bi++) {
    1095        2470 :             if (!BindingKindIsLexical(bi.kind()))
    1096             :                 break;
    1097             : 
    1098           0 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1099           0 :             if (loc.kind() == NameLocation::Kind::FrameSlot) {
    1100           0 :                 MOZ_ASSERT(paramFrameSlotEnd <= loc.frameSlot());
    1101           0 :                 paramFrameSlotEnd = loc.frameSlot() + 1;
    1102             :             }
    1103             :         }
    1104             : 
    1105           0 :         if (!deadZoneFrameSlotRange(bce, 0, paramFrameSlotEnd))
    1106             :             return false;
    1107             :     }
    1108             : 
    1109             :     // Create and intern the VM scope.
    1110       26082 :     auto createScope = [funbox](JSContext* cx, HandleScope enclosing) {
    1111       39123 :         RootedFunction fun(cx, funbox->function());
    1112           0 :         return FunctionScope::create(cx, funbox->functionScopeBindings(),
    1113       13041 :                                      funbox->hasParameterExprs,
    1114           0 :                                      funbox->needsCallObjectRegardlessOfBindings(),
    1115           0 :                                      fun, enclosing);
    1116       13041 :     };
    1117           0 :     if (!internBodyScope(bce, createScope))
    1118             :         return false;
    1119             : 
    1120       13041 :     return checkEnvironmentChainLength(bce);
    1121             : }
    1122             : 
    1123             : bool
    1124          59 : BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox)
    1125             : {
    1126          59 :     MOZ_ASSERT(funbox->hasParameterExprs);
    1127           0 :     MOZ_ASSERT(funbox->extraVarScopeBindings() ||
    1128             :                funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings());
    1129           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1130             : 
    1131             :     // The extra var scope is never popped once it's entered. It replaces the
    1132             :     // function scope as the var emitter scope.
    1133          59 :     bce->setVarEmitterScope(this);
    1134             : 
    1135           0 :     if (!ensureCache(bce))
    1136             :         return false;
    1137             : 
    1138             :     // Resolve body-level bindings, if there are any.
    1139           0 :     uint32_t firstFrameSlot = frameSlotStart();
    1140         118 :     if (auto bindings = funbox->extraVarScopeBindings()) {
    1141           0 :         BindingIter bi(*bindings, firstFrameSlot);
    1142         258 :         for (; bi; bi++) {
    1143         116 :             if (!checkSlotLimits(bce, bi))
    1144           0 :                 return false;
    1145             : 
    1146         116 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1147         116 :             if (!putNameInCache(bce, bi.name(), loc))
    1148             :                 return false;
    1149             :         }
    1150             : 
    1151          26 :         updateFrameFixedSlots(bce, bi);
    1152             :     } else {
    1153           0 :         nextFrameSlot_ = firstFrameSlot;
    1154             :     }
    1155             : 
    1156             :     // If the extra var scope may be extended at runtime due to sloppy
    1157             :     // direct eval, any names beyond the var scope must be accessed
    1158             :     // dynamically as we don't know if the name will become a 'var' binding
    1159             :     // due to direct eval.
    1160          59 :     if (funbox->hasExtensibleScope())
    1161           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1162             : 
    1163             :     // Create and intern the VM scope.
    1164         118 :     auto createScope = [funbox, firstFrameSlot](JSContext* cx, HandleScope enclosing) {
    1165         236 :         return VarScope::create(cx, ScopeKind::FunctionBodyVar,
    1166             :                                 funbox->extraVarScopeBindings(), firstFrameSlot,
    1167           0 :                                 funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(),
    1168             :                                 enclosing);
    1169         177 :     };
    1170           0 :     if (!internScope(bce, createScope))
    1171             :         return false;
    1172             : 
    1173          59 :     if (hasEnvironment()) {
    1174          38 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1175             :             return false;
    1176             :     }
    1177             : 
    1178             :     // The extra var scope needs a note to be mapped from a pc.
    1179          59 :     if (!appendScopeNote(bce))
    1180             :         return false;
    1181             : 
    1182          59 :     return checkEnvironmentChainLength(bce);
    1183             : }
    1184             : 
    1185             : class DynamicBindingIter : public BindingIter
    1186             : {
    1187             :   public:
    1188             :     explicit DynamicBindingIter(GlobalSharedContext* sc)
    1189         831 :       : BindingIter(*sc->bindings)
    1190             :     { }
    1191             : 
    1192           0 :     explicit DynamicBindingIter(EvalSharedContext* sc)
    1193           0 :       : BindingIter(*sc->bindings, /* strict = */ false)
    1194             :     {
    1195           0 :         MOZ_ASSERT(!sc->strict());
    1196           0 :     }
    1197             : 
    1198        2472 :     JSOp bindingOp() const {
    1199        2472 :         switch (kind()) {
    1200             :           case BindingKind::Var:
    1201             :             return JSOP_DEFVAR;
    1202             :           case BindingKind::Let:
    1203           0 :             return JSOP_DEFLET;
    1204             :           case BindingKind::Const:
    1205           0 :             return JSOP_DEFCONST;
    1206             :           default:
    1207           0 :             MOZ_CRASH("Bad BindingKind");
    1208             :         }
    1209             :     }
    1210             : };
    1211             : 
    1212             : bool
    1213         390 : BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
    1214             : {
    1215         390 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1216             : 
    1217         390 :     bce->setVarEmitterScope(this);
    1218             : 
    1219         390 :     if (!ensureCache(bce))
    1220             :         return false;
    1221             : 
    1222           0 :     if (bce->emitterMode == BytecodeEmitter::SelfHosting) {
    1223             :         // In self-hosting, it is incorrect to consult the global scope because
    1224             :         // self-hosted scripts are cloned into their target compartments before
    1225             :         // they are run. Instead of Global, Intrinsic is used for all names.
    1226             :         //
    1227             :         // Intrinsic lookups are redirected to the special intrinsics holder
    1228             :         // in the global object, into which any missing values are cloned
    1229             :         // lazily upon first access.
    1230           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Intrinsic());
    1231             : 
    1232           0 :         auto createScope = [](JSContext* cx, HandleScope enclosing) {
    1233           0 :             MOZ_ASSERT(!enclosing);
    1234           2 :             return &cx->global()->emptyGlobalScope();
    1235             :         };
    1236           1 :         return internBodyScope(bce, createScope);
    1237             :     }
    1238             : 
    1239             :     // Resolve binding names and emit DEF{VAR,LET,CONST} prologue ops.
    1240           0 :     if (globalsc->bindings) {
    1241        7187 :         for (DynamicBindingIter bi(globalsc); bi; bi++) {
    1242        3455 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1243        3455 :             JSAtom* name = bi.name();
    1244        3455 :             if (!putNameInCache(bce, name, loc))
    1245           0 :                 return false;
    1246             : 
    1247             :             // Define the name in the prologue. Do not emit DEFVAR for
    1248             :             // functions that we'll emit DEFFUN for.
    1249           0 :             if (bi.isTopLevelFunction())
    1250         983 :                 continue;
    1251             : 
    1252        2472 :             if (!bce->emitAtomOp(name, bi.bindingOp()))
    1253             :                 return false;
    1254             :         }
    1255             :     }
    1256             : 
    1257             :     // Note that to save space, we don't add free names to the cache for
    1258             :     // global scopes. They are assumed to be global vars in the syntactic
    1259             :     // global scope, dynamic accesses under non-syntactic global scope.
    1260         389 :     if (globalsc->scopeKind() == ScopeKind::Global)
    1261           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1262             :     else
    1263           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1264             : 
    1265           0 :     auto createScope = [globalsc](JSContext* cx, HandleScope enclosing) {
    1266         389 :         MOZ_ASSERT(!enclosing);
    1267           0 :         return GlobalScope::create(cx, globalsc->scopeKind(), globalsc->bindings);
    1268         389 :     };
    1269         389 :     return internBodyScope(bce, createScope);
    1270             : }
    1271             : 
    1272             : bool
    1273          18 : BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
    1274             : {
    1275           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1276             : 
    1277           0 :     bce->setVarEmitterScope(this);
    1278             : 
    1279           0 :     if (!ensureCache(bce))
    1280             :         return false;
    1281             : 
    1282             :     // For simplicity, treat all free name lookups in eval scripts as dynamic.
    1283           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1284             : 
    1285             :     // Create the `var` scope. Note that there is also a lexical scope, created
    1286             :     // separately in emitScript().
    1287          18 :     auto createScope = [evalsc](JSContext* cx, HandleScope enclosing) {
    1288          36 :         ScopeKind scopeKind = evalsc->strict() ? ScopeKind::StrictEval : ScopeKind::Eval;
    1289          36 :         return EvalScope::create(cx, scopeKind, evalsc->bindings, enclosing);
    1290          18 :     };
    1291          18 :     if (!internBodyScope(bce, createScope))
    1292             :         return false;
    1293             : 
    1294           0 :     if (hasEnvironment()) {
    1295           0 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1296             :             return false;
    1297             :     } else {
    1298             :         // Resolve binding names and emit DEFVAR prologue ops if we don't have
    1299             :         // an environment (i.e., a sloppy eval not in a parameter expression).
    1300             :         // Eval scripts always have their own lexical scope, but non-strict
    1301             :         // scopes may introduce 'var' bindings to the nearest var scope.
    1302             :         //
    1303             :         // TODO: We may optimize strict eval bindings in the future to be on
    1304             :         // the frame. For now, handle everything dynamically.
    1305           0 :         if (!hasEnvironment() && evalsc->bindings) {
    1306           0 :             for (DynamicBindingIter bi(evalsc); bi; bi++) {
    1307           0 :                 MOZ_ASSERT(bi.bindingOp() == JSOP_DEFVAR);
    1308             : 
    1309           0 :                 if (bi.isTopLevelFunction())
    1310             :                     continue;
    1311             : 
    1312           0 :                 if (!bce->emitAtomOp(bi.name(), JSOP_DEFVAR))
    1313           0 :                     return false;
    1314             :             }
    1315             :         }
    1316             : 
    1317             :         // As an optimization, if the eval does not have its own var
    1318             :         // environment and is directly enclosed in a global scope, then all
    1319             :         // free name lookups are global.
    1320           0 :         if (scope(bce)->enclosing()->is<GlobalScope>())
    1321           0 :             fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1322             :     }
    1323             : 
    1324             :     return true;
    1325             : }
    1326             : 
    1327             : bool
    1328           0 : BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
    1329             : {
    1330           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1331             : 
    1332           0 :     bce->setVarEmitterScope(this);
    1333             : 
    1334           0 :     if (!ensureCache(bce))
    1335             :         return false;
    1336             : 
    1337             :     // Resolve body-level bindings, if there are any.
    1338           0 :     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
    1339           0 :     Maybe<uint32_t> firstLexicalFrameSlot;
    1340           0 :     if (ModuleScope::Data* bindings = modulesc->bindings) {
    1341             :         BindingIter bi(*bindings);
    1342           0 :         for (; bi; bi++) {
    1343           0 :             if (!checkSlotLimits(bce, bi))
    1344           0 :                 return false;
    1345             : 
    1346           0 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1347           0 :             if (!putNameInCache(bce, bi.name(), loc))
    1348             :                 return false;
    1349             : 
    1350           0 :             if (BindingKindIsLexical(bi.kind())) {
    1351           0 :                 if (loc.kind() == NameLocation::Kind::FrameSlot && !firstLexicalFrameSlot)
    1352           0 :                     firstLexicalFrameSlot = Some(loc.frameSlot());
    1353             : 
    1354           0 :                 if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
    1355             :                     return false;
    1356             :             }
    1357             :         }
    1358             : 
    1359           0 :         updateFrameFixedSlots(bce, bi);
    1360             :     } else {
    1361           0 :         nextFrameSlot_ = 0;
    1362             :     }
    1363             : 
    1364             :     // Modules are toplevel, so any free names are global.
    1365           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1366             : 
    1367             :     // Put lexical frame slots in TDZ. Environment slots are poisoned during
    1368             :     // environment creation.
    1369           0 :     if (firstLexicalFrameSlot) {
    1370           0 :         if (!deadZoneFrameSlotRange(bce, *firstLexicalFrameSlot, frameSlotEnd()))
    1371             :             return false;
    1372             :     }
    1373             : 
    1374             :     // Create and intern the VM scope.
    1375           0 :     auto createScope = [modulesc](JSContext* cx, HandleScope enclosing) {
    1376           0 :         return ModuleScope::create(cx, modulesc->bindings, modulesc->module(), enclosing);
    1377           0 :     };
    1378           0 :     if (!internBodyScope(bce, createScope))
    1379             :         return false;
    1380             : 
    1381           0 :     return checkEnvironmentChainLength(bce);
    1382             : }
    1383             : 
    1384             : bool
    1385           0 : BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
    1386             : {
    1387           0 :     MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
    1388             : 
    1389           0 :     if (!ensureCache(bce))
    1390             :         return false;
    1391             : 
    1392             :     // 'with' make all accesses dynamic and unanalyzable.
    1393           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1394             : 
    1395             :     auto createScope = [](JSContext* cx, HandleScope enclosing) {
    1396             :         return WithScope::create(cx, enclosing);
    1397           0 :     };
    1398           0 :     if (!internScope(bce, createScope))
    1399             :         return false;
    1400             : 
    1401           0 :     if (!bce->emitInternedScopeOp(index(), JSOP_ENTERWITH))
    1402             :         return false;
    1403             : 
    1404           0 :     if (!appendScopeNote(bce))
    1405             :         return false;
    1406             : 
    1407           0 :     return checkEnvironmentChainLength(bce);
    1408             : }
    1409             : 
    1410             : bool
    1411       28441 : BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
    1412             : {
    1413             :     // If we aren't leaving the scope due to a non-local jump (e.g., break),
    1414             :     // we must be the innermost scope.
    1415           0 :     MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScopeNoCheck());
    1416             : 
    1417       28441 :     ScopeKind kind = scope(bce)->kind();
    1418       28441 :     switch (kind) {
    1419             :       case ScopeKind::Lexical:
    1420             :       case ScopeKind::SimpleCatch:
    1421             :       case ScopeKind::Catch:
    1422       13703 :         if (!bce->emit1(hasEnvironment() ? JSOP_POPLEXICALENV : JSOP_DEBUGLEAVELEXICALENV))
    1423             :             return false;
    1424             :         break;
    1425             : 
    1426             :       case ScopeKind::With:
    1427           0 :         if (!bce->emit1(JSOP_LEAVEWITH))
    1428             :             return false;
    1429             :         break;
    1430             : 
    1431             :       case ScopeKind::ParameterExpressionVar:
    1432           0 :         MOZ_ASSERT(hasEnvironment());
    1433           0 :         if (!bce->emit1(JSOP_POPVARENV))
    1434             :             return false;
    1435             :         break;
    1436             : 
    1437             :       case ScopeKind::Function:
    1438             :       case ScopeKind::FunctionBodyVar:
    1439             :       case ScopeKind::NamedLambda:
    1440             :       case ScopeKind::StrictNamedLambda:
    1441             :       case ScopeKind::Eval:
    1442             :       case ScopeKind::StrictEval:
    1443             :       case ScopeKind::Global:
    1444             :       case ScopeKind::NonSyntactic:
    1445             :       case ScopeKind::Module:
    1446             :         break;
    1447             : 
    1448             :       case ScopeKind::WasmInstance:
    1449             :       case ScopeKind::WasmFunction:
    1450           0 :         MOZ_CRASH("No wasm function scopes in JS");
    1451             :     }
    1452             : 
    1453             :     // Finish up the scope if we are leaving it in LIFO fashion.
    1454       28440 :     if (!nonLocal) {
    1455             :         // Popping scopes due to non-local jumps generate additional scope
    1456             :         // notes. See NonLocalExitControl::prepareForNonLocalJump.
    1457           0 :         if (ScopeKindIsInBody(kind)) {
    1458             :             // The extra function var scope is never popped once it's pushed,
    1459             :             // so its scope note extends until the end of any possible code.
    1460        8444 :             uint32_t offset = kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
    1461        8444 :             bce->scopeNoteList.recordEnd(noteIndex_, offset, bce->inPrologue());
    1462             :         }
    1463             :     }
    1464             : 
    1465             :     return true;
    1466             : }
    1467             : 
    1468             : Maybe<MaybeCheckTDZ>
    1469           0 : BytecodeEmitter::TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name)
    1470             : {
    1471           0 :     if (!ensureCache(bce))
    1472             :         return Nothing();
    1473             : 
    1474      116734 :     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
    1475       38912 :     if (p)
    1476           0 :         return Some(p->value().wrapped);
    1477             : 
    1478       19386 :     MaybeCheckTDZ rv = CheckTDZ;
    1479       42351 :     for (TDZCheckCache* it = enclosing(); it; it = it->enclosing()) {
    1480       40229 :         if (it->cache_) {
    1481       99716 :             if (CheckTDZMap::Ptr p2 = it->cache_->lookup(name)) {
    1482       17264 :                 rv = p2->value();
    1483       17264 :                 break;
    1484             :             }
    1485             :         }
    1486             :     }
    1487             : 
    1488           0 :     if (!cache_->add(p, name, rv)) {
    1489           0 :         ReportOutOfMemory(bce->cx);
    1490             :         return Nothing();
    1491             :     }
    1492             : 
    1493             :     return Some(rv);
    1494             : }
    1495             : 
    1496             : bool
    1497           0 : BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
    1498             :                                              MaybeCheckTDZ check)
    1499             : {
    1500       30668 :     if (!ensureCache(bce))
    1501             :         return false;
    1502             : 
    1503       92004 :     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
    1504       30668 :     if (p) {
    1505       14089 :         MOZ_ASSERT(!check, "TDZ only needs to be checked once per binding per basic block.");
    1506       14089 :         p->value() = check;
    1507             :     } else {
    1508       49737 :         if (!cache_->add(p, name, check)) {
    1509           0 :             ReportOutOfMemory(bce->cx);
    1510           0 :             return false;
    1511             :         }
    1512             :     }
    1513             : 
    1514             :     return true;
    1515             : }
    1516             : 
    1517             : // Class for emitting bytecode for blocks like try-catch-finally.
    1518             : //
    1519             : // Usage: (check for the return value is omitted for simplicity)
    1520             : //
    1521             : //   `try { try_block } catch (ex) { catch_block }`
    1522             : //     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatch,
    1523             : //                         TryEmitter::ControlKind::Syntactic);
    1524             : //     tryCatch.emitTry();
    1525             : //     emit(try_block);
    1526             : //     tryCatch.emitCatch();
    1527             : //     emit(ex and catch_block); // use JSOP_EXCEPTION to get exception
    1528             : //     tryCatch.emitEnd();
    1529             : //
    1530             : //   `try { try_block } finally { finally_block }`
    1531             : //     TryEmitter tryCatch(this, TryEmitter::Kind::TryFinally,
    1532             : //                         TryEmitter::ControlKind::Syntactic);
    1533             : //     tryCatch.emitTry();
    1534             : //     emit(try_block);
    1535             : //     // finally_pos: The "{" character's position in the source code text.
    1536             : //     tryCatch.emitFinally(Some(finally_pos));
    1537             : //     emit(finally_block);
    1538             : //     tryCatch.emitEnd();
    1539             : //
    1540             : //   `try { try_block } catch (ex) {catch_block} finally { finally_block }`
    1541             : //     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
    1542             : //                         TryEmitter::ControlKind::Syntactic);
    1543             : //     tryCatch.emitTry();
    1544             : //     emit(try_block);
    1545             : //     tryCatch.emitCatch();
    1546             : //     emit(ex and catch_block);
    1547             : //     tryCatch.emitFinally(Some(finally_pos));
    1548             : //     emit(finally_block);
    1549             : //     tryCatch.emitEnd();
    1550             : //
    1551        6622 : class MOZ_STACK_CLASS TryEmitter
    1552             : {
    1553             :   public:
    1554             :     enum class Kind {
    1555             :         TryCatch,
    1556             :         TryCatchFinally,
    1557             :         TryFinally
    1558             :     };
    1559             : 
    1560             :     // Syntactic try-catch-finally and internally used non-syntactic
    1561             :     // try-catch-finally behave differently for 2 points.
    1562             :     //
    1563             :     // The first one is whether TryFinallyControl is used or not.
    1564             :     // See the comment for `controlInfo_`.
    1565             :     //
    1566             :     // The second one is whether the catch and finally blocks handle the frame's
    1567             :     // return value.  For syntactic try-catch-finally, the bytecode marked with
    1568             :     // "*" are emitted to clear return value with `undefined` before the catch
    1569             :     // block and the finally block, and also to save/restore the return value
    1570             :     // before/after the finally block.
    1571             :     //
    1572             :     //     JSOP_TRY
    1573             :     //
    1574             :     //     try_body...
    1575             :     //
    1576             :     //     JSOP_GOSUB finally
    1577             :     //     JSOP_JUMPTARGET
    1578             :     //     JSOP_GOTO end:
    1579             :     //
    1580             :     //   catch:
    1581             :     //     JSOP_JUMPTARGET
    1582             :     //   * JSOP_UNDEFINED
    1583             :     //   * JSOP_SETRVAL
    1584             :     //
    1585             :     //     catch_body...
    1586             :     //
    1587             :     //     JSOP_GOSUB finally
    1588             :     //     JSOP_JUMPTARGET
    1589             :     //     JSOP_GOTO end
    1590             :     //
    1591             :     //   finally:
    1592             :     //     JSOP_JUMPTARGET
    1593             :     //   * JSOP_GETRVAL
    1594             :     //   * JSOP_UNDEFINED
    1595             :     //   * JSOP_SETRVAL
    1596             :     //
    1597             :     //     finally_body...
    1598             :     //
    1599             :     //   * JSOP_SETRVAL
    1600             :     //     JSOP_NOP
    1601             :     //
    1602             :     //   end:
    1603             :     //     JSOP_JUMPTARGET
    1604             :     //
    1605             :     // For syntactic try-catch-finally, Syntactic should be used.
    1606             :     // For non-syntactic try-catch-finally, NonSyntactic should be used.
    1607             :     enum class ControlKind {
    1608             :         Syntactic,
    1609             :         NonSyntactic
    1610             :     };
    1611             : 
    1612             :   private:
    1613             :     BytecodeEmitter* bce_;
    1614             :     Kind kind_;
    1615             :     ControlKind controlKind_;
    1616             : 
    1617             :     // Track jumps-over-catches and gosubs-to-finally for later fixup.
    1618             :     //
    1619             :     // When a finally block is active, non-local jumps (including
    1620             :     // jumps-over-catches) result in a GOSUB being written into the bytecode
    1621             :     // stream and fixed-up later.
    1622             :     //
    1623             :     // For non-syntactic try-catch-finally, all that handling is skipped.
    1624             :     // The non-syntactic try-catch-finally must:
    1625             :     //   * have only one catch block
    1626             :     //   * have JSOP_GOTO at the end of catch-block
    1627             :     //   * have no non-local-jump
    1628             :     //   * don't use finally block for normal completion of try-block and
    1629             :     //     catch-block
    1630             :     //
    1631             :     // Additionally, a finally block may be emitted for non-syntactic
    1632             :     // try-catch-finally, even if the kind is TryCatch, because GOSUBs are not
    1633             :     // emitted.
    1634             :     Maybe<TryFinallyControl> controlInfo_;
    1635             : 
    1636             :     // The stack depth before emitting JSOP_TRY.
    1637             :     int depth_;
    1638             : 
    1639             :     // The source note index for SRC_TRY.
    1640             :     unsigned noteIndex_;
    1641             : 
    1642             :     // The offset after JSOP_TRY.
    1643             :     ptrdiff_t tryStart_;
    1644             : 
    1645             :     // JSOP_JUMPTARGET after the entire try-catch-finally block.
    1646             :     JumpList catchAndFinallyJump_;
    1647             : 
    1648             :     // The offset of JSOP_GOTO at the end of the try block.
    1649             :     JumpTarget tryEnd_;
    1650             : 
    1651             :     // The offset of JSOP_JUMPTARGET at the beginning of the finally block.
    1652             :     JumpTarget finallyStart_;
    1653             : 
    1654             : #ifdef DEBUG
    1655             :     // The state of this emitter.
    1656             :     //
    1657             :     // +-------+ emitTry +-----+   emitCatch +-------+      emitEnd  +-----+
    1658             :     // | Start |-------->| Try |-+---------->| Catch |-+->+--------->| End |
    1659             :     // +-------+         +-----+ |           +-------+ |  ^          +-----+
    1660             :     //                           |                     |  |
    1661             :     //                           |  +------------------+  +----+
    1662             :     //                           |  |                          |
    1663             :     //                           |  v emitFinally +---------+  |
    1664             :     //                           +->+------------>| Finally |--+
    1665             :     //                                            +---------+
    1666             :     enum class State {
    1667             :         // The initial state.
    1668             :         Start,
    1669             : 
    1670             :         // After calling emitTry.
    1671             :         Try,
    1672             : 
    1673             :         // After calling emitCatch.
    1674             :         Catch,
    1675             : 
    1676             :         // After calling emitFinally.
    1677             :         Finally,
    1678             : 
    1679             :         // After calling emitEnd.
    1680             :         End
    1681             :     };
    1682             :     State state_;
    1683             : #endif
    1684             : 
    1685             :     bool hasCatch() const {
    1686        3449 :         return kind_ == Kind::TryCatch || kind_ == Kind::TryCatchFinally;
    1687             :     }
    1688             :     bool hasFinally() const {
    1689           0 :         return kind_ == Kind::TryCatchFinally || kind_ == Kind::TryFinally;
    1690             :     }
    1691             : 
    1692             :   public:
    1693           0 :     TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind)
    1694           0 :       : bce_(bce),
    1695             :         kind_(kind),
    1696             :         controlKind_(controlKind),
    1697             :         depth_(0),
    1698             :         noteIndex_(0),
    1699             :         tryStart_(0)
    1700             : #ifdef DEBUG
    1701        9933 :       , state_(State::Start)
    1702             : #endif
    1703             :     {
    1704        3302 :         if (controlKind_ == ControlKind::Syntactic)
    1705           0 :             controlInfo_.emplace(bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try);
    1706           0 :         finallyStart_.offset = 0;
    1707        3302 :     }
    1708             : 
    1709             :     // Emits JSOP_GOTO to the end of try-catch-finally.
    1710             :     // Used in `yield*`.
    1711             :     MOZ_MUST_USE bool emitJumpOverCatchAndFinally() {
    1712           9 :         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1713             :             return false;
    1714             :         return true;
    1715             :     }
    1716             : 
    1717        3311 :     MOZ_MUST_USE bool emitTry() {
    1718           0 :         MOZ_ASSERT(state_ == State::Start);
    1719             : 
    1720             :         // Since an exception can be thrown at any place inside the try block,
    1721             :         // we need to restore the stack and the scope chain before we transfer
    1722             :         // the control to the exception handler.
    1723             :         //
    1724             :         // For that we store in a try note associated with the catch or
    1725             :         // finally block the stack depth upon the try entry. The interpreter
    1726             :         // uses this depth to properly unwind the stack and the scope chain.
    1727           0 :         depth_ = bce_->stackDepth;
    1728             : 
    1729             :         // Record the try location, then emit the try block.
    1730        3311 :         if (!bce_->newSrcNote(SRC_TRY, &noteIndex_))
    1731             :             return false;
    1732           0 :         if (!bce_->emit1(JSOP_TRY))
    1733             :             return false;
    1734        3311 :         tryStart_ = bce_->offset();
    1735             : 
    1736             : #ifdef DEBUG
    1737           0 :         state_ = State::Try;
    1738             : #endif
    1739        3311 :         return true;
    1740             :     }
    1741             : 
    1742             :   private:
    1743        3311 :     MOZ_MUST_USE bool emitTryEnd() {
    1744        3311 :         MOZ_ASSERT(state_ == State::Try);
    1745        3311 :         MOZ_ASSERT(depth_ == bce_->stackDepth);
    1746             : 
    1747             :         // GOSUB to finally, if present.
    1748        6731 :         if (hasFinally() && controlInfo_) {
    1749           0 :             if (!bce_->emitJump(JSOP_GOSUB, &controlInfo_->gosubs))
    1750             :                 return false;
    1751             :         }
    1752             : 
    1753             :         // Source note points to the jump at the end of the try block.
    1754        3311 :         if (!bce_->setSrcNoteOffset(noteIndex_, 0, bce_->offset() - tryStart_ + JSOP_TRY_LENGTH))
    1755             :             return false;
    1756             : 
    1757             :         // Emit jump over catch and/or finally.
    1758           0 :         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1759             :             return false;
    1760             : 
    1761           0 :         if (!bce_->emitJumpTarget(&tryEnd_))
    1762             :             return false;
    1763             : 
    1764        3311 :         return true;
    1765             :     }
    1766             : 
    1767             :   public:
    1768           0 :     MOZ_MUST_USE bool emitCatch() {
    1769        3240 :         MOZ_ASSERT(state_ == State::Try);
    1770           0 :         if (!emitTryEnd())
    1771             :             return false;
    1772             : 
    1773        3240 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1774             : 
    1775           0 :         if (controlKind_ == ControlKind::Syntactic) {
    1776             :             // Clear the frame's return value that might have been set by the
    1777             :             // try block:
    1778             :             //
    1779             :             //   eval("try { 1; throw 2 } catch(e) {}"); // undefined, not 1
    1780        1003 :             if (!bce_->emit1(JSOP_UNDEFINED))
    1781             :                 return false;
    1782           0 :             if (!bce_->emit1(JSOP_SETRVAL))
    1783             :                 return false;
    1784             :         }
    1785             : 
    1786             : #ifdef DEBUG
    1787        3240 :         state_ = State::Catch;
    1788             : #endif
    1789           0 :         return true;
    1790             :     }
    1791             : 
    1792             :   private:
    1793        3240 :     MOZ_MUST_USE bool emitCatchEnd() {
    1794           0 :         MOZ_ASSERT(state_ == State::Catch);
    1795             : 
    1796        6480 :         if (!controlInfo_)
    1797             :             return true;
    1798             : 
    1799             :         // gosub <finally>, if required.
    1800        2006 :         if (hasFinally()) {
    1801          29 :             if (!bce_->emitJump(JSOP_GOSUB, &controlInfo_->gosubs))
    1802             :                 return false;
    1803          29 :             MOZ_ASSERT(bce_->stackDepth == depth_);
    1804             : 
    1805             :             // Jump over the finally block.
    1806           0 :             if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1807             :                 return false;
    1808             :         }
    1809             : 
    1810             :         return true;
    1811             :     }
    1812             : 
    1813             :   public:
    1814             :     // If `finallyPos` is specified, it's an offset of the finally block's
    1815             :     // "{" character in the source code text, to improve line:column number in
    1816             :     // the error reporting.
    1817             :     // For non-syntactic try-catch-finally, `finallyPos` can be omitted.
    1818         138 :     MOZ_MUST_USE bool emitFinally(const Maybe<uint32_t>& finallyPos = Nothing()) {
    1819             :         // If we are using controlInfo_ (i.e., emitting a syntactic try
    1820             :         // blocks), we must have specified up front if there will be a finally
    1821             :         // close. For internal non-syntactic try blocks, like those emitted for
    1822             :         // yield* and IteratorClose inside for-of loops, we can emitFinally even
    1823             :         // without specifying up front, since the internal non-syntactic try
    1824             :         // blocks emit no GOSUBs.
    1825           0 :         if (!controlInfo_) {
    1826           0 :             if (kind_ == Kind::TryCatch)
    1827          29 :                 kind_ = Kind::TryCatchFinally;
    1828             :         } else {
    1829         200 :             MOZ_ASSERT(hasFinally());
    1830             :         }
    1831             : 
    1832           0 :         if (!hasCatch()) {
    1833          71 :             MOZ_ASSERT(state_ == State::Try);
    1834          71 :             if (!emitTryEnd())
    1835             :                 return false;
    1836             :         } else {
    1837          67 :             MOZ_ASSERT(state_ == State::Catch);
    1838           0 :             if (!emitCatchEnd())
    1839             :                 return false;
    1840             :         }
    1841             : 
    1842         138 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1843             : 
    1844           0 :         if (!bce_->emitJumpTarget(&finallyStart_))
    1845             :             return false;
    1846             : 
    1847           0 :         if (controlInfo_) {
    1848             :             // Fix up the gosubs that might have been emitted before non-local
    1849             :             // jumps to the finally code.
    1850           0 :             bce_->patchJumpsToTarget(controlInfo_->gosubs, finallyStart_);
    1851             : 
    1852             :             // Indicate that we're emitting a subroutine body.
    1853         100 :             controlInfo_->setEmittingSubroutine();
    1854             :         }
    1855         138 :         if (finallyPos) {
    1856         100 :             if (!bce_->updateSourceCoordNotes(finallyPos.value()))
    1857             :                 return false;
    1858             :         }
    1859         138 :         if (!bce_->emit1(JSOP_FINALLY))
    1860             :             return false;
    1861             : 
    1862         138 :         if (controlKind_ == ControlKind::Syntactic) {
    1863         100 :             if (!bce_->emit1(JSOP_GETRVAL))
    1864             :                 return false;
    1865             : 
    1866             :             // Clear the frame's return value to make break/continue return
    1867             :             // correct value even if there's no other statement before them:
    1868             :             //
    1869             :             //   eval("x: try { 1 } finally { break x; }"); // undefined, not 1
    1870         100 :             if (!bce_->emit1(JSOP_UNDEFINED))
    1871             :                 return false;
    1872           0 :             if (!bce_->emit1(JSOP_SETRVAL))
    1873             :                 return false;
    1874             :         }
    1875             : 
    1876             : #ifdef DEBUG
    1877         138 :         state_ = State::Finally;
    1878             : #endif
    1879           0 :         return true;
    1880             :     }
    1881             : 
    1882             :   private:
    1883           0 :     MOZ_MUST_USE bool emitFinallyEnd() {
    1884         138 :         MOZ_ASSERT(state_ == State::Finally);
    1885             : 
    1886         138 :         if (controlKind_ == ControlKind::Syntactic) {
    1887           0 :             if (!bce_->emit1(JSOP_SETRVAL))
    1888             :                 return false;
    1889             :         }
    1890             : 
    1891         138 :         if (!bce_->emit1(JSOP_RETSUB))
    1892             :             return false;
    1893             : 
    1894           0 :         bce_->hasTryFinally = true;
    1895         138 :         return true;
    1896             :     }
    1897             : 
    1898             :   public:
    1899        3311 :     MOZ_MUST_USE bool emitEnd() {
    1900        6622 :         if (!hasFinally()) {
    1901        3173 :             MOZ_ASSERT(state_ == State::Catch);
    1902           0 :             if (!emitCatchEnd())
    1903             :                 return false;
    1904             :         } else {
    1905         138 :             MOZ_ASSERT(state_ == State::Finally);
    1906           0 :             if (!emitFinallyEnd())
    1907             :                 return false;
    1908             :         }
    1909             : 
    1910        3311 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1911             : 
    1912             :         // ReconstructPCStack needs a NOP here to mark the end of the last
    1913             :         // catch block.
    1914        3311 :         if (!bce_->emit1(JSOP_NOP))
    1915             :             return false;
    1916             : 
    1917             :         // Fix up the end-of-try/catch jumps to come here.
    1918        3311 :         if (!bce_->emitJumpTargetAndPatch(catchAndFinallyJump_))
    1919             :             return false;
    1920             : 
    1921             :         // Add the try note last, to let post-order give us the right ordering
    1922             :         // (first to last for a given nesting level, inner to outer by level).
    1923        6622 :         if (hasCatch()) {
    1924        3240 :             if (!bce_->tryNoteList.append(JSTRY_CATCH, depth_, tryStart_, tryEnd_.offset))
    1925             :                 return false;
    1926             :         }
    1927             : 
    1928             :         // If we've got a finally, mark try+catch region with additional
    1929             :         // trynote to catch exceptions (re)thrown from a catch block or
    1930             :         // for the try{}finally{} case.
    1931        6622 :         if (hasFinally()) {
    1932         138 :             if (!bce_->tryNoteList.append(JSTRY_FINALLY, depth_, tryStart_, finallyStart_.offset))
    1933             :                 return false;
    1934             :         }
    1935             : 
    1936             : #ifdef DEBUG
    1937        3311 :         state_ = State::End;
    1938             : #endif
    1939        3311 :         return true;
    1940             :     }
    1941             : };
    1942             : 
    1943             : // Class for emitting bytecode for blocks like if-then-else.
    1944             : //
    1945             : // This class can be used to emit single if-then-else block, or cascading
    1946             : // else-if blocks.
    1947             : //
    1948             : // Usage: (check for the return value is omitted for simplicity)
    1949             : //
    1950             : //   `if (cond) then_block`
    1951             : //     IfEmitter ifThen(this);
    1952             : //     emit(cond);
    1953             : //     ifThen.emitThen();
    1954             : //     emit(then_block);
    1955             : //     ifThen.emitEnd();
    1956             : //
    1957             : //   `if (cond) then_block else else_block`
    1958             : //     IfEmitter ifThenElse(this);
    1959             : //     emit(cond);
    1960             : //     ifThenElse.emitThenElse();
    1961             : //     emit(then_block);
    1962             : //     ifThenElse.emitElse();
    1963             : //     emit(else_block);
    1964             : //     ifThenElse.emitEnd();
    1965             : //
    1966             : //   `if (c1) b1 else if (c2) b2 else if (c3) b3 else b4`
    1967             : //     IfEmitter ifThenElse(this);
    1968             : //     emit(c1);
    1969             : //     ifThenElse.emitThenElse();
    1970             : //     emit(b1);
    1971             : //     ifThenElse.emitElseIf();
    1972             : //     emit(c2);
    1973             : //     ifThenElse.emitThenElse();
    1974             : //     emit(b2);
    1975             : //     ifThenElse.emitElseIf();
    1976             : //     emit(c3);
    1977             : //     ifThenElse.emitThenElse();
    1978             : //     emit(b3);
    1979             : //     ifThenElse.emitElse();
    1980             : //     emit(b4);
    1981             : //     ifThenElse.emitEnd();
    1982             : //
    1983             : //   `cond ? then_expr : else_expr`
    1984             : //     IfEmitter condElse(this);
    1985             : //     emit(cond);
    1986             : //     condElse.emitCond();
    1987             : //     emit(then_block);
    1988             : //     condElse.emitElse();
    1989             : //     emit(else_block);
    1990             : //     condElse.emitEnd();
    1991             : //
    1992       38954 : class MOZ_STACK_CLASS IfEmitter
    1993             : {
    1994             :   public:
    1995             :     // Whether the then-clause, the else-clause, or else-if condition may
    1996             :     // contain declaration or access to lexical variables, which means they
    1997             :     // should have their own TDZCheckCache.  Basically TDZCheckCache should be
    1998             :     // created for each basic block, which then-clause, else-clause, and
    1999             :     // else-if condition are, but for internally used branches which are
    2000             :     // known not to touch lexical variables we can skip creating TDZCheckCache
    2001             :     // for them.
    2002             :     //
    2003             :     // See the comment for TDZCheckCache class for more details.
    2004             :     enum class Kind {
    2005             :         // For syntactic branches (if, if-else, and conditional expression),
    2006             :         // which basically may contain declaration or accesses to lexical
    2007             :         // variables inside then-clause, else-clause, and else-if condition.
    2008             :         MayContainLexicalAccessInBranch,
    2009             : 
    2010             :         // For internally used branches which don't touch lexical variables
    2011             :         // inside then-clause, else-clause, nor else-if condition.
    2012             :         NoLexicalAccessInBranch
    2013             :     };
    2014             : 
    2015             :   private:
    2016             :     using TDZCheckCache = BytecodeEmitter::TDZCheckCache;
    2017             : 
    2018             :     BytecodeEmitter* bce_;
    2019             : 
    2020             :     // Jump around the then clause, to the beginning of the else clause.
    2021             :     JumpList jumpAroundThen_;
    2022             : 
    2023             :     // Jump around the else clause, to the end of the entire branch.
    2024             :     JumpList jumpsAroundElse_;
    2025             : 
    2026             :     // The stack depth before emitting the then block.
    2027             :     // Used for restoring stack depth before emitting the else block.
    2028             :     // Also used for assertion to make sure then and else blocks pushed the
    2029             :     // same number of values.
    2030             :     int32_t thenDepth_;
    2031             : 
    2032             :     Kind kind_;
    2033             :     Maybe<TDZCheckCache> tdzCache_;
    2034             : 
    2035             : #ifdef DEBUG
    2036             :     // The number of values pushed in the then and else blocks.
    2037             :     int32_t pushed_;
    2038             :     bool calculatedPushed_;
    2039             : 
    2040             :     // The state of this emitter.
    2041             :     //
    2042             :     // +-------+   emitCond +------+ emitElse +------+        emitEnd +-----+
    2043             :     // | Start |-+--------->| Cond |--------->| Else |------>+------->| End |
    2044             :     // +-------+ |          +------+          +------+       ^        +-----+
    2045             :     //           |                                           |
    2046             :     //           v emitThen +------+                         |
    2047             :     //        +->+--------->| Then |------------------------>+
    2048             :     //        ^  |          +------+                         ^
    2049             :     //        |  |                                           |
    2050             :     //        |  |                                           +---+
    2051             :     //        |  |                                               |
    2052             :     //        |  | emitThenElse +----------+   emitElse +------+ |
    2053             :     //        |  +------------->| ThenElse |-+--------->| Else |-+
    2054             :     //        |                 +----------+ |          +------+
    2055             :     //        |                              |
    2056             :     //        |                              | emitElseIf +--------+
    2057             :     //        |                              +----------->| ElseIf |-+
    2058             :     //        |                                           +--------+ |
    2059             :     //        |                                                      |
    2060             :     //        +------------------------------------------------------+
    2061             :     enum class State {
    2062             :         // The initial state.
    2063             :         Start,
    2064             : 
    2065             :         // After calling emitThen.
    2066             :         Then,
    2067             : 
    2068             :         // After calling emitCond.
    2069             :         Cond,
    2070             : 
    2071             :         // After calling emitThenElse.
    2072             :         ThenElse,
    2073             : 
    2074             :         // After calling emitElse.
    2075             :         Else,
    2076             : 
    2077             :         // After calling emitElseIf.
    2078             :         ElseIf,
    2079             : 
    2080             :         // After calling emitEnd.
    2081             :         End
    2082             :     };
    2083             :     State state_;
    2084             : #endif
    2085             : 
    2086             :   protected:
    2087             :     // For InternalIfEmitter.
    2088             :     IfEmitter(BytecodeEmitter* bce, Kind kind)
    2089           0 :       : bce_(bce)
    2090             :       , thenDepth_(0)
    2091             :       , kind_(kind)
    2092             : #ifdef DEBUG
    2093             :       , pushed_(0)
    2094             :       , calculatedPushed_(false)
    2095       77908 :       , state_(State::Start)
    2096             : #endif
    2097             :     {}
    2098             : 
    2099             :   public:
    2100             :     explicit IfEmitter(BytecodeEmitter* bce)
    2101       27610 :       : IfEmitter(bce, Kind::MayContainLexicalAccessInBranch)
    2102             :     {}
    2103             : 
    2104             :   private:
    2105           0 :     MOZ_MUST_USE bool emitIfInternal(SrcNoteType type) {
    2106       19750 :         MOZ_ASSERT_IF(state_ == State::ElseIf, tdzCache_.isSome());
    2107       19750 :         MOZ_ASSERT_IF(state_ != State::ElseIf, tdzCache_.isNothing());
    2108             : 
    2109             :         // The end of TDZCheckCache for cond for else-if.
    2110       19750 :         if (kind_ == Kind::MayContainLexicalAccessInBranch)
    2111           0 :             tdzCache_.reset();
    2112             : 
    2113             :         // Emit an annotated branch-if-false around the then part.
    2114           0 :         if (!bce_->newSrcNote(type))
    2115             :             return false;
    2116           0 :         if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_))
    2117             :             return false;
    2118             : 
    2119             :         // To restore stack depth in else part, save depth of the then part.
    2120             : #ifdef DEBUG
    2121             :         // If DEBUG, this is also necessary to calculate |pushed_|.
    2122           0 :         thenDepth_ = bce_->stackDepth;
    2123             : #else
    2124             :         if (type == SRC_COND || type == SRC_IF_ELSE)
    2125             :             thenDepth_ = bce_->stackDepth;
    2126             : #endif
    2127             : 
    2128             :         // Enclose then-branch with TDZCheckCache.
    2129       19750 :         if (kind_ == Kind::MayContainLexicalAccessInBranch)
    2130       14487 :             tdzCache_.emplace(bce_);
    2131             : 
    2132             :         return true;
    2133             :     }
    2134             : 
    2135       25046 :     void calculateOrCheckPushed() {
    2136             : #ifdef DEBUG
    2137       25046 :         if (!calculatedPushed_) {
    2138       19068 :             pushed_ = bce_->stackDepth - thenDepth_;
    2139       19068 :             calculatedPushed_ = true;
    2140             :         } else {
    2141        5978 :             MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
    2142             :         }
    2143             : #endif
    2144       25046 :     }
    2145             : 
    2146             :   public:
    2147           0 :     MOZ_MUST_USE bool emitThen() {
    2148       13772 :         MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
    2149       13772 :         if (!emitIfInternal(SRC_IF))
    2150             :             return false;
    2151             : 
    2152             : #ifdef DEBUG
    2153       13772 :         state_ = State::Then;
    2154             : #endif
    2155       13772 :         return true;
    2156             :     }
    2157             : 
    2158           0 :     MOZ_MUST_USE bool emitCond() {
    2159         971 :         MOZ_ASSERT(state_ == State::Start);
    2160           0 :         if (!emitIfInternal(SRC_COND))
    2161             :             return false;
    2162             : 
    2163             : #ifdef DEBUG
    2164           0 :         state_ = State::Cond;
    2165             : #endif
    2166           0 :         return true;
    2167             :     }
    2168             : 
    2169        5007 :     MOZ_MUST_USE bool emitThenElse() {
    2170           0 :         MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
    2171        5007 :         if (!emitIfInternal(SRC_IF_ELSE))
    2172             :             return false;
    2173             : 
    2174             : #ifdef DEBUG
    2175           0 :         state_ = State::ThenElse;
    2176             : #endif
    2177        5006 :         return true;
    2178             :     }
    2179             : 
    2180             :   private:
    2181        5978 :     MOZ_MUST_USE bool emitElseInternal() {
    2182           0 :         calculateOrCheckPushed();
    2183             : 
    2184             :         // The end of TDZCheckCache for then-clause.
    2185        5978 :         if (kind_ == Kind::MayContainLexicalAccessInBranch) {
    2186        3025 :             MOZ_ASSERT(tdzCache_.isSome());
    2187           0 :             tdzCache_.reset();
    2188             :         }
    2189             : 
    2190             :         // Emit a jump from the end of our then part around the else part. The
    2191             :         // patchJumpsToTarget call at the bottom of this function will fix up
    2192             :         // the offset with jumpsAroundElse value.
    2193        5978 :         if (!bce_->emitJump(JSOP_GOTO, &jumpsAroundElse_))
    2194             :             return false;
    2195             : 
    2196             :         // Ensure the branch-if-false comes here, then emit the else.
    2197        5978 :         if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
    2198             :             return false;
    2199             : 
    2200             :         // Clear jumpAroundThen_ offset, to tell emitEnd there was an else part.
    2201        5978 :         jumpAroundThen_ = JumpList();
    2202             : 
    2203             :         // Restore stack depth of the then part.
    2204        5978 :         bce_->stackDepth = thenDepth_;
    2205             : #ifdef DEBUG
    2206        5978 :         state_ = State::Else;
    2207             : #endif
    2208        5978 :         return true;
    2209             :     }
    2210             : 
    2211             :   public:
    2212        5296 :     MOZ_MUST_USE bool emitElse() {
    2213        5296 :         MOZ_ASSERT(state_ == State::ThenElse || state_ == State::Cond);
    2214             : 
    2215        5296 :         if (!emitElseInternal())
    2216             :             return false;
    2217             : 
    2218             :         // Enclose else-branch with TDZCheckCache.
    2219        5296 :         if (kind_ == Kind::MayContainLexicalAccessInBranch)
    2220        2343 :             tdzCache_.emplace(bce_);
    2221             : 
    2222             : #ifdef DEBUG
    2223        5296 :         state_ = State::Else;
    2224             : #endif
    2225        5296 :         return true;
    2226             :     }
    2227             : 
    2228         682 :     MOZ_MUST_USE bool emitElseIf() {
    2229         682 :         MOZ_ASSERT(state_ == State::ThenElse);
    2230             : 
    2231         682 :         if (!emitElseInternal())
    2232             :             return false;
    2233             : 
    2234             :         // Enclose cond for else-if with TDZCheckCache.
    2235         682 :         if (kind_ == Kind::MayContainLexicalAccessInBranch)
    2236         682 :             tdzCache_.emplace(bce_);
    2237             : 
    2238             : #ifdef DEBUG
    2239         682 :         state_ = State::ElseIf;
    2240             : #endif
    2241         682 :         return true;
    2242             :     }
    2243             : 
    2244       19068 :     MOZ_MUST_USE bool emitEnd() {
    2245       19068 :         MOZ_ASSERT(state_ == State::Then || state_ == State::Else);
    2246             :         // If there was an else part for the last branch, jumpAroundThen_ is
    2247             :         // already fixed up when emitting the else part.
    2248       19068 :         MOZ_ASSERT_IF(state_ == State::Then, jumpAroundThen_.offset != -1);
    2249       19068 :         MOZ_ASSERT_IF(state_ == State::Else, jumpAroundThen_.offset == -1);
    2250             : 
    2251             :         // The end of TDZCheckCache for then or else-clause.
    2252       19068 :         if (kind_ == Kind::MayContainLexicalAccessInBranch) {
    2253       13805 :             MOZ_ASSERT(tdzCache_.isSome());
    2254       13805 :             tdzCache_.reset();
    2255             :         }
    2256             : 
    2257       19068 :         calculateOrCheckPushed();
    2258             : 
    2259       19068 :         if (jumpAroundThen_.offset != -1) {
    2260             :             // No else part for the last branch, fixup the branch-if-false to
    2261             :             // come here.
    2262       13772 :             if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
    2263             :                 return false;
    2264             :         }
    2265             : 
    2266             :         // Patch all the jumps around else parts.
    2267       19068 :         if (!bce_->emitJumpTargetAndPatch(jumpsAroundElse_))
    2268             :             return false;
    2269             : 
    2270             : #ifdef DEBUG
    2271       19068 :         state_ = State::End;
    2272             : #endif
    2273       19068 :         return true;
    2274             :     }
    2275             : 
    2276             : #ifdef DEBUG
    2277             :     // Returns the number of values pushed onto the value stack inside
    2278             :     // `then_block` and `else_block`.
    2279             :     // Can be used in assertion after emitting if-then-else.
    2280             :     int32_t pushed() const {
    2281             :         return pushed_;
    2282             :     }
    2283             : 
    2284             :     // Returns the number of values popped onto the value stack inside
    2285             :     // `then_block` and `else_block`.
    2286             :     // Can be used in assertion after emitting if-then-else.
    2287             :     int32_t popped() const {
    2288             :         return -pushed_;
    2289             :     }
    2290             : #endif
    2291             : };
    2292             : 
    2293             : // Class for emitting bytecode for blocks like if-then-else which doesn't touch
    2294             : // lexical variables.
    2295             : //
    2296             : // See the comments above NoLexicalAccessInBranch for more details when to use
    2297             : // this instead of IfEmitter.
    2298       11317 : class MOZ_STACK_CLASS InternalIfEmitter : public IfEmitter
    2299             : {
    2300             :   public:
    2301             :     explicit InternalIfEmitter(BytecodeEmitter* bce)
    2302       11344 :       : IfEmitter(bce, Kind::NoLexicalAccessInBranch)
    2303             :     {}
    2304             : };
    2305             : 
    2306           0 : class ForOfLoopControl : public LoopControl
    2307             : {
    2308             :     using EmitterScope = BytecodeEmitter::EmitterScope;
    2309             : 
    2310             :     // The stack depth of the iterator.
    2311             :     int32_t iterDepth_;
    2312             : 
    2313             :     // for-of loops, when throwing from non-iterator code (i.e. from the body
    2314             :     // or from evaluating the LHS of the loop condition), need to call
    2315             :     // IteratorClose.  This is done by enclosing non-iterator code with
    2316             :     // try-catch and call IteratorClose in `catch` block.
    2317             :     // If IteratorClose itself throws, we must not re-call IteratorClose. Since
    2318             :     // non-local jumps like break and return call IteratorClose, whenever a
    2319             :     // non-local jump is emitted, we must tell catch block not to perform
    2320             :     // IteratorClose.
    2321             :     //
    2322             :     //   for (x of y) {
    2323             :     //     // Operations for iterator (IteratorNext etc) are outside of
    2324             :     //     // try-block.
    2325             :     //     try {
    2326             :     //       ...
    2327             :     //       if (...) {
    2328             :     //         // Before non-local jump, clear iterator on the stack to tell
    2329             :     //         // catch block not to perform IteratorClose.
    2330             :     //         tmpIterator = iterator;
    2331             :     //         iterator = undefined;
    2332             :     //         IteratorClose(tmpIterator, { break });
    2333             :     //         break;
    2334             :     //       }
    2335             :     //       ...
    2336             :     //     } catch (e) {
    2337             :     //       // Just throw again when iterator is cleared by non-local jump.
    2338             :     //       if (iterator === undefined)
    2339             :     //         throw e;
    2340             :     //       IteratorClose(iterator, { throw, e });
    2341             :     //     }
    2342             :     //   }
    2343             :     Maybe<TryEmitter> tryCatch_;
    2344             : 
    2345             :     // Used to track if any yields were emitted between calls to to
    2346             :     // emitBeginCodeNeedingIteratorClose and emitEndCodeNeedingIteratorClose.
    2347             :     uint32_t numYieldsAtBeginCodeNeedingIterClose_;
    2348             : 
    2349             :     bool allowSelfHosted_;
    2350             : 
    2351             :     IteratorKind iterKind_;
    2352             : 
    2353             :   public:
    2354             :     ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted,
    2355             :                      IteratorKind iterKind)
    2356        1114 :       : LoopControl(bce, StatementKind::ForOfLoop),
    2357             :         iterDepth_(iterDepth),
    2358             :         numYieldsAtBeginCodeNeedingIterClose_(UINT32_MAX),
    2359             :         allowSelfHosted_(allowSelfHosted),
    2360           0 :         iterKind_(iterKind)
    2361             :     {
    2362             :     }
    2363             : 
    2364        1114 :     bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
    2365        1114 :         tryCatch_.emplace(bce, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
    2366             : 
    2367           0 :         if (!tryCatch_->emitTry())
    2368             :             return false;
    2369             : 
    2370           0 :         MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
    2371        1114 :         numYieldsAtBeginCodeNeedingIterClose_ = bce->yieldAndAwaitOffsetList.numYields;
    2372             : 
    2373        1114 :         return true;
    2374             :     }
    2375             : 
    2376        1114 :     bool emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
    2377           0 :         if (!tryCatch_->emitCatch())              // ITER ...
    2378             :             return false;
    2379             : 
    2380        1114 :         if (!bce->emit1(JSOP_EXCEPTION))          // ITER ... EXCEPTION
    2381             :             return false;
    2382        1114 :         unsigned slotFromTop = bce->stackDepth - iterDepth_;
    2383           0 :         if (!bce->emitDupAt(slotFromTop))         // ITER ... EXCEPTION ITER
    2384             :             return false;
    2385             : 
    2386             :         // If ITER is undefined, it means the exception is thrown by
    2387             :         // IteratorClose for non-local jump, and we should't perform
    2388             :         // IteratorClose again here.
    2389        1114 :         if (!bce->emit1(JSOP_UNDEFINED))          // ITER ... EXCEPTION ITER UNDEF
    2390             :             return false;
    2391        1114 :         if (!bce->emit1(JSOP_STRICTNE))           // ITER ... EXCEPTION NE
    2392             :             return false;
    2393             : 
    2394        1114 :         InternalIfEmitter ifIteratorIsNotClosed(bce);
    2395        1114 :         if (!ifIteratorIsNotClosed.emitThen())    // ITER ... EXCEPTION
    2396             :             return false;
    2397             : 
    2398        1114 :         MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
    2399        1114 :         if (!bce->emitDupAt(slotFromTop))         // ITER ... EXCEPTION ITER
    2400             :             return false;
    2401        1114 :         if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Throw))
    2402             :             return false;                         // ITER ... EXCEPTION
    2403             : 
    2404        1114 :         if (!ifIteratorIsNotClosed.emitEnd())     // ITER ... EXCEPTION
    2405             :             return false;
    2406             : 
    2407        1114 :         if (!bce->emit1(JSOP_THROW))              // ITER ...
    2408             :             return false;
    2409             : 
    2410             :         // If any yields were emitted, then this for-of loop is inside a star
    2411             :         // generator and must handle the case of Generator.return. Like in
    2412             :         // yield*, it is handled with a finally block.
    2413        1114 :         uint32_t numYieldsEmitted = bce->yieldAndAwaitOffsetList.numYields;
    2414           0 :         if (numYieldsEmitted > numYieldsAtBeginCodeNeedingIterClose_) {
    2415          58 :             if (!tryCatch_->emitFinally())
    2416           0 :                 return false;
    2417             : 
    2418          58 :             InternalIfEmitter ifGeneratorClosing(bce);
    2419           0 :             if (!bce->emit1(JSOP_ISGENCLOSING))   // ITER ... FTYPE FVALUE CLOSING
    2420             :                 return false;
    2421          29 :             if (!ifGeneratorClosing.emitThen())   // ITER ... FTYPE FVALUE
    2422             :                 return false;
    2423           0 :             if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER
    2424             :                 return false;
    2425          29 :             if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Normal))
    2426             :                 return false;                     // ITER ... FTYPE FVALUE
    2427          29 :             if (!ifGeneratorClosing.emitEnd())    // ITER ... FTYPE FVALUE
    2428             :                 return false;
    2429             :         }
    2430             : 
    2431        1114 :         if (!tryCatch_->emitEnd())
    2432             :             return false;
    2433             : 
    2434        1114 :         tryCatch_.reset();
    2435        1114 :         numYieldsAtBeginCodeNeedingIterClose_ = UINT32_MAX;
    2436             : 
    2437        1114 :         return true;
    2438             :     }
    2439             : 
    2440           0 :     bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce,
    2441             :                                            CompletionKind completionKind = CompletionKind::Normal) {
    2442           0 :         return emitIteratorCloseInScope(bce,  *bce->innermostEmitterScope(), completionKind);
    2443             :     }
    2444             : 
    2445        1290 :     bool emitIteratorCloseInScope(BytecodeEmitter* bce,
    2446             :                                   EmitterScope& currentScope,
    2447             :                                   CompletionKind completionKind = CompletionKind::Normal) {
    2448        1290 :         ptrdiff_t start = bce->offset();
    2449        1290 :         if (!bce->emitIteratorCloseInScope(currentScope, iterKind_, completionKind,
    2450        1290 :                                            allowSelfHosted_))
    2451             :         {
    2452             :             return false;
    2453             :         }
    2454           0 :         ptrdiff_t end = bce->offset();
    2455        1290 :         return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
    2456             :     }
    2457             : 
    2458         147 :     bool emitPrepareForNonLocalJumpFromScope(BytecodeEmitter* bce,
    2459             :                                              EmitterScope& currentScope,
    2460             :                                              bool isTarget) {
    2461             :         // Pop unnecessary value from the stack.  Effectively this means
    2462             :         // leaving try-catch block.  However, the performing IteratorClose can
    2463             :         // reach the depth for try-catch, and effectively re-enter the
    2464             :         // try-catch block.
    2465           0 :         if (!bce->emit1(JSOP_POP))                        // NEXT ITER
    2466             :             return false;
    2467             : 
    2468             :         // Pop the iterator's next method.
    2469           0 :         if (!bce->emit1(JSOP_SWAP))                       // ITER NEXT
    2470             :             return false;
    2471           0 :         if (!bce->emit1(JSOP_POP))                        // ITER
    2472             :             return false;
    2473             : 
    2474             :         // Clear ITER slot on the stack to tell catch block to avoid performing
    2475             :         // IteratorClose again.
    2476           1 :         if (!bce->emit1(JSOP_UNDEFINED))                  // ITER UNDEF
    2477             :             return false;
    2478           0 :         if (!bce->emit1(JSOP_SWAP))                       // UNDEF ITER
    2479             :             return false;
    2480             : 
    2481         147 :         if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) // UNDEF
    2482             :             return false;
    2483             : 
    2484         147 :         if (isTarget) {
    2485             :             // At the level of the target block, there's bytecode after the
    2486             :             // loop that will pop the next method, the iterator, and the
    2487             :             // value, so push two undefineds to balance the stack.
    2488          44 :             if (!bce->emit1(JSOP_UNDEFINED))              // UNDEF UNDEF
    2489             :                 return false;
    2490          44 :             if (!bce->emit1(JSOP_UNDEFINED))              // UNDEF UNDEF UNDEF
    2491             :                 return false;
    2492             :         } else {
    2493         103 :             if (!bce->emit1(JSOP_POP))                    //
    2494             :                 return false;
    2495             :         }
    2496             : 
    2497             :         return true;
    2498             :     }
    2499             : };
    2500             : 
    2501             : 
    2502       13449 : BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
    2503             :                                  SharedContext* sc, HandleScript script,
    2504             :                                  Handle<LazyScript*> lazyScript,
    2505           0 :                                  uint32_t lineNum, EmitterMode emitterMode)
    2506             :   : sc(sc),
    2507       13449 :     cx(sc->context),
    2508             :     parent(parent),
    2509             :     script(cx, script),
    2510             :     lazyScript(cx, lazyScript),
    2511           0 :     prologue(cx, lineNum),
    2512             :     main(cx, lineNum),
    2513             :     current(&main),
    2514       13449 :     atomIndices(cx->frontendCollectionPool()),
    2515             :     firstLine(lineNum),
    2516             :     maxFixedSlots(0),
    2517             :     maxStackDepth(0),
    2518             :     stackDepth(0),
    2519             :     emitLevel(0),
    2520             :     bodyScopeIndex(UINT32_MAX),
    2521             :     varEmitterScope(nullptr),
    2522             :     innermostNestableControl(nullptr),
    2523             :     innermostEmitterScope_(nullptr),
    2524             :     innermostTDZCheckCache(nullptr),
    2525             : #ifdef DEBUG
    2526             :     unstableEmitterScope(false),
    2527             : #endif
    2528           0 :     constList(cx),
    2529             :     scopeList(cx),
    2530           0 :     tryNoteList(cx),
    2531             :     scopeNoteList(cx),
    2532             :     yieldAndAwaitOffsetList(cx),
    2533             :     typesetCount(0),
    2534             :     hasSingletons(false),
    2535             :     hasTryFinally(false),
    2536             :     emittingRunOnceLambda(false),
    2537             :     emitterMode(emitterMode),
    2538             :     scriptStartOffsetSet(false),
    2539      201731 :     functionBodyEndPosSet(false)
    2540             : {
    2541           0 :     MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
    2542       13448 : }
    2543             : 
    2544           0 : BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
    2545             :                                  BCEParserHandle* handle, SharedContext* sc,
    2546             :                                  HandleScript script, Handle<LazyScript*> lazyScript,
    2547           0 :                                  uint32_t lineNum, EmitterMode emitterMode)
    2548           0 :     : BytecodeEmitter(parent, sc, script, lazyScript, lineNum, emitterMode)
    2549             : {
    2550       12227 :     parser = handle;
    2551           0 : }
    2552             : 
    2553           0 : BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
    2554             :                                  const EitherParser& parser, SharedContext* sc,
    2555             :                                  HandleScript script, Handle<LazyScript*> lazyScript,
    2556        1221 :                                  uint32_t lineNum, EmitterMode emitterMode)
    2557           0 :     : BytecodeEmitter(parent, sc, script, lazyScript, lineNum, emitterMode)
    2558             : {
    2559           0 :     ep_.emplace(parser);
    2560        1221 :     this->parser = ep_.ptr();
    2561        1221 : }
    2562             : 
    2563             : void
    2564           0 : BytecodeEmitter::initFromBodyPosition(TokenPos bodyPosition)
    2565             : {
    2566           0 :     setScriptStartOffsetIfUnset(bodyPosition);
    2567       12227 :     setFunctionBodyEndPos(bodyPosition);
    2568           0 : }
    2569             : 
    2570             : bool
    2571           0 : BytecodeEmitter::init()
    2572             : {
    2573           0 :     return atomIndices.acquire(cx);
    2574             : }
    2575             : 
    2576             : template <typename T>
    2577             : T*
    2578             : BytecodeEmitter::findInnermostNestableControl() const
    2579             : {
    2580       12658 :     return NestableControl::findNearest<T>(innermostNestableControl);
    2581             : }
    2582             : 
    2583             : template <typename T, typename Predicate /* (T*) -> bool */>
    2584             : T*
    2585             : BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
    2586             : {
    2587           0 :     return NestableControl::findNearest<T>(innermostNestableControl, predicate);
    2588             : }
    2589             : 
    2590             : NameLocation
    2591           0 : BytecodeEmitter::lookupName(JSAtom* name)
    2592             : {
    2593      167850 :     return innermostEmitterScope()->lookup(this, name);
    2594             : }
    2595             : 
    2596             : Maybe<NameLocation>
    2597           0 : BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
    2598             : {
    2599       13490 :     return innermostEmitterScope()->locationBoundInScope(name, target);
    2600             : }
    2601             : 
    2602             : Maybe<NameLocation>
    2603        2682 : BytecodeEmitter::locationOfNameBoundInFunctionScope(JSAtom* name, EmitterScope* source)
    2604             : {
    2605        2682 :     EmitterScope* funScope = source;
    2606        5862 :     while (!funScope->scope(this)->is<FunctionScope>())
    2607           0 :         funScope = funScope->enclosingInFrame();
    2608           0 :     return source->locationBoundInScope(name, funScope);
    2609             : }
    2610             : 
    2611             : bool
    2612           0 : BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
    2613             : {
    2614      885534 :     *offset = code().length();
    2615             : 
    2616           0 :     if (!code().growBy(delta)) {
    2617           0 :         ReportOutOfMemory(cx);
    2618           0 :         return false;
    2619             :     }
    2620             :     return true;
    2621             : }
    2622             : 
    2623             : void
    2624      885628 : BytecodeEmitter::updateDepth(ptrdiff_t target)
    2625             : {
    2626           0 :     jsbytecode* pc = code(target);
    2627             : 
    2628      885626 :     int nuses = StackUses(pc);
    2629      885646 :     int ndefs = StackDefs(pc);
    2630             : 
    2631      885663 :     stackDepth -= nuses;
    2632      885663 :     MOZ_ASSERT(stackDepth >= 0);
    2633           0 :     stackDepth += ndefs;
    2634             : 
    2635      885663 :     if ((uint32_t)stackDepth > maxStackDepth)
    2636           0 :         maxStackDepth = stackDepth;
    2637           0 : }
    2638             : 
    2639             : #ifdef DEBUG
    2640             : bool
    2641      834951 : BytecodeEmitter::checkStrictOrSloppy(JSOp op)
    2642             : {
    2643      842633 :     if (IsCheckStrictOp(op) && !sc->strict())
    2644             :         return false;
    2645      836961 :     if (IsCheckSloppyOp(op) && sc->strict())
    2646             :         return false;
    2647           0 :     return true;
    2648             : }
    2649             : #endif
    2650             : 
    2651             : bool
    2652           0 : BytecodeEmitter::emit1(JSOp op)
    2653             : {
    2654           0 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2655             : 
    2656             :     ptrdiff_t offset;
    2657      411873 :     if (!emitCheck(1, &offset))
    2658             :         return false;
    2659             : 
    2660           1 :     jsbytecode* code = this->code(offset);
    2661      411896 :     code[0] = jsbytecode(op);
    2662           0 :     updateDepth(offset);
    2663           0 :     return true;
    2664             : }
    2665             : 
    2666             : bool
    2667           0 : BytecodeEmitter::emit2(JSOp op, uint8_t op1)
    2668             : {
    2669       15074 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2670             : 
    2671             :     ptrdiff_t offset;
    2672           0 :     if (!emitCheck(2, &offset))
    2673             :         return false;
    2674             : 
    2675           0 :     jsbytecode* code = this->code(offset);
    2676           0 :     code[0] = jsbytecode(op);
    2677       15074 :     code[1] = jsbytecode(op1);
    2678           0 :     updateDepth(offset);
    2679       15074 :     return true;
    2680             : }
    2681             : 
    2682             : bool
    2683       50676 : BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
    2684             : {
    2685       50676 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2686             : 
    2687             :     /* These should filter through emitVarOp. */
    2688           0 :     MOZ_ASSERT(!IsArgOp(op));
    2689           0 :     MOZ_ASSERT(!IsLocalOp(op));
    2690             : 
    2691             :     ptrdiff_t offset;
    2692           0 :     if (!emitCheck(3, &offset))
    2693             :         return false;
    2694             : 
    2695       50676 :     jsbytecode* code = this->code(offset);
    2696           0 :     code[0] = jsbytecode(op);
    2697       50676 :     code[1] = op1;
    2698           0 :     code[2] = op2;
    2699       50676 :     updateDepth(offset);
    2700           0 :     return true;
    2701             : }
    2702             : 
    2703             : bool
    2704      161925 : BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset)
    2705             : {
    2706      161925 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2707      161925 :     ptrdiff_t length = 1 + ptrdiff_t(extra);
    2708             : 
    2709             :     ptrdiff_t off;
    2710      161925 :     if (!emitCheck(length, &off))
    2711             :         return false;
    2712             : 
    2713           0 :     jsbytecode* code = this->code(off);
    2714      161933 :     code[0] = jsbytecode(op);
    2715             :     /* The remaining |extra| bytes are set by the caller */
    2716             : 
    2717             :     /*
    2718             :      * Don't updateDepth if op's use-count comes from the immediate
    2719             :      * operand yet to be stored in the extra bytes after op.
    2720             :      */
    2721      161933 :     if (CodeSpec[op].nuses >= 0)
    2722      161933 :         updateDepth(off);
    2723             : 
    2724      161933 :     if (offset)
    2725           0 :         *offset = off;
    2726             :     return true;
    2727             : }
    2728             : 
    2729             : bool
    2730           0 : BytecodeEmitter::emitJumpTarget(JumpTarget* target)
    2731             : {
    2732       76277 :     ptrdiff_t off = offset();
    2733             : 
    2734             :     // Alias consecutive jump targets.
    2735           0 :     if (off == current->lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
    2736        5165 :         target->offset = current->lastTarget.offset;
    2737        5165 :         return true;
    2738             :     }
    2739             : 
    2740           0 :     target->offset = off;
    2741           0 :     current->lastTarget.offset = off;
    2742       71113 :     if (!emit1(JSOP_JUMPTARGET))
    2743             :         return false;
    2744       71114 :     return true;
    2745             : }
    2746             : 
    2747             : void
    2748           0 : JumpList::push(jsbytecode* code, ptrdiff_t jumpOffset)
    2749             : {
    2750       91762 :     SET_JUMP_OFFSET(&code[jumpOffset], offset - jumpOffset);
    2751       45881 :     offset = jumpOffset;
    2752           0 : }
    2753             : 
    2754             : void
    2755           0 : JumpList::patchAll(jsbytecode* code, JumpTarget target)
    2756             : {
    2757             :     ptrdiff_t delta;
    2758           0 :     for (ptrdiff_t jumpOffset = offset; jumpOffset != -1; jumpOffset += delta) {
    2759       45882 :         jsbytecode* pc = &code[jumpOffset];
    2760           0 :         MOZ_ASSERT(IsJumpOpcode(JSOp(*pc)) || JSOp(*pc) == JSOP_LABEL);
    2761           1 :         delta = GET_JUMP_OFFSET(pc);
    2762           1 :         MOZ_ASSERT(delta < 0);
    2763       45882 :         ptrdiff_t span = target.offset - jumpOffset;
    2764       91764 :         SET_JUMP_OFFSET(pc, span);
    2765             :     }
    2766           0 : }
    2767             : 
    2768             : bool
    2769           0 : BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump)
    2770             : {
    2771             :     ptrdiff_t offset;
    2772       45881 :     if (!emitCheck(5, &offset))
    2773             :         return false;
    2774             : 
    2775           0 :     jsbytecode* code = this->code(offset);
    2776       45881 :     code[0] = jsbytecode(op);
    2777           0 :     MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
    2778       91762 :     jump->push(this->code(0), offset);
    2779           0 :     updateDepth(offset);
    2780           1 :     return true;
    2781             : }
    2782             : 
    2783             : bool
    2784           0 : BytecodeEmitter::emitJump(JSOp op, JumpList* jump)
    2785             : {
    2786           0 :     if (!emitJumpNoFallthrough(op, jump))
    2787             :         return false;
    2788       43457 :     if (BytecodeFallsThrough(op)) {
    2789             :         JumpTarget fallthrough;
    2790           1 :         if (!emitJumpTarget(&fallthrough))
    2791           0 :             return false;
    2792             :     }
    2793             :     return true;
    2794             : }
    2795             : 
    2796             : bool
    2797        2425 : BytecodeEmitter::emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump, JumpTarget* fallthrough)
    2798             : {
    2799        2425 :     if (!emitJumpNoFallthrough(op, jump))
    2800             :         return false;
    2801        2425 :     patchJumpsToTarget(*jump, target);
    2802             : 
    2803             :     // Unconditionally create a fallthrough for closing iterators, and as a
    2804             :     // target for break statements.
    2805        2425 :     if (!emitJumpTarget(fallthrough))
    2806             :         return false;
    2807        2425 :     return true;
    2808             : }
    2809             : 
    2810             : void
    2811           0 : BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target)
    2812             : {
    2813           0 :     MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
    2814           1 :     MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
    2815           1 :     MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
    2816             :                   BytecodeIsJumpTarget(JSOp(*code(target.offset))));
    2817       45834 :     jump.patchAll(code(0), target);
    2818           0 : }
    2819             : 
    2820             : bool
    2821       52838 : BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump)
    2822             : {
    2823       52838 :     if (jump.offset == -1)
    2824             :         return true;
    2825             :     JumpTarget target;
    2826       38378 :     if (!emitJumpTarget(&target))
    2827             :         return false;
    2828       38379 :     patchJumpsToTarget(jump, target);
    2829       38379 :     return true;
    2830             : }
    2831             : 
    2832             : bool
    2833           0 : BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
    2834             : {
    2835           0 :     if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
    2836             :         return false;
    2837       97728 :     return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
    2838             : }
    2839             : 
    2840             : bool
    2841       10136 : BytecodeEmitter::emitDupAt(unsigned slotFromTop)
    2842             : {
    2843       10136 :     MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
    2844             : 
    2845       10136 :     if (slotFromTop == 0)
    2846        1072 :         return emit1(JSOP_DUP);
    2847             : 
    2848        9064 :     if (slotFromTop >= JS_BIT(24)) {
    2849           0 :         reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
    2850           0 :         return false;
    2851             :     }
    2852             : 
    2853             :     ptrdiff_t off;
    2854        9064 :     if (!emitN(JSOP_DUPAT, 3, &off))
    2855             :         return false;
    2856             : 
    2857           0 :     jsbytecode* pc = code(off);
    2858        9064 :     SET_UINT24(pc, slotFromTop);
    2859        9064 :     return true;
    2860             : }
    2861             : 
    2862             : bool
    2863           0 : BytecodeEmitter::emitPopN(unsigned n)
    2864             : {
    2865           0 :     MOZ_ASSERT(n != 0);
    2866             : 
    2867           0 :     if (n == 1)
    2868           0 :         return emit1(JSOP_POP);
    2869             : 
    2870             :     // 2 JSOP_POPs (2 bytes) are shorter than JSOP_POPN (3 bytes).
    2871        2807 :     if (n == 2)
    2872        1441 :         return emit1(JSOP_POP) && emit1(JSOP_POP);
    2873             : 
    2874        1366 :     return emitUint16Operand(JSOP_POPN, n);
    2875             : }
    2876             : 
    2877             : bool
    2878           0 : BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind)
    2879             : {
    2880        4158 :     return emit2(JSOP_CHECKISOBJ, uint8_t(kind));
    2881             : }
    2882             : 
    2883             : bool
    2884           0 : BytecodeEmitter::emitCheckIsCallable(CheckIsCallableKind kind)
    2885             : {
    2886           0 :     return emit2(JSOP_CHECKISCALLABLE, uint8_t(kind));
    2887             : }
    2888             : 
    2889             : static inline unsigned
    2890             : LengthOfSetLine(unsigned line)
    2891             : {
    2892      131006 :     return 1 /* SRC_SETLINE */ + (line > SN_4BYTE_OFFSET_MASK ? 4 : 1);
    2893             : }
    2894             : 
    2895             : /* Updates line number notes, not column notes. */
    2896             : bool
    2897           0 : BytecodeEmitter::updateLineNumberNotes(uint32_t offset)
    2898             : {
    2899           0 :     ErrorReporter* er = &parser->errorReporter();
    2900             :     bool onThisLine;
    2901           0 :     if (!er->isOnThisLine(offset, currentLine(), &onThisLine)) {
    2902           0 :         er->reportErrorNoOffset(JSMSG_OUT_OF_MEMORY);
    2903           0 :         return false;
    2904             :     }
    2905             : 
    2906      640259 :     if (!onThisLine) {
    2907      131002 :         unsigned line = er->lineAt(offset);
    2908           0 :         unsigned delta = line - currentLine();
    2909             : 
    2910             :         /*
    2911             :          * Encode any change in the current source line number by using
    2912             :          * either several SRC_NEWLINE notes or just one SRC_SETLINE note,
    2913             :          * whichever consumes less space.
    2914             :          *
    2915             :          * NB: We handle backward line number deltas (possible with for
    2916             :          * loops where the update part is emitted after the body, but its
    2917             :          * line number is <= any line number in the body) here by letting
    2918             :          * unsigned delta_ wrap to a very large number, which triggers a
    2919             :          * SRC_SETLINE.
    2920             :          */
    2921      131006 :         current->currentLine = line;
    2922           0 :         current->lastColumn  = 0;
    2923           0 :         if (delta >= LengthOfSetLine(line)) {
    2924           0 :             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line)))
    2925             :                 return false;
    2926             :         } else {
    2927      130411 :             do {
    2928      130414 :                 if (!newSrcNote(SRC_NEWLINE))
    2929             :                     return false;
    2930             :             } while (--delta != 0);
    2931             :         }
    2932             :     }
    2933             :     return true;
    2934             : }
    2935             : 
    2936             : /* Updates the line number and column number information in the source notes. */
    2937             : bool
    2938      184122 : BytecodeEmitter::updateSourceCoordNotes(uint32_t offset)
    2939             : {
    2940      184122 :     if (!updateLineNumberNotes(offset))
    2941             :         return false;
    2942             : 
    2943      184121 :     uint32_t columnIndex = parser->errorReporter().columnAt(offset);
    2944           0 :     ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(current->lastColumn);
    2945      184123 :     if (colspan != 0) {
    2946             :         // If the column span is so large that we can't store it, then just
    2947             :         // discard this information. This can happen with minimized or otherwise
    2948             :         // machine-generated code. Even gigantic column numbers are still
    2949             :         // valuable if you have a source map to relate them to something real;
    2950             :         // but it's better to fail soft here.
    2951      137854 :         if (!SN_REPRESENTABLE_COLSPAN(colspan))
    2952             :             return true;
    2953      137854 :         if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)))
    2954             :             return false;
    2955      137858 :         current->lastColumn = columnIndex;
    2956             :     }
    2957             :     return true;
    2958             : }
    2959             : 
    2960             : bool
    2961        2407 : BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
    2962             : {
    2963        2407 :     if (nextpn) {
    2964             :         /*
    2965             :          * Try to give the JSOP_LOOPHEAD the same line number as the next
    2966             :          * instruction. nextpn is often a block, in which case the next
    2967             :          * instruction typically comes from the first statement inside.
    2968             :          */
    2969         910 :         if (nextpn->isKind(ParseNodeKind::LexicalScope))
    2970         843 :             nextpn = nextpn->scopeBody();
    2971        1753 :         MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::StatementList), nextpn->isArity(PN_LIST));
    2972         910 :         if (nextpn->isKind(ParseNodeKind::StatementList) && nextpn->pn_head)
    2973         842 :             nextpn = nextpn->pn_head;
    2974         910 :         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
    2975             :             return false;
    2976             :     }
    2977             : 
    2978        2407 :     *top = { offset() };
    2979        2407 :     return emit1(JSOP_LOOPHEAD);
    2980             : }
    2981             : 
    2982             : bool
    2983           0 : BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
    2984             : {
    2985           0 :     if (nextpn) {
    2986             :         /* Update the line number, as for LOOPHEAD. */
    2987           0 :         if (nextpn->isKind(ParseNodeKind::LexicalScope))
    2988           8 :             nextpn = nextpn->scopeBody();
    2989        1742 :         MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::StatementList), nextpn->isArity(PN_LIST));
    2990           0 :         if (nextpn->isKind(ParseNodeKind::StatementList) && nextpn->pn_head)
    2991           0 :             nextpn = nextpn->pn_head;
    2992           0 :         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
    2993             :             return false;
    2994             :     }
    2995             : 
    2996        2407 :     JumpTarget entry{ offset() };
    2997        2407 :     patchJumpsToTarget(entryJump, entry);
    2998             : 
    2999           0 :     LoopControl& loopInfo = innermostNestableControl->as<LoopControl>();
    3000        2407 :     MOZ_ASSERT(loopInfo.loopDepth() > 0);
    3001             : 
    3002        2407 :     uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loopInfo.loopDepth(),
    3003        4814 :                                                                loopInfo.canIonOsr());
    3004           0 :     return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
    3005             : }
    3006             : 
    3007             : void
    3008           0 : BytecodeEmitter::checkTypeSet(JSOp op)
    3009             : {
    3010      296303 :     if (CodeSpec[op].format & JOF_TYPESET) {
    3011      198026 :         if (typesetCount < UINT16_MAX)
    3012           0 :             typesetCount++;
    3013             :     }
    3014           0 : }
    3015             : 
    3016             : bool
    3017        1813 : BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
    3018             : {
    3019        1813 :     MOZ_ASSERT(operand <= UINT16_MAX);
    3020           0 :     if (!emit3(op, UINT16_LO(operand), UINT16_HI(operand)))
    3021             :         return false;
    3022             :     checkTypeSet(op);
    3023             :     return true;
    3024             : }
    3025             : 
    3026             : bool
    3027           0 : BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand)
    3028             : {
    3029             :     ptrdiff_t off;
    3030        7215 :     if (!emitN(op, 4, &off))
    3031             :         return false;
    3032           0 :     SET_UINT32(code(off), operand);
    3033             :     checkTypeSet(op);
    3034             :     return true;
    3035             : }
    3036             : 
    3037             : namespace {
    3038             : 
    3039             : class NonLocalExitControl
    3040             : {
    3041             :   public:
    3042             :     enum Kind
    3043             :     {
    3044             :         // IteratorClose is handled especially inside the exception unwinder.
    3045             :         Throw,
    3046             : 
    3047             :         // A 'continue' statement does not call IteratorClose for the loop it
    3048             :         // is continuing, i.e. excluding the target loop.
    3049             :         Continue,
    3050             : 
    3051             :         // A 'break' or 'return' statement does call IteratorClose for the
    3052             :         // loop it is breaking out of or returning from, i.e. including the
    3053             :         // target loop.
    3054             :         Break,
    3055             :         Return
    3056             :     };
    3057             : 
    3058             :   private:
    3059             :     BytecodeEmitter* bce_;
    3060             :     const uint32_t savedScopeNoteIndex_;
    3061             :     const int savedDepth_;
    3062             :     uint32_t openScopeNoteIndex_;
    3063             :     Kind kind_;
    3064             : 
    3065             :     NonLocalExitControl(const NonLocalExitControl&) = delete;
    3066             : 
    3067             :     MOZ_MUST_USE bool leaveScope(BytecodeEmitter::EmitterScope* scope);
    3068             : 
    3069             :   public:
    3070             :     NonLocalExitControl(BytecodeEmitter* bce, Kind kind)
    3071           0 :       : bce_(bce),
    3072       25692 :         savedScopeNoteIndex_(bce->scopeNoteList.length()),
    3073           0 :         savedDepth_(bce->stackDepth),
    3074       12846 :         openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
    3075           0 :         kind_(kind)
    3076             :     { }
    3077             : 
    3078       25692 :     ~NonLocalExitControl() {
    3079       36328 :         for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length(); n++)
    3080       10636 :             bce_->scopeNoteList.recordEnd(n, bce_->offset(), bce_->inPrologue());
    3081       12846 :         bce_->stackDepth = savedDepth_;
    3082           0 :     }
    3083             : 
    3084             :     MOZ_MUST_USE bool prepareForNonLocalJump(BytecodeEmitter::NestableControl* target);
    3085             : 
    3086             :     MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
    3087           0 :         return prepareForNonLocalJump(nullptr);
    3088             :     }
    3089             : };
    3090             : 
    3091             : bool
    3092        5318 : NonLocalExitControl::leaveScope(BytecodeEmitter::EmitterScope* es)
    3093             : {
    3094        5318 :     if (!es->leave(bce_, /* nonLocal = */ true))
    3095             :         return false;
    3096             : 
    3097             :     // As we pop each scope due to the non-local jump, emit notes that
    3098             :     // record the extent of the enclosing scope. These notes will have
    3099             :     // their ends recorded in ~NonLocalExitControl().
    3100           0 :     uint32_t enclosingScopeIndex = ScopeNote::NoScopeIndex;
    3101        5318 :     if (es->enclosingInFrame())
    3102        5318 :         enclosingScopeIndex = es->enclosingInFrame()->index();
    3103       10636 :     if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(), bce_->inPrologue(),
    3104             :                                     openScopeNoteIndex_))
    3105             :         return false;
    3106           0 :     openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
    3107             : 
    3108        5318 :     return true;
    3109             : }
    3110             : 
    3111             : /*
    3112             :  * Emit additional bytecode(s) for non-local jumps.
    3113             :  */
    3114             : bool
    3115           0 : NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* target)
    3116             : {
    3117             :     using NestableControl = BytecodeEmitter::NestableControl;
    3118             :     using EmitterScope = BytecodeEmitter::EmitterScope;
    3119             : 
    3120           0 :     EmitterScope* es = bce_->innermostEmitterScope();
    3121       12846 :     int npops = 0;
    3122             : 
    3123       38538 :     AutoCheckUnstableEmitterScope cues(bce_);
    3124             : 
    3125             :     // For 'continue', 'break', and 'return' statements, emit IteratorClose
    3126             :     // bytecode inline. 'continue' statements do not call IteratorClose for
    3127             :     // the loop they are continuing.
    3128           0 :     bool emitIteratorClose = kind_ == Continue || kind_ == Break || kind_ == Return;
    3129           0 :     bool emitIteratorCloseAtTarget = emitIteratorClose && kind_ != Continue;
    3130             : 
    3131       26008 :     auto flushPops = [&npops](BytecodeEmitter* bce) {
    3132       13004 :         if (npops && !bce->emitPopN(npops))
    3133             :             return false;
    3134       13004 :         npops = 0;
    3135       13004 :         return true;
    3136       12846 :     };
    3137             : 
    3138             :     // Walk the nestable control stack and patch jumps.
    3139           0 :     for (NestableControl* control = bce_->innermostNestableControl;
    3140       14066 :          control != target;
    3141        1220 :          control = control->enclosing())
    3142             :     {
    3143             :         // Walk the scope stack and leave the scopes we entered. Leaving a scope
    3144             :         // may emit administrative ops like JSOP_POPLEXICALENV but never anything
    3145             :         // that manipulates the stack.
    3146        2160 :         for (; es != control->emitterScope(); es = es->enclosingInFrame()) {
    3147         470 :             if (!leaveScope(es))
    3148             :                 return false;
    3149             :         }
    3150             : 
    3151        1220 :         switch (control->kind()) {
    3152             :           case StatementKind::Finally: {
    3153           0 :             TryFinallyControl& finallyControl = control->as<TryFinallyControl>();
    3154          49 :             if (finallyControl.emittingSubroutine()) {
    3155             :                 /*
    3156             :                  * There's a [exception or hole, retsub pc-index] pair and the
    3157             :                  * possible return value on the stack that we need to pop.
    3158             :                  */
    3159           0 :                 npops += 3;
    3160             :             } else {
    3161          49 :                 if (!flushPops(bce_))
    3162             :                     return false;
    3163           0 :                 if (!bce_->emitJump(JSOP_GOSUB, &finallyControl.gosubs)) // ...
    3164             :                     return false;
    3165             :             }
    3166             :             break;
    3167             :           }
    3168             : 
    3169             :           case StatementKind::ForOfLoop:
    3170         103 :             if (emitIteratorClose) {
    3171           0 :                 if (!flushPops(bce_))
    3172             :                     return false;
    3173             : 
    3174           0 :                 ForOfLoopControl& loopinfo = control->as<ForOfLoopControl>();
    3175           0 :                 if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es,
    3176             :                                                                   /* isTarget = */ false))
    3177             :                 {                                         // ...
    3178             :                     return false;
    3179             :                 }
    3180             :             } else {
    3181             :                 // The iterator next method, the iterator, and the current
    3182             :                 // value are on the stack.
    3183           0 :                 npops += 3;
    3184             :             }
    3185             :             break;
    3186             : 
    3187             :           case StatementKind::ForInLoop:
    3188           0 :             if (!flushPops(bce_))
    3189             :                 return false;
    3190             : 
    3191             :             // The iterator and the current value are on the stack.
    3192           6 :             if (!bce_->emit1(JSOP_POP))                   // ... ITER
    3193             :                 return false;
    3194           0 :             if (!bce_->emit1(JSOP_ENDITER))               // ...
    3195             :                 return false;
    3196             :             break;
    3197             : 
    3198             :           default:
    3199             :             break;
    3200             :         }
    3201             :     }
    3202             : 
    3203           0 :     if (!flushPops(bce_))
    3204             :         return false;
    3205             : 
    3206           0 :     if (target && emitIteratorCloseAtTarget && target->is<ForOfLoopControl>()) {
    3207          44 :         ForOfLoopControl& loopinfo = target->as<ForOfLoopControl>();
    3208          44 :         if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es,
    3209             :                                                           /* isTarget = */ true))
    3210             :         {                                                 // ... UNDEF UNDEF UNDEF
    3211             :             return false;
    3212             :         }
    3213             :     }
    3214             : 
    3215           0 :     EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope;
    3216       22542 :     for (; es != targetEmitterScope; es = es->enclosingInFrame()) {
    3217           0 :         if (!leaveScope(es))
    3218             :             return false;
    3219             :     }
    3220             : 
    3221             :     return true;
    3222             : }
    3223             : 
    3224             : }  // anonymous namespace
    3225             : 
    3226             : bool
    3227        1525 : BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteType noteType)
    3228             : {
    3229             :     NonLocalExitControl nle(this, noteType == SRC_CONTINUE
    3230             :                                   ? NonLocalExitControl::Continue
    3231           0 :                                   : NonLocalExitControl::Break);
    3232             : 
    3233        1525 :     if (!nle.prepareForNonLocalJump(target))
    3234             :         return false;
    3235             : 
    3236        1525 :     if (noteType != SRC_NULL) {
    3237           0 :         if (!newSrcNote(noteType))
    3238             :             return false;
    3239             :     }
    3240             : 
    3241        1525 :     return emitJump(JSOP_GOTO, jumplist);
    3242             : }
    3243             : 
    3244             : Scope*
    3245           0 : BytecodeEmitter::innermostScope() const
    3246             : {
    3247           0 :     return innermostEmitterScope()->scope(this);
    3248             : }
    3249             : 
    3250             : bool
    3251           1 : BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
    3252             : {
    3253           0 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    3254             : 
    3255       30915 :     const size_t len = 1 + UINT32_INDEX_LEN;
    3256       30915 :     MOZ_ASSERT(len == size_t(CodeSpec[op].length));
    3257             : 
    3258             :     ptrdiff_t offset;
    3259           0 :     if (!emitCheck(len, &offset))
    3260             :         return false;
    3261             : 
    3262       30914 :     jsbytecode* code = this->code(offset);
    3263       30914 :     code[0] = jsbytecode(op);
    3264       30914 :     SET_UINT32_INDEX(code, index);
    3265           1 :     checkTypeSet(op);
    3266       30914 :     updateDepth(offset);
    3267           0 :     return true;
    3268             : }
    3269             : 
    3270             : bool
    3271           0 : BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
    3272             : {
    3273           0 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    3274             : 
    3275      164733 :     const size_t len = CodeSpec[op].length;
    3276      164733 :     MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
    3277             : 
    3278             :     ptrdiff_t offset;
    3279      164733 :     if (!emitCheck(len, &offset))
    3280             :         return false;
    3281             : 
    3282      164734 :     jsbytecode* code = this->code(offset);
    3283      164734 :     code[0] = jsbytecode(op);
    3284      164734 :     SET_UINT32_INDEX(code, index);
    3285           0 :     checkTypeSet(op);
    3286      164734 :     updateDepth(offset);
    3287           0 :     return true;
    3288             : }
    3289             : 
    3290             : bool
    3291      153046 : BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op)
    3292             : {
    3293           0 :     MOZ_ASSERT(atom);
    3294      153046 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
    3295             : 
    3296             :     // .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of
    3297             :     // JSOP_GETNAME etc, to bypass |with| objects on the scope chain.
    3298             :     // It's safe to emit .this lookups though because |with| objects skip
    3299             :     // those.
    3300      215258 :     MOZ_ASSERT_IF(op == JSOP_GETNAME || op == JSOP_GETGNAME,
    3301             :                   atom != cx->names().dotGenerator);
    3302             : 
    3303      252628 :     if (op == JSOP_GETPROP && atom == cx->names().length) {
    3304             :         /* Specialize length accesses for the interpreter. */
    3305           0 :         op = JSOP_LENGTH;
    3306             :     }
    3307             : 
    3308             :     uint32_t index;
    3309           0 :     if (!makeAtomIndex(atom, &index))
    3310             :         return false;
    3311             : 
    3312           0 :     return emitIndexOp(op, index);
    3313             : }
    3314             : 
    3315             : bool
    3316      104131 : BytecodeEmitter::emitAtomOp(ParseNode* pn, JSOp op)
    3317             : {
    3318           0 :     MOZ_ASSERT(pn->pn_atom != nullptr);
    3319      104131 :     return emitAtomOp(pn->pn_atom, op);
    3320             : }
    3321             : 
    3322             : bool
    3323        1962 : BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op)
    3324             : {
    3325        1962 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE);
    3326           0 :     MOZ_ASSERT(index < scopeList.length());
    3327           0 :     return emitIndex32(op, index);
    3328             : }
    3329             : 
    3330             : bool
    3331           1 : BytecodeEmitter::emitInternedObjectOp(uint32_t index, JSOp op)
    3332             : {
    3333           1 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
    3334         166 :     MOZ_ASSERT(index < objectList.length);
    3335           0 :     return emitIndex32(op, index);
    3336             : }
    3337             : 
    3338             : bool
    3339           0 : BytecodeEmitter::emitObjectOp(ObjectBox* objbox, JSOp op)
    3340             : {
    3341         159 :     return emitInternedObjectOp(objectList.add(objbox), op);
    3342             : }
    3343             : 
    3344             : bool
    3345           7 : BytecodeEmitter::emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op)
    3346             : {
    3347           7 :     uint32_t index = objectList.add(objbox1);
    3348           0 :     objectList.add(objbox2);
    3349           7 :     return emitInternedObjectOp(index, op);
    3350             : }
    3351             : 
    3352             : bool
    3353           0 : BytecodeEmitter::emitRegExp(uint32_t index)
    3354             : {
    3355           0 :     return emitIndex32(JSOP_REGEXP, index);
    3356             : }
    3357             : 
    3358             : bool
    3359       86521 : BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot)
    3360             : {
    3361       86521 :     MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD);
    3362       86521 :     MOZ_ASSERT(IsLocalOp(op));
    3363             : 
    3364             :     ptrdiff_t off;
    3365       86521 :     if (!emitN(op, LOCALNO_LEN, &off))
    3366             :         return false;
    3367             : 
    3368      173050 :     SET_LOCALNO(code(off), slot);
    3369           0 :     return true;
    3370             : }
    3371             : 
    3372             : bool
    3373       23280 : BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot)
    3374             : {
    3375       23280 :     MOZ_ASSERT(IsArgOp(op));
    3376             :     ptrdiff_t off;
    3377           0 :     if (!emitN(op, ARGNO_LEN, &off))
    3378             :         return false;
    3379             : 
    3380       46560 :     SET_ARGNO(code(off), slot);
    3381       23280 :     return true;
    3382             : }
    3383             : 
    3384             : bool
    3385           0 : BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec)
    3386             : {
    3387           0 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD);
    3388             : 
    3389       33344 :     unsigned n = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
    3390       33344 :     MOZ_ASSERT(int(n) + 1 /* op */ == CodeSpec[op].length);
    3391             : 
    3392             :     ptrdiff_t off;
    3393           1 :     if (!emitN(op, n, &off))
    3394             :         return false;
    3395             : 
    3396       33344 :     jsbytecode* pc = code(off);
    3397       66688 :     SET_ENVCOORD_HOPS(pc, ec.hops());
    3398           0 :     pc += ENVCOORD_HOPS_LEN;
    3399           0 :     SET_ENVCOORD_SLOT(pc, ec.slot());
    3400           0 :     pc += ENVCOORD_SLOT_LEN;
    3401             :     checkTypeSet(op);
    3402             :     return true;
    3403             : }
    3404             : 
    3405             : static JSOp
    3406           0 : GetIncDecInfo(ParseNodeKind kind, bool* post)
    3407             : {
    3408         648 :     MOZ_ASSERT(kind == ParseNodeKind::PostIncrement ||
    3409             :                kind == ParseNodeKind::PreIncrement ||
    3410             :                kind == ParseNodeKind::PostDecrement ||
    3411             :                kind == ParseNodeKind::PreDecrement);
    3412         648 :     *post = kind == ParseNodeKind::PostIncrement || kind == ParseNodeKind::PostDecrement;
    3413             :     return (kind == ParseNodeKind::PostIncrement || kind == ParseNodeKind::PreIncrement)
    3414         648 :            ? JSOP_ADD
    3415         648 :            : JSOP_SUB;
    3416             : }
    3417             : 
    3418             : JSOp
    3419           0 : BytecodeEmitter::strictifySetNameOp(JSOp op)
    3420             : {
    3421           0 :     switch (op) {
    3422             :       case JSOP_SETNAME:
    3423           0 :         if (sc->strict())
    3424         159 :             op = JSOP_STRICTSETNAME;
    3425             :         break;
    3426             :       case JSOP_SETGNAME:
    3427           0 :         if (sc->strict())
    3428           0 :             op = JSOP_STRICTSETGNAME;
    3429             :         break;
    3430             :         default:;
    3431             :     }
    3432           0 :     return op;
    3433             : }
    3434             : 
    3435             : bool
    3436       31591 : BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
    3437             : {
    3438           0 :     if (!CheckRecursionLimit(cx))
    3439             :         return false;
    3440             : 
    3441             :  restart:
    3442             : 
    3443       31595 :     switch (pn->getKind()) {
    3444             :       // Trivial cases with no side effects.
    3445             :       case ParseNodeKind::EmptyStatement:
    3446             :       case ParseNodeKind::String:
    3447             :       case ParseNodeKind::TemplateString:
    3448             :       case ParseNodeKind::RegExp:
    3449             :       case ParseNodeKind::True:
    3450             :       case ParseNodeKind::False:
    3451             :       case ParseNodeKind::Null:
    3452             :       case ParseNodeKind::RawUndefined:
    3453             :       case ParseNodeKind::Elision:
    3454             :       case ParseNodeKind::Generator:
    3455             :       case ParseNodeKind::Number:
    3456             :       case ParseNodeKind::ObjectPropertyName:
    3457           0 :         MOZ_ASSERT(pn->isArity(PN_NULLARY));
    3458           0 :         *answer = false;
    3459         232 :         return true;
    3460             : 
    3461             :       // |this| can throw in derived class constructors, including nested arrow
    3462             :       // functions or eval.
    3463             :       case ParseNodeKind::This:
    3464           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3465           0 :         *answer = sc->needsThisTDZChecks();
    3466           0 :         return true;
    3467             : 
    3468             :       // Trivial binary nodes with more token pos holders.
    3469             :       case ParseNodeKind::NewTarget:
    3470             :       case ParseNodeKind::ImportMeta:
    3471           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3472           0 :         MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
    3473           0 :         MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
    3474           0 :         *answer = false;
    3475           0 :         return true;
    3476             : 
    3477             :       case ParseNodeKind::Break:
    3478             :       case ParseNodeKind::Continue:
    3479             :       case ParseNodeKind::Debugger:
    3480           0 :         MOZ_ASSERT(pn->isArity(PN_NULLARY));
    3481           0 :         *answer = true;
    3482           0 :         return true;
    3483             : 
    3484             :       // Watch out for getters!
    3485             :       case ParseNodeKind::Dot:
    3486           0 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3487           0 :         *answer = true;
    3488          18 :         return true;
    3489             : 
    3490             :       // Unary cases with side effects only if the child has them.
    3491             :       case ParseNodeKind::TypeOfExpr:
    3492             :       case ParseNodeKind::Void:
    3493             :       case ParseNodeKind::Not:
    3494           4 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3495           4 :         return checkSideEffects(pn->pn_kid, answer);
    3496             : 
    3497             :       // Even if the name expression is effect-free, performing ToPropertyKey on
    3498             :       // it might not be effect-free:
    3499             :       //
    3500             :       //   RegExp.prototype.toString = () => { throw 42; };
    3501             :       //   ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
    3502             :       //
    3503             :       //   function Q() {
    3504             :       //     ({ [new.target]: 0 });
    3505             :       //   }
    3506             :       //   Q.toString = () => { throw 17; };
    3507             :       //   new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
    3508             :       case ParseNodeKind::ComputedName:
    3509           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3510           0 :         *answer = true;
    3511           0 :         return true;
    3512             : 
    3513             :       // Looking up or evaluating the associated name could throw.
    3514             :       case ParseNodeKind::TypeOfName:
    3515           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3516           0 :         *answer = true;
    3517           0 :         return true;
    3518             : 
    3519             :       // This unary case has side effects on the enclosing object, sure.  But
    3520             :       // that's not the question this function answers: it's whether the
    3521             :       // operation may have a side effect on something *other* than the result
    3522             :       // of the overall operation in which it's embedded.  The answer to that
    3523             :       // is no, because an object literal having a mutated prototype only
    3524             :       // produces a value, without affecting anything else.
    3525             :       case ParseNodeKind::MutateProto:
    3526           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3527           0 :         return checkSideEffects(pn->pn_kid, answer);
    3528             : 
    3529             :       // Unary cases with obvious side effects.
    3530             :       case ParseNodeKind::PreIncrement:
    3531             :       case ParseNodeKind::PostIncrement:
    3532             :       case ParseNodeKind::PreDecrement:
    3533             :       case ParseNodeKind::PostDecrement:
    3534             :       case ParseNodeKind::Throw:
    3535         205 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3536         205 :         *answer = true;
    3537         205 :         return true;
    3538             : 
    3539             :       // These might invoke valueOf/toString, even with a subexpression without
    3540             :       // side effects!  Consider |+{ valueOf: null, toString: null }|.
    3541             :       case ParseNodeKind::BitNot:
    3542             :       case ParseNodeKind::Pos:
    3543             :       case ParseNodeKind::Neg:
    3544           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3545           0 :         *answer = true;
    3546           0 :         return true;
    3547             : 
    3548             :       // This invokes the (user-controllable) iterator protocol.
    3549             :       case ParseNodeKind::Spread:
    3550           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3551           0 :         *answer = true;
    3552           0 :         return true;
    3553             : 
    3554             :       case ParseNodeKind::InitialYield:
    3555             :       case ParseNodeKind::YieldStar:
    3556             :       case ParseNodeKind::Yield:
    3557             :       case ParseNodeKind::Await:
    3558         665 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3559         665 :         *answer = true;
    3560         665 :         return true;
    3561             : 
    3562             :       // Deletion generally has side effects, even if isolated cases have none.
    3563             :       case ParseNodeKind::DeleteName:
    3564             :       case ParseNodeKind::DeleteProp:
    3565             :       case ParseNodeKind::DeleteElem:
    3566         360 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3567         360 :         *answer = true;
    3568         360 :         return true;
    3569             : 
    3570             :       // Deletion of a non-Reference expression has side effects only through
    3571             :       // evaluating the expression.
    3572             :       case ParseNodeKind::DeleteExpr: {
    3573           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3574           0 :         ParseNode* expr = pn->pn_kid;
    3575           0 :         return checkSideEffects(expr, answer);
    3576             :       }
    3577             : 
    3578             :       case ParseNodeKind::ExpressionStatement:
    3579           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3580           0 :         return checkSideEffects(pn->pn_kid, answer);
    3581             : 
    3582             :       // Binary cases with obvious side effects.
    3583             :       case ParseNodeKind::Assign:
    3584             :       case ParseNodeKind::AddAssign:
    3585             :       case ParseNodeKind::SubAssign:
    3586             :       case ParseNodeKind::BitOrAssign:
    3587             :       case ParseNodeKind::BitXorAssign:
    3588             :       case ParseNodeKind::BitAndAssign:
    3589             :       case ParseNodeKind::LshAssign:
    3590             :       case ParseNodeKind::RshAssign:
    3591             :       case ParseNodeKind::UrshAssign:
    3592             :       case ParseNodeKind::MulAssign:
    3593             :       case ParseNodeKind::DivAssign:
    3594             :       case ParseNodeKind::ModAssign:
    3595             :       case ParseNodeKind::PowAssign:
    3596             :       case ParseNodeKind::SetThis:
    3597       11522 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3598       11522 :         *answer = true;
    3599       11522 :         return true;
    3600             : 
    3601             :       case ParseNodeKind::StatementList:
    3602             :       // Strict equality operations and logical operators are well-behaved and
    3603             :       // perform no conversions.
    3604             :       case ParseNodeKind::Or:
    3605             :       case ParseNodeKind::And:
    3606             :       case ParseNodeKind::StrictEq:
    3607             :       case ParseNodeKind::StrictNe:
    3608             :       // Any subexpression of a comma expression could be effectful.
    3609             :       case ParseNodeKind::Comma:
    3610           9 :         MOZ_ASSERT(pn->pn_count > 0);
    3611             :         MOZ_FALLTHROUGH;
    3612             :       // Subcomponents of a literal may be effectful.
    3613             :       case ParseNodeKind::Array:
    3614             :       case ParseNodeKind::Object:
    3615           9 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3616           9 :         for (ParseNode* item = pn->pn_head; item; item = item->pn_next) {
    3617           9 :             if (!checkSideEffects(item, answer))
    3618             :                 return false;
    3619           0 :             if (*answer)
    3620             :                 return true;
    3621             :         }
    3622             :         return true;
    3623             : 
    3624             :       // Most other binary operations (parsed as lists in SpiderMonkey) may
    3625             :       // perform conversions triggering side effects.  Math operations perform
    3626             :       // ToNumber and may fail invoking invalid user-defined toString/valueOf:
    3627             :       // |5 < { toString: null }|.  |instanceof| throws if provided a
    3628             :       // non-object constructor: |null instanceof null|.  |in| throws if given
    3629             :       // a non-object RHS: |5 in null|.
    3630             :       case ParseNodeKind::BitOr:
    3631             :       case ParseNodeKind::BitXor:
    3632             :       case ParseNodeKind::BitAnd:
    3633             :       case ParseNodeKind::Eq:
    3634             :       case ParseNodeKind::Ne:
    3635             :       case ParseNodeKind::Lt:
    3636             :       case ParseNodeKind::Le:
    3637             :       case ParseNodeKind::Gt:
    3638             :       case ParseNodeKind::Ge:
    3639             :       case ParseNodeKind::InstanceOf:
    3640             :       case ParseNodeKind::In:
    3641             :       case ParseNodeKind::Lsh:
    3642             :       case ParseNodeKind::Rsh:
    3643             :       case ParseNodeKind::Ursh:
    3644             :       case ParseNodeKind::Add:
    3645             :       case ParseNodeKind::Sub:
    3646             :       case ParseNodeKind::Star:
    3647             :       case ParseNodeKind::Div:
    3648             :       case ParseNodeKind::Mod:
    3649             :       case ParseNodeKind::Pow:
    3650           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3651           0 :         MOZ_ASSERT(pn->pn_count >= 2);
    3652           0 :         *answer = true;
    3653           0 :         return true;
    3654             : 
    3655             :       case ParseNodeKind::Colon:
    3656             :       case ParseNodeKind::Case:
    3657           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3658           0 :         if (!checkSideEffects(pn->pn_left, answer))
    3659             :             return false;
    3660           0 :         if (*answer)
    3661             :             return true;
    3662           0 :         return checkSideEffects(pn->pn_right, answer);
    3663             : 
    3664             :       // More getters.
    3665             :       case ParseNodeKind::Elem:
    3666           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3667           0 :         *answer = true;
    3668           0 :         return true;
    3669             : 
    3670             :       // These affect visible names in this code, or in other code.
    3671             :       case ParseNodeKind::Import:
    3672             :       case ParseNodeKind::ExportFrom:
    3673             :       case ParseNodeKind::ExportDefault:
    3674           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3675           0 :         *answer = true;
    3676           0 :         return true;
    3677             : 
    3678             :       // Likewise.
    3679             :       case ParseNodeKind::Export:
    3680           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3681           0 :         *answer = true;
    3682           0 :         return true;
    3683             : 
    3684             :       // Every part of a loop might be effect-free, but looping infinitely *is*
    3685             :       // an effect.  (Language lawyer trivia: C++ says threads can be assumed
    3686             :       // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
    3687             :       // implementation's equivalent of the below could set |*answer = false;|
    3688             :       // if all loop sub-nodes set |*answer = false|!)
    3689             :       case ParseNodeKind::DoWhile:
    3690             :       case ParseNodeKind::While:
    3691             :       case ParseNodeKind::For:
    3692           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3693           0 :         *answer = true;
    3694           0 :         return true;
    3695             : 
    3696             :       // Declarations affect the name set of the relevant scope.
    3697             :       case ParseNodeKind::Var:
    3698             :       case ParseNodeKind::Const:
    3699             :       case ParseNodeKind::Let:
    3700           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3701           0 :         *answer = true;
    3702           0 :         return true;
    3703             : 
    3704             :       case ParseNodeKind::If:
    3705             :       case ParseNodeKind::Conditional:
    3706           1 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3707           1 :         if (!checkSideEffects(pn->pn_kid1, answer))
    3708             :             return false;
    3709           1 :         if (*answer)
    3710             :             return true;
    3711           0 :         if (!checkSideEffects(pn->pn_kid2, answer))
    3712             :             return false;
    3713           0 :         if (*answer)
    3714             :             return true;
    3715           0 :         if ((pn = pn->pn_kid3))
    3716             :             goto restart;
    3717             :         return true;
    3718             : 
    3719             :       // Function calls can invoke non-local code.
    3720             :       case ParseNodeKind::New:
    3721             :       case ParseNodeKind::Call:
    3722             :       case ParseNodeKind::TaggedTemplate:
    3723             :       case ParseNodeKind::SuperCall:
    3724       18573 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3725       18573 :         *answer = true;
    3726           1 :         return true;
    3727             : 
    3728             :       case ParseNodeKind::Pipeline:
    3729           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3730           0 :         MOZ_ASSERT(pn->pn_count >= 2);
    3731           0 :         *answer = true;
    3732           0 :         return true;
    3733             : 
    3734             :       // Classes typically introduce names.  Even if no name is introduced,
    3735             :       // the heritage and/or class body (through computed property names)
    3736             :       // usually have effects.
    3737             :       case ParseNodeKind::Class:
    3738           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3739           0 :         *answer = true;
    3740           0 :         return true;
    3741             : 
    3742             :       // |with| calls |ToObject| on its expression and so throws if that value
    3743             :       // is null/undefined.
    3744             :       case ParseNodeKind::With:
    3745           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3746           0 :         *answer = true;
    3747           0 :         return true;
    3748             : 
    3749             :       case ParseNodeKind::Return:
    3750           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3751           0 :         *answer = true;
    3752           0 :         return true;
    3753             : 
    3754             :       case ParseNodeKind::Name:
    3755           6 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3756           6 :         *answer = true;
    3757           6 :         return true;
    3758             : 
    3759             :       // Shorthands could trigger getters: the |x| in the object literal in
    3760             :       // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
    3761             :       // one.  (Of course, it isn't necessary to use |with| for a shorthand to
    3762             :       // trigger a getter.)
    3763             :       case ParseNodeKind::Shorthand:
    3764           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3765           0 :         *answer = true;
    3766           0 :         return true;
    3767             : 
    3768             :       case ParseNodeKind::Function:
    3769           0 :         MOZ_ASSERT(pn->isArity(PN_CODE));
    3770             :         /*
    3771             :          * A named function, contrary to ES3, is no longer effectful, because
    3772             :          * we bind its name lexically (using JSOP_CALLEE) instead of creating
    3773             :          * an Object instance and binding a readonly, permanent property in it
    3774             :          * (the object and binding can be detected and hijacked or captured).
    3775             :          * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
    3776             :          */
    3777           0 :         *answer = false;
    3778           0 :         return true;
    3779             : 
    3780             :       case ParseNodeKind::Module:
    3781           0 :         *answer = false;
    3782           0 :         return true;
    3783             : 
    3784             :       case ParseNodeKind::Try:
    3785           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3786           0 :         if (!checkSideEffects(pn->pn_kid1, answer))
    3787             :             return false;
    3788           0 :         if (*answer)
    3789             :             return true;
    3790           0 :         if (ParseNode* catchScope = pn->pn_kid2) {
    3791           0 :             MOZ_ASSERT(catchScope->isKind(ParseNodeKind::LexicalScope));
    3792           0 :             if (!checkSideEffects(catchScope, answer))
    3793             :                 return false;
    3794           0 :             if (*answer)
    3795             :                 return true;
    3796             :         }
    3797           0 :         if (ParseNode* finallyBlock = pn->pn_kid3) {
    3798           0 :             if (!checkSideEffects(finallyBlock, answer))
    3799             :                 return false;
    3800             :         }
    3801             :         return true;
    3802             : 
    3803             :       case ParseNodeKind::Catch:
    3804           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3805           0 :         if (ParseNode* name = pn->pn_left) {
    3806           0 :             if (!checkSideEffects(name, answer))
    3807             :                 return false;
    3808           0 :             if (*answer)
    3809             :                 return true;
    3810             :         }
    3811           0 :         return checkSideEffects(pn->pn_right, answer);
    3812             : 
    3813             :       case ParseNodeKind::Switch:
    3814           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3815           0 :         if (!checkSideEffects(pn->pn_left, answer))
    3816             :             return false;
    3817           0 :         return *answer || checkSideEffects(pn->pn_right, answer);
    3818             : 
    3819             :       case ParseNodeKind::Label:
    3820           0 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3821           0 :         return checkSideEffects(pn->expr(), answer);
    3822             : 
    3823             :       case ParseNodeKind::LexicalScope:
    3824           0 :         MOZ_ASSERT(pn->isArity(PN_SCOPE));
    3825           0 :         return checkSideEffects(pn->scopeBody(), answer);
    3826             : 
    3827             :       // We could methodically check every interpolated expression, but it's
    3828             :       // probably not worth the trouble.  Treat template strings as effect-free
    3829             :       // only if they don't contain any substitutions.
    3830             :       case ParseNodeKind::TemplateStringList:
    3831           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3832           0 :         MOZ_ASSERT(pn->pn_count > 0);
    3833           0 :         MOZ_ASSERT((pn->pn_count % 2) == 1,
    3834             :                    "template strings must alternate template and substitution "
    3835             :                    "parts");
    3836           0 :         *answer = pn->pn_count > 1;
    3837           0 :         return true;
    3838             : 
    3839             :       // This should be unreachable but is left as-is for now.
    3840             :       case ParseNodeKind::ParamsBody:
    3841           0 :         *answer = true;
    3842           0 :         return true;
    3843             : 
    3844             :       case ParseNodeKind::ForIn:           // by ParseNodeKind::For
    3845             :       case ParseNodeKind::ForOf:           // by ParseNodeKind::For
    3846             :       case ParseNodeKind::ForHead:         // by ParseNodeKind::For
    3847             :       case ParseNodeKind::ClassMethod:     // by ParseNodeKind::Class
    3848             :       case ParseNodeKind::ClassNames:      // by ParseNodeKind::Class
    3849             :       case ParseNodeKind::ClassMethodList: // by ParseNodeKind::Class
    3850             :       case ParseNodeKind::ImportSpecList: // by ParseNodeKind::Import
    3851             :       case ParseNodeKind::ImportSpec:      // by ParseNodeKind::Import
    3852             :       case ParseNodeKind::ExportBatchSpec:// by ParseNodeKind::Export
    3853             :       case ParseNodeKind::ExportSpecList: // by ParseNodeKind::Export
    3854             :       case ParseNodeKind::ExportSpec:      // by ParseNodeKind::Export
    3855             :       case ParseNodeKind::CallSiteObj:      // by ParseNodeKind::TaggedTemplate
    3856             :       case ParseNodeKind::PosHolder:        // by ParseNodeKind::NewTarget
    3857             :       case ParseNodeKind::SuperBase:        // by ParseNodeKind::Elem and others
    3858           0 :         MOZ_CRASH("handled by parent nodes");
    3859             : 
    3860             :       case ParseNodeKind::Limit: // invalid sentinel value
    3861           0 :         MOZ_CRASH("invalid node kind");
    3862             :     }
    3863             : 
    3864           0 :     MOZ_CRASH("invalid, unenumerated ParseNodeKind value encountered in "
    3865             :               "BytecodeEmitter::checkSideEffects");
    3866             : }
    3867             : 
    3868             : bool
    3869           0 : BytecodeEmitter::isInLoop()
    3870             : {
    3871           0 :     return findInnermostNestableControl<LoopControl>();
    3872             : }
    3873             : 
    3874             : bool
    3875           0 : BytecodeEmitter::checkSingletonContext()
    3876             : {
    3877       43298 :     if (!script->treatAsRunOnce() || sc->isFunctionBox() || isInLoop())
    3878             :         return false;
    3879         842 :     hasSingletons = true;
    3880           0 :     return true;
    3881             : }
    3882             : 
    3883             : bool
    3884           0 : BytecodeEmitter::checkRunOnceContext()
    3885             : {
    3886           0 :     return checkSingletonContext() || (!isInLoop() && isRunOnceLambda());
    3887             : }
    3888             : 
    3889             : bool
    3890           0 : BytecodeEmitter::needsImplicitThis()
    3891             : {
    3892             :     // Short-circuit if there is an enclosing 'with' scope.
    3893           0 :     if (sc->inWith())
    3894             :         return true;
    3895             : 
    3896             :     // Otherwise see if the current point is under a 'with'.
    3897           0 :     for (EmitterScope* es = innermostEmitterScope(); es; es = es->enclosingInFrame()) {
    3898         913 :         if (es->scope(this)->kind() == ScopeKind::With)
    3899             :             return true;
    3900             :     }
    3901             : 
    3902             :     return false;
    3903             : }
    3904             : 
    3905             : void
    3906           0 : BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext* cx)
    3907             : {
    3908             :     // Note: when parsing off thread the resulting scripts need to be handed to
    3909             :     // the debugger after rejoining to the main thread.
    3910       13449 :     if (cx->helperThread())
    3911             :         return;
    3912             : 
    3913             :     // Lazy scripts are never top level (despite always being invoked with a
    3914             :     // nullptr parent), and so the hook should never be fired.
    3915           0 :     if (emitterMode != LazyFunction && !parent)
    3916        2432 :         Debugger::onNewScript(cx, script);
    3917             : }
    3918             : 
    3919             : void
    3920           0 : BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
    3921             : {
    3922           0 :     MOZ_ASSERT_IF(!pn, this->scriptStartOffsetSet);
    3923           0 :     uint32_t offset = pn ? pn->pn_pos.begin : this->scriptStartOffset;
    3924             : 
    3925             :     va_list args;
    3926           0 :     va_start(args, errorNumber);
    3927             : 
    3928           0 :     parser->errorReporter().errorAtVA(offset, errorNumber, &args);
    3929             : 
    3930           0 :     va_end(args);
    3931           0 : }
    3932             : 
    3933             : bool
    3934           0 : BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
    3935             : {
    3936           0 :     MOZ_ASSERT_IF(!pn, this->scriptStartOffsetSet);
    3937           1 :     uint32_t offset = pn ? pn->pn_pos.begin : this->scriptStartOffset;
    3938             : 
    3939             :     va_list args;
    3940           1 :     va_start(args, errorNumber);
    3941             : 
    3942           2 :     bool result = parser->errorReporter().reportExtraWarningErrorNumberVA(nullptr, offset, errorNumber, &args);
    3943             : 
    3944           1 :     va_end(args);
    3945           1 :     return result;
    3946             : }
    3947             : 
    3948             : bool
    3949        4739 : BytecodeEmitter::emitNewInit(JSProtoKey key)
    3950             : {
    3951        4739 :     const size_t len = 1 + UINT32_INDEX_LEN;
    3952             :     ptrdiff_t offset;
    3953           0 :     if (!emitCheck(len, &offset))
    3954             :         return false;
    3955             : 
    3956        4739 :     jsbytecode* code = this->code(offset);
    3957        4739 :     code[0] = JSOP_NEWINIT;
    3958           0 :     code[1] = jsbytecode(key);
    3959        4739 :     code[2] = 0;
    3960        4739 :     code[3] = 0;
    3961        4739 :     code[4] = 0;
    3962        4739 :     checkTypeSet(JSOP_NEWINIT);
    3963           0 :     updateDepth(offset);
    3964        4739 :     return true;
    3965             : }
    3966             : 
    3967             : bool
    3968           0 : BytecodeEmitter::iteratorResultShape(unsigned* shape)
    3969             : {
    3970             :     // No need to do any guessing for the object kind, since we know exactly how
    3971             :     // many properties we plan to have.
    3972           0 :     gc::AllocKind kind = gc::GetGCObjectKind(2);
    3973         204 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
    3974         102 :     if (!obj)
    3975             :         return false;
    3976             : 
    3977           0 :     Rooted<jsid> value_id(cx, NameToId(cx->names().value));
    3978           0 :     Rooted<jsid> done_id(cx, NameToId(cx->names().done));
    3979         204 :     if (!NativeDefineDataProperty(cx, obj, value_id, UndefinedHandleValue, JSPROP_ENUMERATE))
    3980             :         return false;
    3981           0 :     if (!NativeDefineDataProperty(cx, obj, done_id, UndefinedHandleValue, JSPROP_ENUMERATE))
    3982             :         return false;
    3983             : 
    3984         204 :     ObjectBox* objbox = parser->newObjectBox(obj);
    3985         102 :     if (!objbox)
    3986             :         return false;
    3987             : 
    3988         102 :     *shape = objectList.add(objbox);
    3989             : 
    3990           0 :     return true;
    3991             : }
    3992             : 
    3993             : bool
    3994           0 : BytecodeEmitter::emitPrepareIteratorResult()
    3995             : {
    3996             :     unsigned shape;
    3997         102 :     if (!iteratorResultShape(&shape))
    3998             :         return false;
    3999         102 :     return emitIndex32(JSOP_NEWOBJECT, shape);
    4000             : }
    4001             : 
    4002             : bool
    4003         102 : BytecodeEmitter::emitFinishIteratorResult(bool done)
    4004             : {
    4005             :     uint32_t value_id;
    4006         306 :     if (!makeAtomIndex(cx->names().value, &value_id))
    4007             :         return false;
    4008             :     uint32_t done_id;
    4009         306 :     if (!makeAtomIndex(cx->names().done, &done_id))
    4010             :         return false;
    4011             : 
    4012         102 :     if (!emitIndex32(JSOP_INITPROP, value_id))
    4013             :         return false;
    4014         102 :     if (!emit1(done ? JSOP_TRUE : JSOP_FALSE))
    4015             :         return false;
    4016         102 :     if (!emitIndex32(JSOP_INITPROP, done_id))
    4017             :         return false;
    4018         102 :     return true;
    4019             : }
    4020             : 
    4021             : bool
    4022      132137 : BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bool callContext)
    4023             : {
    4024      132137 :     switch (loc.kind()) {
    4025             :       case NameLocation::Kind::Dynamic:
    4026       14738 :         if (!emitAtomOp(name, JSOP_GETNAME))
    4027             :             return false;
    4028             :         break;
    4029             : 
    4030             :       case NameLocation::Kind::Global:
    4031       16368 :         if (!emitAtomOp(name, JSOP_GETGNAME))
    4032             :             return false;
    4033             :         break;
    4034             : 
    4035             :       case NameLocation::Kind::Intrinsic:
    4036        3321 :         if (!emitAtomOp(name, JSOP_GETINTRINSIC))
    4037             :             return false;
    4038             :         break;
    4039             : 
    4040             :       case NameLocation::Kind::NamedLambdaCallee:
    4041           0 :         if (!emit1(JSOP_CALLEE))
    4042             :             return false;
    4043             :         break;
    4044             : 
    4045             :       case NameLocation::Kind::Import:
    4046           0 :         if (!emitAtomOp(name, JSOP_GETIMPORT))
    4047             :             return false;
    4048             :         break;
    4049             : 
    4050             :       case NameLocation::Kind::ArgumentSlot:
    4051       21607 :         if (!emitArgOp(JSOP_GETARG, loc.argumentSlot()))
    4052             :             return false;
    4053             :         break;
    4054             : 
    4055             :       case NameLocation::Kind::FrameSlot:
    4056       50963 :         if (loc.isLexical()) {
    4057           0 :             if (!emitTDZCheckIfNeeded(name, loc))
    4058             :                 return false;
    4059             :         }
    4060       50963 :         if (!emitLocalOp(JSOP_GETLOCAL, loc.frameSlot()))
    4061             :             return false;
    4062             :         break;
    4063             : 
    4064             :       case NameLocation::Kind::EnvironmentCoordinate:
    4065           0 :         if (loc.isLexical()) {
    4066       10573 :             if (!emitTDZCheckIfNeeded(name, loc))
    4067             :                 return false;
    4068             :         }
    4069       25112 :         if (!emitEnvCoordOp(JSOP_GETALIASEDVAR, loc.environmentCoordinate()))
    4070             :             return false;
    4071             :         break;
    4072             : 
    4073             :       case NameLocation::Kind::DynamicAnnexBVar:
    4074           0 :         MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
    4075             :     }
    4076             : 
    4077             :     // Need to provide |this| value for call.
    4078           0 :     if (callContext) {
    4079        6589 :         switch (loc.kind()) {
    4080             :           case NameLocation::Kind::Dynamic: {
    4081         511 :             JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS;
    4082         511 :             if (!emitAtomOp(name, thisOp))
    4083             :                 return false;
    4084             :             break;
    4085             :           }
    4086             : 
    4087             :           case NameLocation::Kind::Global:
    4088        2542 :             if (!emitAtomOp(name, JSOP_GIMPLICITTHIS))
    4089             :                 return false;
    4090             :             break;
    4091             : 
    4092             :           case NameLocation::Kind::Intrinsic:
    4093             :           case NameLocation::Kind::NamedLambdaCallee:
    4094             :           case NameLocation::Kind::Import:
    4095             :           case NameLocation::Kind::ArgumentSlot:
    4096             :           case NameLocation::Kind::FrameSlot:
    4097             :           case NameLocation::Kind::EnvironmentCoordinate:
    4098        3536 :             if (!emit1(JSOP_UNDEFINED))
    4099             :                 return false;
    4100             :             break;
    4101             : 
    4102             :           case NameLocation::Kind::DynamicAnnexBVar:
    4103           0 :             MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
    4104             :         }
    4105             :     }
    4106             : 
    4107             :     return true;
    4108             : }
    4109             : 
    4110             : bool
    4111           0 : BytecodeEmitter::emitGetName(ParseNode* pn, bool callContext)
    4112             : {
    4113           0 :     return emitGetName(pn->name(), callContext);
    4114             : }
    4115             : 
    4116             : template <typename RHSEmitter>
    4117             : bool
    4118       32467 : BytecodeEmitter::emitSetOrInitializeNameAtLocation(HandleAtom name, const NameLocation& loc,
    4119             :                                                    RHSEmitter emitRhs, bool initialize)
    4120             : {
    4121       32467 :     bool emittedBindOp = false;
    4122             : 
    4123           0 :     switch (loc.kind()) {
    4124             :       case NameLocation::Kind::Dynamic:
    4125             :       case NameLocation::Kind::Import:
    4126             :       case NameLocation::Kind::DynamicAnnexBVar: {
    4127             :         uint32_t atomIndex;
    4128         159 :         if (!makeAtomIndex(name, &atomIndex))
    4129           0 :             return false;
    4130         159 :         if (loc.kind() == NameLocation::Kind::DynamicAnnexBVar) {
    4131             :             // Annex B vars always go on the nearest variable environment,
    4132             :             // even if lexical environments in between contain same-named
    4133             :             // bindings.
    4134           0 :             if (!emit1(JSOP_BINDVAR))
    4135             :                 return false;
    4136             :         } else {
    4137         159 :             if (!emitIndexOp(JSOP_BINDNAME, atomIndex))
    4138             :                 return false;
    4139             :         }
    4140         159 :         emittedBindOp = true;
    4141         159 :         if (!emitRhs(this, loc, emittedBindOp))
    4142             :             return false;
    4143           0 :         if (!emitIndexOp(strictifySetNameOp(JSOP_SETNAME), atomIndex))
    4144             :             return false;
    4145         159 :         break;
    4146             :       }
    4147             : 
    4148             :       case NameLocation::Kind::Global: {
    4149             :         JSOp op;
    4150             :         uint32_t atomIndex;
    4151           0 :         if (!makeAtomIndex(name, &atomIndex))
    4152           0 :             return false;
    4153           0 :         if (loc.isLexical() && initialize) {
    4154             :             // INITGLEXICAL always gets the global lexical scope. It doesn't
    4155             :             // need a BINDGNAME.
    4156        3450 :             MOZ_ASSERT(innermostScope()->is<GlobalScope>());
    4157             :             op = JSOP_INITGLEXICAL;
    4158             :         } else {
    4159         946 :             if (!emitIndexOp(JSOP_BINDGNAME, atomIndex))
    4160             :                 return false;
    4161           0 :             emittedBindOp = true;
    4162             :             op = strictifySetNameOp(JSOP_SETGNAME);
    4163             :         }
    4164           0 :         if (!emitRhs(this, loc, emittedBindOp))
    4165             :             return false;
    4166        2671 :         if (!emitIndexOp(op, atomIndex))
    4167             :             return false;
    4168           0 :         break;
    4169             :       }
    4170             : 
    4171             :       case NameLocation::Kind::Intrinsic:
    4172          25 :         if (!emitRhs(this, loc, emittedBindOp))
    4173             :             return false;
    4174          25 :         if (!emitAtomOp(name, JSOP_SETINTRINSIC))
    4175             :             return false;
    4176             :         break;
    4177             : 
    4178             :       case NameLocation::Kind::NamedLambdaCallee:
    4179           0 :         if (!emitRhs(this, loc, emittedBindOp))
    4180             :             return false;
    4181             :         // Assigning to the named lambda is a no-op in sloppy mode but
    4182             :         // throws in strict mode.
    4183           0 :         if (sc->strict() && !emit1(JSOP_THROWSETCALLEE))
    4184             :             return false;
    4185             :         break;
    4186             : 
    4187             :       case NameLocation::Kind::ArgumentSlot: {
    4188             :         // If we assign to a positional formal parameter and the arguments
    4189             :         // object is unmapped (strict mode or function with
    4190             :         // default/rest/destructing args), parameters do not alias
    4191             :         // arguments[i], and to make the arguments object reflect initial
    4192             :         // parameter values prior to any mutation we create it eagerly
    4193             :         // whenever parameters are (or might, in the case of calls to eval)
    4194             :         // assigned.
    4195           0 :         FunctionBox* funbox = sc->asFunctionBox();
    4196         471 :         if (funbox->argumentsHasLocalBinding() && !funbox->hasMappedArgsObj())
    4197          11 :             funbox->setDefinitelyNeedsArgsObj();
    4198             : 
    4199         453 :         if (!emitRhs(this, loc, emittedBindOp))
    4200             :             return false;
    4201         453 :         if (!emitArgOp(JSOP_SETARG, loc.argumentSlot()))
    4202             :             return false;
    4203             :         break;
    4204             :       }
    4205             : 
    4206             :       case NameLocation::Kind::FrameSlot: {
    4207       23049 :         JSOp op = JSOP_SETLOCAL;
    4208           0 :         if (!emitRhs(this, loc, emittedBindOp))
    4209             :             return false;
    4210       23049 :         if (loc.isLexical()) {
    4211           0 :             if (initialize) {
    4212             :                 op = JSOP_INITLEXICAL;
    4213             :             } else {
    4214        2144 :                 if (loc.isConst())
    4215           0 :                     op = JSOP_THROWSETCONST;
    4216             : 
    4217        2144 :                 if (!emitTDZCheckIfNeeded(name, loc))
    4218             :                     return false;
    4219             :             }
    4220             :         }
    4221       23049 :         if (!emitLocalOp(op, loc.frameSlot()))
    4222             :             return false;
    4223       23049 :         if (op == JSOP_INITLEXICAL) {
    4224           0 :             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
    4225             :                 return false;
    4226             :         }
    4227             :         break;
    4228             :       }
    4229             : 
    4230             :       case NameLocation::Kind::EnvironmentCoordinate: {
    4231        6110 :         JSOp op = JSOP_SETALIASEDVAR;
    4232        7207 :         if (!emitRhs(this, loc, emittedBindOp))
    4233             :             return false;
    4234        6110 :         if (loc.isLexical()) {
    4235        4002 :             if (initialize) {
    4236             :                 op = JSOP_INITALIASEDLEXICAL;
    4237             :             } else {
    4238           0 :                 if (loc.isConst())
    4239           0 :                     op = JSOP_THROWSETALIASEDCONST;
    4240             : 
    4241         609 :                 if (!emitTDZCheckIfNeeded(name, loc))
    4242             :                     return false;
    4243             :             }
    4244             :         }
    4245           0 :         if (loc.bindingKind() == BindingKind::NamedLambdaCallee) {
    4246             :             // Assigning to the named lambda is a no-op in sloppy mode and throws
    4247             :             // in strict mode.
    4248           0 :             op = JSOP_THROWSETALIASEDCONST;
    4249           0 :             if (sc->strict() && !emitEnvCoordOp(op, loc.environmentCoordinate()))
    4250             :                 return false;
    4251             :         } else {
    4252        6110 :             if (!emitEnvCoordOp(op, loc.environmentCoordinate()))
    4253             :                 return false;
    4254             :         }
    4255        6110 :         if (op == JSOP_INITALIASEDLEXICAL) {
    4256           0 :             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
    4257             :                 return false;
    4258             :         }
    4259             :         break;
    4260             :       }
    4261             :     }
    4262             : 
    4263             :     return true;
    4264             : }
    4265             : 
    4266             : bool
    4267       38912 : BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc)
    4268             : {
    4269             :     // Dynamic accesses have TDZ checks built into their VM code and should
    4270             :     // never emit explicit TDZ checks.
    4271       77824 :     MOZ_ASSERT(loc.hasKnownSlot());
    4272       38912 :     MOZ_ASSERT(loc.isLexical());
    4273             : 
    4274       77824 :     Maybe<MaybeCheckTDZ> check = innermostTDZCheckCache->needsTDZCheck(this, name);
    4275       38912 :     if (!check)
    4276             :         return false;
    4277             : 
    4278             :     // We've already emitted a check in this basic block.
    4279           0 :     if (*check == DontCheckTDZ)
    4280             :         return true;
    4281             : 
    4282           0 :     if (loc.kind() == NameLocation::Kind::FrameSlot) {
    4283           4 :         if (!emitLocalOp(JSOP_CHECKLEXICAL, loc.frameSlot()))
    4284             :             return false;
    4285             :     } else {
    4286           0 :         if (!emitEnvCoordOp(JSOP_CHECKALIASEDLEXICAL, loc.environmentCoordinate()))
    4287             :             return false;
    4288             :     }
    4289             : 
    4290        2126 :     return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
    4291             : }
    4292             : 
    4293             : bool
    4294       62769 : BytecodeEmitter::emitPropLHS(ParseNode* pn)
    4295             : {
    4296       62769 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
    4297      125538 :     MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
    4298             : 
    4299       62769 :     ParseNode* pn2 = pn->pn_expr;
    4300             : 
    4301             :     /*
    4302             :      * If the object operand is also a dotted property reference, reverse the
    4303             :      * list linked via pn_expr temporarily so we can iterate over it from the
    4304             :      * bottom up (reversing again as we go), to avoid excessive recursion.
    4305             :      */
    4306       75765 :     if (pn2->isKind(ParseNodeKind::Dot) && !pn2->as<PropertyAccess>().isSuper()) {
    4307             :         ParseNode* pndot = pn2;
    4308             :         ParseNode* pnup = nullptr;
    4309             :         ParseNode* pndown;
    4310             :         for (;;) {
    4311             :             /* Reverse pndot->pn_expr to point up, not down. */
    4312           0 :             pndown = pndot->pn_expr;
    4313       13951 :             pndot->pn_expr = pnup;
    4314           0 :             if (!pndown->isKind(ParseNodeKind::Dot) || pndown->as<PropertyAccess>().isSuper())
    4315             :                 break;
    4316             :             pnup = pndot;
    4317             :             pndot = pndown;
    4318             :         }
    4319             : 
    4320             :         /* pndown is a primary expression, not a dotted property reference. */
    4321       12993 :         if (!emitTree(pndown))
    4322             :             return false;
    4323             : 
    4324           0 :         do {
    4325             :             /* Walk back up the list, emitting annotated name ops. */
    4326           0 :             if (!emitAtomOp(pndot, JSOP_GETPROP))
    4327             :                 return false;
    4328             : 
    4329             :             /* Reverse the pn_expr link again. */
    4330           0 :             pnup = pndot->pn_expr;
    4331       13951 :             pndot->pn_expr = pndown;
    4332       13951 :             pndown = pndot;
    4333           0 :         } while ((pndot = pnup) != nullptr);
    4334             :         return true;
    4335             :     }
    4336             : 
    4337             :     // The non-optimized case.
    4338           0 :     return emitTree(pn2);
    4339             : }
    4340             : 
    4341             : bool
    4342          60 : BytecodeEmitter::emitSuperPropLHS(ParseNode* superBase, bool isCall)
    4343             : {
    4344          60 :     if (!emitGetThisForSuperBase(superBase))
    4345             :         return false;
    4346           0 :     if (isCall && !emit1(JSOP_DUP))
    4347             :         return false;
    4348           0 :     if (!emit1(JSOP_SUPERBASE))
    4349             :         return false;
    4350           0 :     return true;
    4351             : }
    4352             : 
    4353             : bool
    4354       62653 : BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
    4355             : {
    4356       62653 :     MOZ_ASSERT(pn->isArity(PN_NAME));
    4357             : 
    4358       62653 :     if (!emitPropLHS(pn))
    4359             :         return false;
    4360             : 
    4361       62655 :     if (op == JSOP_CALLPROP && !emit1(JSOP_DUP))
    4362             :         return false;
    4363             : 
    4364       62655 :     if (!emitAtomOp(pn, op))
    4365             :         return false;
    4366             : 
    4367           0 :     if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP))
    4368             :         return false;
    4369             : 
    4370       62653 :     return true;
    4371             : }
    4372             : 
    4373             : bool
    4374          60 : BytecodeEmitter::emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall)
    4375             : {
    4376          60 :     ParseNode* base = &pn->as<PropertyAccess>().expression();
    4377          60 :     if (!emitSuperPropLHS(base, isCall))
    4378             :         return false;
    4379             : 
    4380           0 :     if (!emitAtomOp(pn, op))
    4381             :         return false;
    4382             : 
    4383          60 :     if (isCall && !emit1(JSOP_SWAP))
    4384             :         return false;
    4385             : 
    4386          60 :     return true;
    4387             : }
    4388             : 
    4389             : bool
    4390           0 : BytecodeEmitter::emitPropIncDec(ParseNode* pn)
    4391             : {
    4392         232 :     MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::Dot));
    4393             : 
    4394             :     bool post;
    4395           0 :     bool isSuper = pn->pn_kid->as<PropertyAccess>().isSuper();
    4396         116 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4397             : 
    4398         116 :     if (isSuper) {
    4399           0 :         ParseNode* base = &pn->pn_kid->as<PropertyAccess>().expression();
    4400           0 :         if (!emitSuperPropLHS(base))                // THIS OBJ
    4401             :             return false;
    4402           0 :         if (!emit1(JSOP_DUP2))                      // THIS OBJ THIS OBJ
    4403             :             return false;
    4404             :     } else {
    4405           0 :         if (!emitPropLHS(pn->pn_kid))               // OBJ
    4406             :             return false;
    4407         116 :         if (!emit1(JSOP_DUP))                       // OBJ OBJ
    4408             :             return false;
    4409             :     }
    4410           0 :     if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
    4411             :         return false;
    4412           0 :     if (!emit1(JSOP_POS))                           // OBJ N
    4413             :         return false;
    4414         116 :     if (post && !emit1(JSOP_DUP))                   // OBJ N? N
    4415             :         return false;
    4416         116 :     if (!emit1(JSOP_ONE))                           // OBJ N? N 1
    4417             :         return false;
    4418           0 :     if (!emit1(binop))                              // OBJ N? N+1
    4419             :         return false;
    4420             : 
    4421         116 :     if (post) {
    4422           0 :         if (!emit2(JSOP_PICK, 2 + isSuper))        // N? N+1 OBJ
    4423             :             return false;
    4424           0 :         if (!emit1(JSOP_SWAP))                     // N? OBJ N+1
    4425             :             return false;
    4426           0 :         if (isSuper) {
    4427           0 :             if (!emit2(JSOP_PICK, 3))              // N THIS N+1 OBJ
    4428             :                 return false;
    4429           0 :             if (!emit1(JSOP_SWAP))                 // N THIS OBJ N+1
    4430             :                 return false;
    4431             :         }
    4432             :     }
    4433             : 
    4434         116 :     JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
    4435         232 :                          : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
    4436         116 :     if (!emitAtomOp(pn->pn_kid, setOp))             // N? N+1
    4437             :         return false;
    4438         116 :     if (post && !emit1(JSOP_POP))                   // RESULT
    4439             :         return false;
    4440             : 
    4441           1 :     return true;
    4442             : }
    4443             : 
    4444             : bool
    4445         911 : BytecodeEmitter::emitGetNameAtLocationForCompoundAssignment(JSAtom* name, const NameLocation& loc)
    4446             : {
    4447         911 :     if (loc.kind() == NameLocation::Kind::Dynamic) {
    4448             :         // For dynamic accesses we need to emit GETBOUNDNAME instead of
    4449             :         // GETNAME for correctness: looking up @@unscopables on the
    4450             :         // environment chain (due to 'with' environments) must only happen
    4451             :         // once.
    4452             :         //
    4453             :         // GETBOUNDNAME uses the environment already pushed on the stack from
    4454             :         // the earlier BINDNAME.
    4455           0 :         if (!emit1(JSOP_DUP))                              // ENV ENV
    4456             :             return false;
    4457           0 :         if (!emitAtomOp(name, JSOP_GETBOUNDNAME))          // ENV V
    4458             :             return false;
    4459             :     } else {
    4460           0 :         if (!emitGetNameAtLocation(name, loc))             // ENV? V
    4461             :             return false;
    4462             :     }
    4463             : 
    4464             :     return true;
    4465             : }
    4466             : 
    4467             : bool
    4468         527 : BytecodeEmitter::emitNameIncDec(ParseNode* pn)
    4469             : {
    4470           0 :     MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::Name));
    4471             : 
    4472             :     bool post;
    4473           0 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4474             : 
    4475             :     auto emitRhs = [pn, post, binop](BytecodeEmitter* bce, const NameLocation& loc,
    4476         527 :                                      bool emittedBindOp)
    4477        2108 :     {
    4478           0 :         JSAtom* name = pn->pn_kid->name();
    4479         527 :         if (!bce->emitGetNameAtLocationForCompoundAssignment(name, loc)) // ENV? V
    4480             :             return false;
    4481         527 :         if (!bce->emit1(JSOP_POS))                         // ENV? N
    4482             :             return false;
    4483         527 :         if (post && !bce->emit1(JSOP_DUP))                 // ENV? N? N
    4484             :             return false;
    4485           0 :         if (!bce->emit1(JSOP_ONE))                         // ENV? N? N 1
    4486             :             return false;
    4487         527 :         if (!bce->emit1(binop))                            // ENV? N? N+1
    4488             :             return false;
    4489             : 
    4490         527 :         if (post && emittedBindOp) {
    4491           8 :             if (!bce->emit2(JSOP_PICK, 2))                 // N? N+1 ENV?
    4492             :                 return false;
    4493           8 :             if (!bce->emit1(JSOP_SWAP))                    // N? ENV? N+1
    4494             :                 return false;
    4495             :         }
    4496             : 
    4497             :         return true;
    4498         527 :     };
    4499             : 
    4500         527 :     if (!emitSetName(pn->pn_kid, emitRhs))
    4501             :         return false;
    4502             : 
    4503         527 :     if (post && !emit1(JSOP_POP))
    4504             :         return false;
    4505             : 
    4506         527 :     return true;
    4507             : }
    4508             : 
    4509             : bool
    4510           0 : BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
    4511             : {
    4512        3239 :     MOZ_ASSERT(pn->isArity(PN_BINARY));
    4513             : 
    4514           0 :     if (!emitTree(pn->pn_left))
    4515             :         return false;
    4516             : 
    4517           0 :     if (opts == EmitElemOption::IncDec) {
    4518           5 :         if (!emit1(JSOP_CHECKOBJCOERCIBLE))
    4519             :             return false;
    4520           1 :     } else if (opts == EmitElemOption::Call) {
    4521          60 :         if (!emit1(JSOP_DUP))
    4522             :             return false;
    4523             :     }
    4524             : 
    4525        3239 :     if (!emitTree(pn->pn_right))
    4526             :         return false;
    4527             : 
    4528        3239 :     if (opts == EmitElemOption::Set) {
    4529           0 :         if (!emit2(JSOP_PICK, 2))
    4530             :             return false;
    4531        3239 :     } else if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
    4532          17 :         if (!emit1(JSOP_TOID))
    4533             :             return false;
    4534             :     }
    4535             :     return true;
    4536             : }
    4537             : 
    4538             : bool
    4539           0 : BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
    4540             : {
    4541           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Elem) && pn->as<PropertyByValue>().isSuper());
    4542             : 
    4543             :     // The ordering here is somewhat screwy. We need to evaluate the propval
    4544             :     // first, by spec. Do a little dance to not emit more than one JSOP_THIS.
    4545             :     // Since JSOP_THIS might throw in derived class constructors, we cannot
    4546             :     // just push it earlier as the receiver. We have to swap it down instead.
    4547             : 
    4548           0 :     if (!emitTree(pn->pn_right))
    4549             :         return false;
    4550             : 
    4551             :     // We need to convert the key to an object id first, so that we do not do
    4552             :     // it inside both the GETELEM and the SETELEM.
    4553           0 :     if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
    4554           0 :         if (!emit1(JSOP_TOID))
    4555             :             return false;
    4556             :     }
    4557             : 
    4558           0 :     if (!emitGetThisForSuperBase(pn->pn_left))
    4559             :         return false;
    4560             : 
    4561           0 :     if (opts == EmitElemOption::Call) {
    4562           0 :         if (!emit1(JSOP_SWAP))
    4563             :             return false;
    4564             : 
    4565             :         // We need another |this| on top, also
    4566           0 :         if (!emitDupAt(1))
    4567             :             return false;
    4568             :     }
    4569             : 
    4570           0 :     if (!emit1(JSOP_SUPERBASE))
    4571             :         return false;
    4572             : 
    4573           0 :     if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 3))
    4574             :         return false;
    4575             : 
    4576           0 :     return true;
    4577             : }
    4578             : 
    4579             : bool
    4580        4400 : BytecodeEmitter::emitElemOpBase(JSOp op)
    4581             : {
    4582           0 :     if (!emit1(op))
    4583             :         return false;
    4584             : 
    4585             :     checkTypeSet(op);
    4586             :     return true;
    4587             : }
    4588             : 
    4589             : bool
    4590        2701 : BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op)
    4591             : {
    4592        2701 :     EmitElemOption opts = EmitElemOption::Get;
    4593           0 :     if (op == JSOP_CALLELEM)
    4594             :         opts = EmitElemOption::Call;
    4595        2641 :     else if (op == JSOP_SETELEM || op == JSOP_STRICTSETELEM)
    4596           0 :         opts = EmitElemOption::Set;
    4597             : 
    4598           0 :     return emitElemOperands(pn, opts) && emitElemOpBase(op);
    4599             : }
    4600             : 
    4601             : bool
    4602           0 : BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
    4603             : {
    4604           0 :     EmitElemOption opts = EmitElemOption::Get;
    4605           0 :     if (isCall)
    4606             :         opts = EmitElemOption::Call;
    4607           0 :     else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
    4608           0 :         opts = EmitElemOption::Set;
    4609             : 
    4610           0 :     if (!emitSuperElemOperands(pn, opts))
    4611             :         return false;
    4612           0 :     if (!emitElemOpBase(op))
    4613             :         return false;
    4614             : 
    4615           0 :     if (isCall && !emit1(JSOP_SWAP))
    4616             :         return false;
    4617             : 
    4618           0 :     return true;
    4619             : }
    4620             : 
    4621             : bool
    4622           5 : BytecodeEmitter::emitElemIncDec(ParseNode* pn)
    4623             : {
    4624          10 :     MOZ_ASSERT(pn->pn_kid->isKind(ParseNodeKind::Elem));
    4625             : 
    4626          10 :     bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
    4627             : 
    4628             :     // We need to convert the key to an object id first, so that we do not do
    4629             :     // it inside both the GETELEM and the SETELEM. This is done by
    4630             :     // emit(Super)ElemOperands.
    4631           5 :     if (isSuper) {
    4632           0 :         if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
    4633             :             return false;
    4634             :     } else {
    4635           0 :         if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec))
    4636             :             return false;
    4637             :     }
    4638             : 
    4639             :     bool post;
    4640           0 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4641             : 
    4642             :     JSOp getOp;
    4643           5 :     if (isSuper) {
    4644             :         // There's no such thing as JSOP_DUP3, so we have to be creative.
    4645             :         // Note that pushing things again is no fewer JSOps.
    4646           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY
    4647             :             return false;
    4648           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS
    4649             :             return false;
    4650           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS OBJ
    4651             :             return false;
    4652             :         getOp = JSOP_GETELEM_SUPER;
    4653             :     } else {
    4654             :                                                         // OBJ KEY
    4655           5 :         if (!emit1(JSOP_DUP2))                          // OBJ KEY OBJ KEY
    4656             :             return false;
    4657             :         getOp = JSOP_GETELEM;
    4658             :     }
    4659           5 :     if (!emitElemOpBase(getOp))                         // OBJ KEY V
    4660             :         return false;
    4661           0 :     if (!emit1(JSOP_POS))                               // OBJ KEY N
    4662             :         return false;
    4663           5 :     if (post && !emit1(JSOP_DUP))                       // OBJ KEY N? N
    4664             :         return false;
    4665           5 :     if (!emit1(JSOP_ONE))                               // OBJ KEY N? N 1
    4666             :         return false;
    4667           5 :     if (!emit1(binop))                                  // OBJ KEY N? N+1
    4668             :         return false;
    4669             : 
    4670           0 :     if (post) {
    4671           5 :         if (isSuper) {
    4672             :             // We have one more value to rotate around, because of |this|
    4673             :             // on the stack
    4674           0 :             if (!emit2(JSOP_PICK, 4))
    4675             :                 return false;
    4676             :         }
    4677           0 :         if (!emit2(JSOP_PICK, 3 + isSuper))             // KEY N N+1 OBJ
    4678             :             return false;
    4679           5 :         if (!emit2(JSOP_PICK, 3 + isSuper))             // N N+1 OBJ KEY
    4680             :             return false;
    4681           5 :         if (!emit2(JSOP_PICK, 2 + isSuper))             // N OBJ KEY N+1
    4682             :             return false;
    4683             :     }
    4684             : 
    4685           0 :     JSOp setOp = isSuper ? (sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER)
    4686           0 :                          : (sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM);
    4687           0 :     if (!emitElemOpBase(setOp))                         // N? N+1
    4688             :         return false;
    4689           5 :     if (post && !emit1(JSOP_POP))                       // RESULT
    4690             :         return false;
    4691             : 
    4692           5 :     return true;
    4693             : }
    4694             : 
    4695             : bool
    4696           0 : BytecodeEmitter::emitCallIncDec(ParseNode* incDec)
    4697             : {
    4698           0 :     MOZ_ASSERT(incDec->isKind(ParseNodeKind::PreIncrement) ||
    4699             :                incDec->isKind(ParseNodeKind::PostIncrement) ||
    4700             :                incDec->isKind(ParseNodeKind::PreDecrement) ||
    4701             :                incDec->isKind(ParseNodeKind::PostDecrement));
    4702             : 
    4703           0 :     MOZ_ASSERT(incDec->pn_kid->isKind(ParseNodeKind::Call));
    4704             : 
    4705           0 :     ParseNode* call = incDec->pn_kid;
    4706           0 :     if (!emitTree(call))                                // CALLRESULT
    4707             :         return false;
    4708           0 :     if (!emit1(JSOP_POS))                               // N
    4709             :         return false;
    4710             : 
    4711             :     // The increment/decrement has no side effects, so proceed to throw for
    4712             :     // invalid assignment target.
    4713           0 :     return emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS);
    4714             : }
    4715             : 
    4716             : bool
    4717           1 : BytecodeEmitter::emitNumberOp(double dval)
    4718             : {
    4719             :     int32_t ival;
    4720        7951 :     if (NumberIsInt32(dval, &ival)) {
    4721        7872 :         if (ival == 0)
    4722           0 :             return emit1(JSOP_ZERO);
    4723           0 :         if (ival == 1)
    4724        1445 :             return emit1(JSOP_ONE);
    4725           0 :         if ((int)(int8_t)ival == ival)
    4726           0 :             return emit2(JSOP_INT8, uint8_t(int8_t(ival)));
    4727             : 
    4728           0 :         uint32_t u = uint32_t(ival);
    4729         534 :         if (u < JS_BIT(16)) {
    4730         438 :             if (!emitUint16Operand(JSOP_UINT16, u))
    4731             :                 return false;
    4732          96 :         } else if (u < JS_BIT(24)) {
    4733             :             ptrdiff_t off;
    4734           0 :             if (!emitN(JSOP_UINT24, 3, &off))
    4735           0 :                 return false;
    4736           0 :             SET_UINT24(code(off), u);
    4737             :         } else {
    4738             :             ptrdiff_t off;
    4739           0 :             if (!emitN(JSOP_INT32, 4, &off))
    4740           0 :                 return false;
    4741           0 :             SET_INT32(code(off), ival);
    4742             :         }
    4743             :         return true;
    4744             :     }
    4745             : 
    4746           0 :     if (!constList.append(DoubleValue(dval)))
    4747             :         return false;
    4748             : 
    4749           0 :     return emitIndex32(JSOP_DOUBLE, constList.length() - 1);
    4750             : }
    4751             : 
    4752             : /*
    4753             :  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
    4754             :  * LLVM is deciding to inline this function which uses a lot of stack space
    4755             :  * into emitTree which is recursive and uses relatively little stack space.
    4756             :  */
    4757             : MOZ_NEVER_INLINE bool
    4758         397 : BytecodeEmitter::emitSwitch(ParseNode* pn)
    4759             : {
    4760         397 :     ParseNode* cases = pn->pn_right;
    4761         397 :     MOZ_ASSERT(cases->isKind(ParseNodeKind::LexicalScope) ||
    4762             :                cases->isKind(ParseNodeKind::StatementList));
    4763             : 
    4764             :     // Emit code for the discriminant.
    4765         397 :     if (!emitTree(pn->pn_left))
    4766             :         return false;
    4767             : 
    4768             :     // Enter the scope before pushing the switch BreakableControl since all
    4769             :     // breaks are under this scope.
    4770           0 :     Maybe<TDZCheckCache> tdzCache;
    4771           0 :     Maybe<EmitterScope> emitterScope;
    4772         397 :     if (cases->isKind(ParseNodeKind::LexicalScope)) {
    4773         397 :         if (!cases->isEmptyScope()) {
    4774          49 :             tdzCache.emplace(this);
    4775          49 :             emitterScope.emplace(this);
    4776           0 :             if (!emitterScope->enterLexical(this, ScopeKind::Lexical, cases->scopeBindings()))
    4777             :                 return false;
    4778             :         }
    4779             : 
    4780             :         // Advance |cases| to refer to the switch case list.
    4781           0 :         cases = cases->scopeBody();
    4782             : 
    4783             :         // A switch statement may contain hoisted functions inside its
    4784             :         // cases. The PNX_FUNCDEFS flag is propagated from the STATEMENTLIST
    4785             :         // bodies of the cases to the case list.
    4786           0 :         if (cases->pn_xflags & PNX_FUNCDEFS) {
    4787           0 :             MOZ_ASSERT(emitterScope);
    4788           0 :             for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
    4789           0 :                 if (caseNode->pn_right->pn_xflags & PNX_FUNCDEFS) {
    4790           0 :                     if (!emitHoistedFunctionsInList(caseNode->pn_right))
    4791             :                         return false;
    4792             :                 }
    4793             :             }
    4794             :         }
    4795             :     }
    4796             : 
    4797             :     // After entering the scope, push the switch control.
    4798           0 :     BreakableControl controlInfo(this, StatementKind::Switch);
    4799             : 
    4800         397 :     ptrdiff_t top = offset();
    4801             : 
    4802             :     // Switch bytecodes run from here till end of final case.
    4803         397 :     uint32_t caseCount = cases->pn_count;
    4804         397 :     if (caseCount > JS_BIT(16)) {
    4805           0 :         reportError(pn, JSMSG_TOO_MANY_CASES);
    4806           0 :         return false;
    4807             :     }
    4808             : 
    4809             :     // Try for most optimal, fall back if not dense ints.
    4810         397 :     JSOp switchOp = JSOP_TABLESWITCH;
    4811         397 :     uint32_t tableLength = 0;
    4812             :     int32_t low, high;
    4813         397 :     bool hasDefault = false;
    4814         397 :     CaseClause* firstCase = cases->pn_head ? &cases->pn_head->as<CaseClause>() : nullptr;
    4815           0 :     if (caseCount == 0 ||
    4816           0 :         (caseCount == 1 && (hasDefault = firstCase->isDefault())))
    4817             :     {
    4818             :         low = 0;
    4819             :         high = -1;
    4820             :     } else {
    4821           0 :         Vector<size_t, 128, SystemAllocPolicy> intmap;
    4822           0 :         int32_t intmapBitLength = 0;
    4823             : 
    4824         397 :         low  = JSVAL_INT_MAX;
    4825           0 :         high = JSVAL_INT_MIN;
    4826             : 
    4827           0 :         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4828           0 :             if (caseNode->isDefault()) {
    4829         129 :                 hasDefault = true;
    4830           0 :                 caseCount--;  // one of the "cases" was the default
    4831           0 :                 continue;
    4832             :             }
    4833             : 
    4834        1706 :             if (switchOp == JSOP_CONDSWITCH)
    4835             :                 continue;
    4836             : 
    4837         584 :             MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4838             : 
    4839           0 :             ParseNode* caseValue = caseNode->caseExpression();
    4840             : 
    4841         584 :             if (caseValue->getKind() != ParseNodeKind::Number) {
    4842             :                 switchOp = JSOP_CONDSWITCH;
    4843             :                 continue;
    4844             :             }
    4845             : 
    4846             :             int32_t i;
    4847           0 :             if (!NumberEqualsInt32(caseValue->pn_dval, &i)) {
    4848             :                 switchOp = JSOP_CONDSWITCH;
    4849             :                 continue;
    4850             :             }
    4851             : 
    4852         226 :             if (unsigned(i + int(JS_BIT(15))) >= unsigned(JS_BIT(16))) {
    4853             :                 switchOp = JSOP_CONDSWITCH;
    4854             :                 continue;
    4855             :             }
    4856           0 :             if (i < low)
    4857          46 :                 low = i;
    4858           0 :             if (i > high)
    4859         189 :                 high = i;
    4860             : 
    4861             :             // Check for duplicates, which require a JSOP_CONDSWITCH.
    4862             :             // We bias i by 65536 if it's negative, and hope that's a rare
    4863             :             // case (because it requires a malloc'd bitmap).
    4864         226 :             if (i < 0)
    4865           0 :                 i += JS_BIT(16);
    4866         226 :             if (i >= intmapBitLength) {
    4867           0 :                 size_t newLength = NumWordsForBitArrayOfLength(i + 1);
    4868           0 :                 if (!intmap.resize(newLength)) {
    4869           0 :                     ReportOutOfMemory(cx);
    4870           0 :                     return false;
    4871             :                 }
    4872          39 :                 intmapBitLength = newLength * BitArrayElementBits;
    4873             :             }
    4874         678 :             if (IsBitArrayElementSet(intmap.begin(), intmap.length(), i)) {
    4875             :                 switchOp = JSOP_CONDSWITCH;
    4876             :                 continue;
    4877             :             }
    4878           0 :             SetBitArrayElement(intmap.begin(), intmap.length(), i);
    4879             :         }
    4880             : 
    4881             :         // Compute table length and select condswitch instead if overlarge or
    4882             :         // more than half-sparse.
    4883         397 :         if (switchOp == JSOP_TABLESWITCH) {
    4884          39 :             tableLength = uint32_t(high - low + 1);
    4885          39 :             if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
    4886           1 :                 switchOp = JSOP_CONDSWITCH;
    4887             :         }
    4888             :     }
    4889             : 
    4890             :     // The note has one or two offsets: first tells total switch code length;
    4891             :     // second (if condswitch) tells offset to first JSOP_CASE.
    4892             :     unsigned noteIndex;
    4893             :     size_t switchSize;
    4894         397 :     if (switchOp == JSOP_CONDSWITCH) {
    4895             :         // 0 bytes of immediate for unoptimized switch.
    4896         359 :         switchSize = 0;
    4897           0 :         if (!newSrcNote3(SRC_CONDSWITCH, 0, 0, &noteIndex))
    4898             :             return false;
    4899             :     } else {
    4900           0 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4901             : 
    4902             :         // 3 offsets (len, low, high) before the table, 1 per entry.
    4903           0 :         switchSize = size_t(JUMP_OFFSET_LEN * (3 + tableLength));
    4904          38 :         if (!newSrcNote2(SRC_TABLESWITCH, 0, &noteIndex))
    4905             :             return false;
    4906             :     }
    4907             : 
    4908             :     // Emit switchOp followed by switchSize bytes of jump or lookup table.
    4909           0 :     MOZ_ASSERT(top == offset());
    4910         397 :     if (!emitN(switchOp, switchSize))
    4911             :         return false;
    4912             : 
    4913           1 :     Vector<CaseClause*, 32, SystemAllocPolicy> table;
    4914             : 
    4915         397 :     JumpList condSwitchDefaultOff;
    4916         397 :     if (switchOp == JSOP_CONDSWITCH) {
    4917             :         unsigned caseNoteIndex;
    4918           0 :         bool beforeCases = true;
    4919           0 :         ptrdiff_t lastCaseOffset = -1;
    4920             : 
    4921             :         // The case conditions need their own TDZ cache since they might not
    4922             :         // all execute.
    4923         718 :         TDZCheckCache tdzCache(this);
    4924             : 
    4925             :         // Emit code for evaluating cases and jumping to case statements.
    4926           0 :         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4927           0 :             ParseNode* caseValue = caseNode->caseExpression();
    4928             : 
    4929             :             // If the expression is a literal, suppress line number emission so
    4930             :             // that debugging works more naturally.
    4931        1594 :             if (caseValue) {
    4932        1483 :                 if (!emitTree(caseValue, ValueUsage::WantValue,
    4933           0 :                               caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE))
    4934             :                 {
    4935           0 :                     return false;
    4936             :                 }
    4937             :             }
    4938             : 
    4939        1594 :             if (!beforeCases) {
    4940             :                 // prevCase is the previous JSOP_CASE's bytecode offset.
    4941           0 :                 if (!setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
    4942             :                     return false;
    4943             :             }
    4944        1594 :             if (!caseValue) {
    4945             :                 // This is the default clause.
    4946         111 :                 continue;
    4947             :             }
    4948             : 
    4949           0 :             if (!newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex))
    4950             :                 return false;
    4951             : 
    4952             :             // The case clauses are produced before any of the case body. The
    4953             :             // JumpList is saved on the parsed tree, then later restored and
    4954             :             // patched when generating the cases body.
    4955        1483 :             JumpList caseJump;
    4956           0 :             if (!emitJump(JSOP_CASE, &caseJump))
    4957             :                 return false;
    4958           0 :             caseNode->setOffset(caseJump.offset);
    4959        1483 :             lastCaseOffset = caseJump.offset;
    4960             : 
    4961           1 :             if (beforeCases) {
    4962             :                 // Switch note's second offset is to first JSOP_CASE.
    4963         359 :                 unsigned noteCount = notes().length();
    4964           0 :                 if (!setSrcNoteOffset(noteIndex, 1, lastCaseOffset - top))
    4965             :                     return false;
    4966           0 :                 unsigned noteCountDelta = notes().length() - noteCount;
    4967         359 :                 if (noteCountDelta != 0)
    4968           0 :                     caseNoteIndex += noteCountDelta;
    4969             :                 beforeCases = false;
    4970             :             }
    4971             :         }
    4972             : 
    4973             :         // If we didn't have an explicit default (which could fall in between
    4974             :         // cases, preventing us from fusing this setSrcNoteOffset with the call
    4975             :         // in the loop above), link the last case to the implicit default for
    4976             :         // the benefit of IonBuilder.
    4977           0 :         if (!hasDefault &&
    4978           0 :             !beforeCases &&
    4979           0 :             !setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
    4980             :         {
    4981             :             return false;
    4982             :         }
    4983             : 
    4984             :         // Emit default even if no explicit default statement.
    4985         359 :         if (!emitJump(JSOP_DEFAULT, &condSwitchDefaultOff))
    4986             :             return false;
    4987             :     } else {
    4988          38 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4989             : 
    4990             :         // skip default offset.
    4991          38 :         jsbytecode* pc = code(top + JUMP_OFFSET_LEN);
    4992             : 
    4993             :         // Fill in switch bounds, which we know fit in 16-bit offsets.
    4994           0 :         SET_JUMP_OFFSET(pc, low);
    4995           0 :         pc += JUMP_OFFSET_LEN;
    4996           0 :         SET_JUMP_OFFSET(pc, high);
    4997          38 :         pc += JUMP_OFFSET_LEN;
    4998             : 
    4999          38 :         if (tableLength != 0) {
    5000          38 :             if (!table.growBy(tableLength)) {
    5001           0 :                 ReportOutOfMemory(cx);
    5002           0 :                 return false;
    5003             :             }
    5004             : 
    5005           0 :             for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    5006         241 :                 if (ParseNode* caseValue = caseNode->caseExpression()) {
    5007         223 :                     MOZ_ASSERT(caseValue->isKind(ParseNodeKind::Number));
    5008             : 
    5009         223 :                     int32_t i = int32_t(caseValue->pn_dval);
    5010         223 :                     MOZ_ASSERT(double(i) == caseValue->pn_dval);
    5011             : 
    5012           0 :                     i -= low;
    5013         223 :                     MOZ_ASSERT(uint32_t(i) < tableLength);
    5014         223 :                     MOZ_ASSERT(!table[i]);
    5015         223 :                     table[i] = caseNode;
    5016             :                 }
    5017             :             }
    5018             :         }
    5019             :     }
    5020             : 
    5021         397 :     JumpTarget defaultOffset{ -1 };
    5022             : 
    5023             :     // Emit code for each case's statements.
    5024           0 :     for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    5025           0 :         if (switchOp == JSOP_CONDSWITCH && !caseNode->isDefault()) {
    5026             :             // The case offset got saved in the caseNode structure after
    5027             :             // emitting the JSOP_CASE jump instruction above.
    5028           0 :             JumpList caseCond;
    5029        1483 :             caseCond.offset = caseNode->offset();
    5030        1483 :             if (!emitJumpTargetAndPatch(caseCond))
    5031           0 :                 return false;
    5032             :         }
    5033             : 
    5034             :         JumpTarget here;
    5035           0 :         if (!emitJumpTarget(&here))
    5036             :             return false;
    5037           0 :         if (caseNode->isDefault())
    5038         129 :             defaultOffset = here;
    5039             : 
    5040             :         // If this is emitted as a TABLESWITCH, we'll need to know this case's
    5041             :         // offset later when emitting the table. Store it in the node's
    5042             :         // pn_offset (giving the field a different meaning vs. how we used it
    5043             :         // on the immediately preceding line of code).
    5044           0 :         caseNode->setOffset(here.offset);
    5045             : 
    5046           1 :         TDZCheckCache tdzCache(this);
    5047             : 
    5048        1835 :         if (!emitTree(caseNode->statementList()))
    5049           0 :             return false;
    5050             :     }
    5051             : 
    5052           0 :     if (!hasDefault) {
    5053             :         // If no default case, offset for default is to end of switch.
    5054           0 :         if (!emitJumpTarget(&defaultOffset))
    5055             :             return false;
    5056             :     }
    5057         397 :     MOZ_ASSERT(defaultOffset.offset != -1);
    5058             : 
    5059             :     // Set the default offset (to end of switch if no default).
    5060             :     jsbytecode* pc;
    5061         397 :     if (switchOp == JSOP_CONDSWITCH) {
    5062         359 :         pc = nullptr;
    5063           0 :         patchJumpsToTarget(condSwitchDefaultOff, defaultOffset);
    5064             :     } else {
    5065          38 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    5066          38 :         pc = code(top);
    5067          76 :         SET_JUMP_OFFSET(pc, defaultOffset.offset - top);
    5068           0 :         pc += JUMP_OFFSET_LEN;
    5069             :     }
    5070             : 
    5071             :     // Set the SRC_SWITCH note's offset operand to tell end of switch.
    5072           0 :     if (!setSrcNoteOffset(noteIndex, 0, lastNonJumpTargetOffset() - top))
    5073             :         return false;
    5074             : 
    5075         397 :     if (switchOp == JSOP_TABLESWITCH) {
    5076             :         // Skip over the already-initialized switch bounds.
    5077          38 :         pc += 2 * JUMP_OFFSET_LEN;
    5078             : 
    5079             :         // Fill in the jump table, if there is one.
    5080         296 :         for (uint32_t i = 0; i < tableLength; i++) {
    5081           0 :             CaseClause* caseNode = table[i];
    5082         258 :             ptrdiff_t off = caseNode ? caseNode->offset() - top : 0;
    5083           0 :             SET_JUMP_OFFSET(pc, off);
    5084         258 :             pc += JUMP_OFFSET_LEN;
    5085             :         }
    5086             :     }
    5087             : 
    5088             :     // Patch breaks before leaving the scope, as all breaks are under the
    5089             :     // lexical scope if it exists.
    5090           0 :     if (!controlInfo.patchBreaks(this))
    5091             :         return false;
    5092             : 
    5093           0 :     if (emitterScope && !emitterScope->leave(this))
    5094             :         return false;
    5095             : 
    5096           0 :     return true;
    5097             : }
    5098             : 
    5099             : bool
    5100           0 : BytecodeEmitter::isRunOnceLambda()
    5101             : {
    5102             :     // The run once lambda flags set by the parser are approximate, and we look
    5103             :     // at properties of the function itself before deciding to emit a function
    5104             :     // as a run once lambda.
    5105             : 
    5106       73095 :     if (!(parent && parent->emittingRunOnceLambda) &&
    5107           0 :         (emitterMode != LazyFunction || !lazyScript->treatAsRunOnce()))
    5108             :     {
    5109             :         return false;
    5110             :     }
    5111             : 
    5112         258 :     FunctionBox* funbox = sc->asFunctionBox();
    5113           0 :     return !funbox->argumentsHasLocalBinding() &&
    5114           0 :            !funbox->isGenerator() &&
    5115           0 :            !funbox->isAsync() &&
    5116           0 :            !funbox->function()->explicitName();
    5117             : }
    5118             : 
    5119             : bool
    5120           0 : BytecodeEmitter::emitYieldOp(JSOp op)
    5121             : {
    5122           0 :     if (op == JSOP_FINALYIELDRVAL)
    5123        1361 :         return emit1(JSOP_FINALYIELDRVAL);
    5124             : 
    5125        2015 :     MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD || op == JSOP_AWAIT);
    5126             : 
    5127             :     ptrdiff_t off;
    5128        2015 :     if (!emitN(op, 3, &off))
    5129             :         return false;
    5130             : 
    5131           0 :     uint32_t yieldAndAwaitIndex = yieldAndAwaitOffsetList.length();
    5132        2015 :     if (yieldAndAwaitIndex >= JS_BIT(24)) {
    5133           0 :         reportError(nullptr, JSMSG_TOO_MANY_YIELDS);
    5134           0 :         return false;
    5135             :     }
    5136             : 
    5137        2015 :     if (op == JSOP_AWAIT)
    5138        1233 :         yieldAndAwaitOffsetList.numAwaits++;
    5139             :     else
    5140           0 :         yieldAndAwaitOffsetList.numYields++;
    5141             : 
    5142           0 :     SET_UINT24(code(off), yieldAndAwaitIndex);
    5143             : 
    5144           1 :     if (!yieldAndAwaitOffsetList.append(offset()))
    5145             :         return false;
    5146             : 
    5147           0 :     return emit1(JSOP_DEBUGAFTERYIELD);
    5148             : }
    5149             : 
    5150             : bool
    5151          79 : BytecodeEmitter::emitSetThis(ParseNode* pn)
    5152             : {
    5153             :     // ParseNodeKind::SetThis is used to update |this| after a super() call
    5154             :     // in a derived class constructor.
    5155             : 
    5156          79 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::SetThis));
    5157           0 :     MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::Name));
    5158             : 
    5159         158 :     RootedAtom name(cx, pn->pn_left->name());
    5160           0 :     auto emitRhs = [&name, pn](BytecodeEmitter* bce, const NameLocation&, bool) {
    5161             :         // Emit the new |this| value.
    5162          79 :         if (!bce->emitTree(pn->pn_right))
    5163             :             return false;
    5164             :         // Get the original |this| and throw if we already initialized
    5165             :         // it. Do *not* use the NameLocation argument, as that's the special
    5166             :         // lexical location below to deal with super() semantics.
    5167          79 :         if (!bce->emitGetName(name))
    5168             :             return false;
    5169           0 :         if (!bce->emit1(JSOP_CHECKTHISREINIT))
    5170             :             return false;
    5171           0 :         if (!bce->emit1(JSOP_POP))
    5172             :             return false;
    5173          79 :         return true;
    5174          79 :     };
    5175             : 
    5176             :     // The 'this' binding is not lexical, but due to super() semantics this
    5177             :     // initialization needs to be treated as a lexical one.
    5178           0 :     NameLocation loc = lookupName(name);
    5179             :     NameLocation lexicalLoc;
    5180           0 :     if (loc.kind() == NameLocation::Kind::FrameSlot) {
    5181          74 :         lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
    5182           5 :     } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
    5183           5 :         EnvironmentCoordinate coord = loc.environmentCoordinate();
    5184           5 :         uint8_t hops = AssertedCast<uint8_t>(coord.hops());
    5185           5 :         lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, coord.slot());
    5186             :     } else {
    5187           0 :         MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic);
    5188           0 :         lexicalLoc = loc;
    5189             :     }
    5190             : 
    5191         158 :     return emitSetOrInitializeNameAtLocation(name, lexicalLoc, emitRhs, true);
    5192             : }
    5193             : 
    5194             : bool
    5195         408 : BytecodeEmitter::emitScript(ParseNode* body)
    5196             : {
    5197         816 :     AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, parser->errorReporter(), body);
    5198             : 
    5199         816 :     setScriptStartOffsetIfUnset(body->pn_pos);
    5200             : 
    5201           0 :     TDZCheckCache tdzCache(this);
    5202           0 :     EmitterScope emitterScope(this);
    5203           0 :     if (sc->isGlobalContext()) {
    5204         390 :         switchToPrologue();
    5205           0 :         if (!emitterScope.enterGlobal(this, sc->asGlobalContext()))
    5206             :             return false;
    5207             :         switchToMain();
    5208          18 :     } else if (sc->isEvalContext()) {
    5209          18 :         switchToPrologue();
    5210          18 :         if (!emitterScope.enterEval(this, sc->asEvalContext()))
    5211             :             return false;
    5212             :         switchToMain();
    5213             :     } else {
    5214           0 :         MOZ_ASSERT(sc->isModuleContext());
    5215           0 :         if (!emitterScope.enterModule(this, sc->asModuleContext()))
    5216             :             return false;
    5217             :     }
    5218             : 
    5219         408 :     setFunctionBodyEndPos(body->pn_pos);
    5220             : 
    5221           0 :     if (sc->isEvalContext() && !sc->strict() &&
    5222         408 :         body->isKind(ParseNodeKind::LexicalScope) && !body->isEmptyScope())
    5223             :     {
    5224             :         // Sloppy eval scripts may need to emit DEFFUNs in the prologue. If there is
    5225             :         // an immediately enclosed lexical scope, we need to enter the lexical
    5226             :         // scope in the prologue for the DEFFUNs to pick up the right
    5227             :         // environment chain.
    5228           0 :         EmitterScope lexicalEmitterScope(this);
    5229             : 
    5230           0 :         switchToPrologue();
    5231           0 :         if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, body->scopeBindings()))
    5232           0 :             return false;
    5233           0 :         switchToMain();
    5234             : 
    5235           0 :         if (!emitLexicalScopeBody(body->scopeBody()))
    5236             :             return false;
    5237             : 
    5238           0 :         if (!lexicalEmitterScope.leave(this))
    5239             :             return false;
    5240             :     } else {
    5241           0 :         if (!emitTree(body))
    5242             :             return false;
    5243             :     }
    5244             : 
    5245           0 :     if (!updateSourceCoordNotes(body->pn_pos.end))
    5246             :         return false;
    5247             : 
    5248         408 :     if (!emit1(JSOP_RETRVAL))
    5249             :         return false;
    5250             : 
    5251         408 :     if (!emitterScope.leave(this))
    5252             :         return false;
    5253             : 
    5254           0 :     if (!JSScript::fullyInitFromEmitter(cx, script, this))
    5255             :         return false;
    5256             : 
    5257         408 :     tellDebuggerAboutCompiledScript(cx);
    5258             : 
    5259         408 :     return true;
    5260             : }
    5261             : 
    5262             : bool
    5263           0 : BytecodeEmitter::emitFunctionScript(ParseNode* body)
    5264             : {
    5265           0 :     FunctionBox* funbox = sc->asFunctionBox();
    5266           0 :     AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, parser->errorReporter(), funbox);
    5267             : 
    5268           0 :     setScriptStartOffsetIfUnset(body->pn_pos);
    5269             : 
    5270             :     // The ordering of these EmitterScopes is important. The named lambda
    5271             :     // scope needs to enclose the function scope needs to enclose the extra
    5272             :     // var scope.
    5273             : 
    5274       26082 :     Maybe<EmitterScope> namedLambdaEmitterScope;
    5275       26082 :     if (funbox->namedLambdaBindings()) {
    5276        1230 :         namedLambdaEmitterScope.emplace(this);
    5277        1230 :         if (!namedLambdaEmitterScope->enterNamedLambda(this, funbox))
    5278             :             return false;
    5279             :     }
    5280             : 
    5281             :     /*
    5282             :      * Emit a prologue for run-once scripts which will deoptimize JIT code
    5283             :      * if the script ends up running multiple times via foo.caller related
    5284             :      * shenanigans.
    5285             :      *
    5286             :      * Also mark the script so that initializers created within it may be
    5287             :      * given more precise types.
    5288             :      */
    5289       13041 :     if (isRunOnceLambda()) {
    5290          84 :         script->setTreatAsRunOnce();
    5291           1 :         MOZ_ASSERT(!script->hasRunOnce());
    5292             : 
    5293          28 :         switchToPrologue();
    5294          28 :         if (!emit1(JSOP_RUNONCE))
    5295             :             return false;
    5296             :         switchToMain();
    5297             :     }
    5298             : 
    5299       13041 :     setFunctionBodyEndPos(body->pn_pos);
    5300           0 :     if (!emitTree(body))
    5301             :         return false;
    5302             : 
    5303       13041 :     if (!updateSourceCoordNotes(body->pn_pos.end))
    5304             :         return false;
    5305             : 
    5306             :     // Always end the script with a JSOP_RETRVAL. Some other parts of the
    5307             :     // codebase depend on this opcode,
    5308             :     // e.g. InterpreterRegs::setToEndOfScript.
    5309       13041 :     if (!emit1(JSOP_RETRVAL))
    5310             :         return false;
    5311             : 
    5312           0 :     if (namedLambdaEmitterScope) {
    5313           0 :         if (!namedLambdaEmitterScope->leave(this))
    5314             :             return false;
    5315           0 :         namedLambdaEmitterScope.reset();
    5316             :     }
    5317             : 
    5318       26082 :     if (!JSScript::fullyInitFromEmitter(cx, script, this))
    5319             :         return false;
    5320             : 
    5321           0 :     tellDebuggerAboutCompiledScript(cx);
    5322             : 
    5323       13041 :     return true;
    5324             : }
    5325             : 
    5326             : bool
    5327        1636 : BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted)
    5328             : {
    5329           0 :     *emitted = 0;
    5330             : 
    5331        1636 :     if (target->isKind(ParseNodeKind::Spread))
    5332           1 :         target = target->pn_kid;
    5333        1635 :     else if (target->isKind(ParseNodeKind::Assign))
    5334           0 :         target = target->pn_left;
    5335             : 
    5336             :     // No need to recur into ParseNodeKind::Array and
    5337             :     // ParseNodeKind::Object subpatterns here, since
    5338             :     // emitSetOrInitializeDestructuring does the recursion when
    5339             :     // setting or initializing value.  Getting reference doesn't recur.
    5340        3301 :     if (target->isKind(ParseNodeKind::Name) ||
    5341        1686 :         target->isKind(ParseNodeKind::Array) ||
    5342          21 :         target->isKind(ParseNodeKind::Object))
    5343             :     {
    5344             :         return true;
    5345             :     }
    5346             : 
    5347             : #ifdef DEBUG
    5348          13 :     int depth = stackDepth;
    5349             : #endif
    5350             : 
    5351          13 :     switch (target->getKind()) {
    5352             :       case ParseNodeKind::Dot: {
    5353           0 :         if (target->as<PropertyAccess>().isSuper()) {
    5354           0 :             if (!emitSuperPropLHS(&target->as<PropertyAccess>().expression()))
    5355             :                 return false;
    5356           0 :             *emitted = 2;
    5357             :         } else {
    5358          13 :             if (!emitTree(target->pn_expr))
    5359             :                 return false;
    5360          13 :             *emitted = 1;
    5361             :         }
    5362             :         break;
    5363             :       }
    5364             : 
    5365             :       case ParseNodeKind::Elem: {
    5366           0 :         if (target->as<PropertyByValue>().isSuper()) {
    5367           0 :             if (!emitSuperElemOperands(target, EmitElemOption::Ref))
    5368             :                 return false;
    5369           0 :             *emitted = 3;
    5370             :         } else {
    5371           0 :             if (!emitElemOperands(target, EmitElemOption::Ref))
    5372             :                 return false;
    5373           0 :             *emitted = 2;
    5374             :         }
    5375             :         break;
    5376             :       }
    5377             : 
    5378             :       case ParseNodeKind::Call:
    5379           0 :         MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
    5380             :                                "rejects function calls as assignment "
    5381             :                                "targets in destructuring assignments");
    5382             :         break;
    5383             : 
    5384             :       default:
    5385           0 :         MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
    5386             :     }
    5387             : 
    5388           0 :     MOZ_ASSERT(stackDepth == depth + int(*emitted));
    5389             : 
    5390             :     return true;
    5391             : }
    5392             : 
    5393             : bool
    5394        1636 : BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav)
    5395             : {
    5396             :     // Now emit the lvalue opcode sequence. If the lvalue is a nested
    5397             :     // destructuring initialiser-form, call ourselves to handle it, then pop
    5398             :     // the matched value. Otherwise emit an lvalue bytecode sequence followed
    5399             :     // by an assignment op.
    5400        1636 :     if (target->isKind(ParseNodeKind::Spread))
    5401           1 :         target = target->pn_kid;
    5402           0 :     else if (target->isKind(ParseNodeKind::Assign))
    5403           0 :         target = target->pn_left;
    5404        3264 :     if (target->isKind(ParseNodeKind::Array) || target->isKind(ParseNodeKind::Object)) {
    5405          16 :         if (!emitDestructuringOps(target, flav))
    5406             :             return false;
    5407             :         // Per its post-condition, emitDestructuringOps has left the
    5408             :         // to-be-destructured value on top of the stack.
    5409          16 :         if (!emit1(JSOP_POP))
    5410             :             return false;
    5411             :     } else {
    5412        1620 :         switch (target->getKind()) {
    5413             :           case ParseNodeKind::Name: {
    5414             :             auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
    5415             :                                           bool emittedBindOp)
    5416             :             {
    5417         242 :                 if (emittedBindOp) {
    5418             :                     // This is like ordinary assignment, but with one
    5419             :                     // difference.
    5420             :                     //
    5421             :                     // In `a = b`, we first determine a binding for `a` (using
    5422             :                     // JSOP_BINDNAME or JSOP_BINDGNAME), then we evaluate `b`,
    5423             :                     // then a JSOP_SETNAME instruction.
    5424             :                     //
    5425             :                     // In `[a] = [b]`, per spec, `b` is evaluated first, then
    5426             :                     // we determine a binding for `a`. Then we need to do
    5427             :                     // assignment-- but the operands are on the stack in the
    5428             :                     // wrong order for JSOP_SETPROP, so we have to add a
    5429             :                     // JSOP_SWAP.
    5430             :                     //
    5431             :                     // In the cases where we are emitting a name op, emit a
    5432             :                     // swap because of this.
    5433          52 :                     return bce->emit1(JSOP_SWAP);
    5434             :                 }
    5435             : 
    5436             :                 // In cases of emitting a frame slot or environment slot,
    5437             :                 // nothing needs be done.
    5438             :                 return true;
    5439             :             };
    5440             : 
    5441           0 :             RootedAtom name(cx, target->name());
    5442        1607 :             switch (flav) {
    5443             :               case DestructuringDeclaration:
    5444        3128 :                 if (!emitInitializeName(name, emitSwapScopeAndRhs))
    5445           0 :                     return false;
    5446             :                 break;
    5447             : 
    5448             :               case DestructuringFormalParameterInVarScope: {
    5449             :                 // If there's an parameter expression var scope, the
    5450             :                 // destructuring declaration needs to initialize the name in
    5451             :                 // the function scope. The innermost scope is the var scope,
    5452             :                 // and its enclosing scope is the function scope.
    5453           0 :                 EmitterScope* funScope = innermostEmitterScope()->enclosingInFrame();
    5454           0 :                 NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope);
    5455           0 :                 if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true))
    5456           0 :                     return false;
    5457           0 :                 break;
    5458             :               }
    5459             : 
    5460             :               case DestructuringAssignment:
    5461          86 :                 if (!emitSetName(name, emitSwapScopeAndRhs))
    5462             :                     return false;
    5463             :                 break;
    5464             :             }
    5465             : 
    5466        1607 :             break;
    5467             :           }
    5468             : 
    5469             :           case ParseNodeKind::Dot: {
    5470             :             // The reference is already pushed by emitDestructuringLHSRef.
    5471             :             JSOp setOp;
    5472          26 :             if (target->as<PropertyAccess>().isSuper())
    5473           0 :                 setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
    5474             :             else
    5475          26 :                 setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
    5476           0 :             if (!emitAtomOp(target, setOp))
    5477             :                 return false;
    5478             :             break;
    5479             :           }
    5480             : 
    5481             :           case ParseNodeKind::Elem: {
    5482             :             // The reference is already pushed by emitDestructuringLHSRef.
    5483           0 :             if (target->as<PropertyByValue>().isSuper()) {
    5484           0 :                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER;
    5485             :                 // emitDestructuringLHSRef already did emitSuperElemOperands
    5486             :                 // part of emitSuperElemOp.  Perform remaining part here.
    5487           0 :                 if (!emitElemOpBase(setOp))
    5488             :                     return false;
    5489             :             } else {
    5490           0 :                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
    5491           0 :                 if (!emitElemOpBase(setOp))
    5492             :                     return false;
    5493             :             }
    5494             :             break;
    5495             :           }
    5496             : 
    5497             :           case ParseNodeKind::Call:
    5498           0 :             MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
    5499             :                                    "rejects function calls as assignment "
    5500             :                                    "targets in destructuring assignments");
    5501             :             break;
    5502             : 
    5503             :           default:
    5504           0 :             MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind");
    5505             :         }
    5506             : 
    5507             :         // Pop the assigned value.
    5508        1620 :         if (!emit1(JSOP_POP))
    5509             :             return false;
    5510             :     }
    5511             : 
    5512             :     return true;
    5513             : }
    5514             : 
    5515             : bool
    5516           0 : BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = IteratorKind::Sync */,
    5517             :                                   bool allowSelfHosted /* = false */)
    5518             : {
    5519        1961 :     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
    5520             :                ".next() iteration is prohibited in self-hosted code because it "
    5521             :                "can run user-modifiable iteration code");
    5522             : 
    5523        1961 :     MOZ_ASSERT(this->stackDepth >= 2);                    // ... NEXT ITER
    5524             : 
    5525        1961 :     if (!emitCall(JSOP_CALL, 0, pn))                      // ... RESULT
    5526             :         return false;
    5527             : 
    5528        1961 :     if (iterKind == IteratorKind::Async) {
    5529           0 :         if (!emitAwaitInInnermostScope())                 // ... RESULT
    5530             :             return false;
    5531             :     }
    5532             : 
    5533        1961 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
    5534             :         return false;
    5535             :     checkTypeSet(JSOP_CALL);
    5536             :     return true;
    5537             : }
    5538             : 
    5539             : bool
    5540        1619 : BytecodeEmitter::emitPushNotUndefinedOrNull()
    5541             : {
    5542        1619 :     MOZ_ASSERT(this->stackDepth > 0);                     // V
    5543             : 
    5544        1619 :     if (!emit1(JSOP_DUP))                                 // V V
    5545             :         return false;
    5546           0 :     if (!emit1(JSOP_UNDEFINED))                           // V V UNDEFINED
    5547             :         return false;
    5548           0 :     if (!emit1(JSOP_STRICTNE))                            // V ?NEQL
    5549             :         return false;
    5550             : 
    5551        1619 :     JumpList undefinedOrNullJump;
    5552           0 :     if (!emitJump(JSOP_AND, &undefinedOrNullJump))        // V ?NEQL
    5553             :         return false;
    5554             : 
    5555        1619 :     if (!emit1(JSOP_POP))                                 // V
    5556             :         return false;
    5557        1619 :     if (!emit1(JSOP_DUP))                                 // V V
    5558             :         return false;
    5559        1619 :     if (!emit1(JSOP_NULL))                                // V V NULL
    5560             :         return false;
    5561        1619 :     if (!emit1(JSOP_STRICTNE))                            // V ?NEQL
    5562             :         return false;
    5563             : 
    5564           0 :     if (!emitJumpTargetAndPatch(undefinedOrNullJump))     // V NOT-UNDEF-OR-NULL
    5565             :         return false;
    5566             : 
    5567           0 :     return true;
    5568             : }
    5569             : 
    5570             : bool
    5571           0 : BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
    5572             :                                           IteratorKind iterKind /* = IteratorKind::Sync */,
    5573             :                                           CompletionKind completionKind /* = CompletionKind::Normal */,
    5574             :                                           bool allowSelfHosted /* = false */)
    5575             : {
    5576        1608 :     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
    5577             :                ".close() on iterators is prohibited in self-hosted code because it "
    5578             :                "can run user-modifiable iteration code");
    5579             : 
    5580             :     // Generate inline logic corresponding to IteratorClose (ES 7.4.6).
    5581             :     //
    5582             :     // Callers need to ensure that the iterator object is at the top of the
    5583             :     // stack.
    5584             : 
    5585        1608 :     if (!emit1(JSOP_DUP))                                 // ... ITER ITER
    5586             :         return false;
    5587             : 
    5588             :     // Step 3.
    5589             :     //
    5590             :     // Get the "return" method.
    5591        4824 :     if (!emitAtomOp(cx->names().return_, JSOP_CALLPROP))  // ... ITER RET
    5592             :         return false;
    5593             : 
    5594             :     // Step 4.
    5595             :     //
    5596             :     // Do nothing if "return" is undefined or null.
    5597           0 :     InternalIfEmitter ifReturnMethodIsDefined(this);
    5598        1608 :     if (!emitPushNotUndefinedOrNull())                    // ... ITER RET NOT-UNDEF-OR-NULL
    5599             :         return false;
    5600             : 
    5601        1608 :     if (!ifReturnMethodIsDefined.emitThenElse())          // ... ITER RET
    5602             :         return false;
    5603             : 
    5604        1608 :     if (completionKind == CompletionKind::Throw) {
    5605             :         // 7.4.6 IteratorClose ( iterator, completion )
    5606             :         //   ...
    5607             :         //   3. Let return be ? GetMethod(iterator, "return").
    5608             :         //   4. If return is undefined, return Completion(completion).
    5609             :         //   5. Let innerResult be Call(return, iterator, « »).
    5610             :         //   6. If completion.[[Type]] is throw, return Completion(completion).
    5611             :         //   7. If innerResult.[[Type]] is throw, return
    5612             :         //      Completion(innerResult).
    5613             :         //
    5614             :         // For CompletionKind::Normal case, JSOP_CALL for step 5 checks if RET
    5615             :         // is callable, and throws if not.  Since step 6 doesn't match and
    5616             :         // error handling in step 3 and step 7 can be merged.
    5617             :         //
    5618             :         // For CompletionKind::Throw case, an error thrown by JSOP_CALL for
    5619             :         // step 5 is ignored by try-catch.  So we should check if RET is
    5620             :         // callable here, outside of try-catch, and the throw immediately if
    5621             :         // not.
    5622           0 :         CheckIsCallableKind kind = CheckIsCallableKind::IteratorReturn;
    5623        1114 :         if (!emitCheckIsCallable(kind))                   // ... ITER RET
    5624             :             return false;
    5625             :     }
    5626             : 
    5627             :     // Steps 5, 8.
    5628             :     //
    5629             :     // Call "return" if it is not undefined or null, and check that it returns
    5630             :     // an Object.
    5631        1608 :     if (!emit1(JSOP_SWAP))                                // ... RET ITER
    5632             :         return false;
    5633             : 
    5634        1608 :     Maybe<TryEmitter> tryCatch;
    5635             : 
    5636           0 :     if (completionKind == CompletionKind::Throw) {
    5637        1114 :         tryCatch.emplace(this, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
    5638             : 
    5639             :         // Mutate stack to balance stack for try-catch.
    5640           0 :         if (!emit1(JSOP_UNDEFINED))                       // ... RET ITER UNDEF
    5641             :             return false;
    5642           0 :         if (!tryCatch->emitTry())                         // ... RET ITER UNDEF
    5643             :             return false;
    5644           0 :         if (!emitDupAt(2))                                // ... RET ITER UNDEF RET
    5645             :             return false;
    5646        1114 :         if (!emitDupAt(2))                                // ... RET ITER UNDEF RET ITER
    5647             :             return false;
    5648             :     }
    5649             : 
    5650        1608 :     if (!emitCall(JSOP_CALL, 0))                          // ... ... RESULT
    5651             :         return false;
    5652        1608 :     checkTypeSet(JSOP_CALL);
    5653             : 
    5654        1608 :     if (iterKind == IteratorKind::Async) {
    5655           0 :         if (completionKind != CompletionKind::Throw) {
    5656             :             // Await clobbers rval, so save the current rval.
    5657           2 :             if (!emit1(JSOP_GETRVAL))                     // ... ... RESULT RVAL
    5658             :                 return false;
    5659           2 :             if (!emit1(JSOP_SWAP))                        // ... ... RVAL RESULT
    5660             :                 return false;
    5661             :         }
    5662           2 :         if (!emitAwaitInScope(currentScope))              // ... ... RVAL? RESULT
    5663             :             return false;
    5664             :     }
    5665             : 
    5666        1608 :     if (completionKind == CompletionKind::Throw) {
    5667           0 :         if (!emit1(JSOP_SWAP))                            // ... RET ITER RESULT UNDEF
    5668             :             return false;
    5669           0 :         if (!emit1(JSOP_POP))                             // ... RET ITER RESULT
    5670             :             return false;
    5671             : 
    5672        1114 :         if (!tryCatch->emitCatch())                       // ... RET ITER RESULT
    5673             :             return false;
    5674             : 
    5675             :         // Just ignore the exception thrown by call and await.
    5676        1114 :         if (!emit1(JSOP_EXCEPTION))                       // ... RET ITER RESULT EXC
    5677             :             return false;
    5678        1114 :         if (!emit1(JSOP_POP))                             // ... RET ITER RESULT
    5679             :             return false;
    5680             : 
    5681        1114 :         if (!tryCatch->emitEnd())                         // ... RET ITER RESULT
    5682             :             return false;
    5683             : 
    5684             :         // Restore stack.
    5685           0 :         if (!emit2(JSOP_UNPICK, 2))                       // ... RESULT RET ITER
    5686             :             return false;
    5687           1 :         if (!emitPopN(2))                                 // ... RESULT
    5688             :             return false;
    5689             :     } else {
    5690         494 :         if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) // ... RVAL? RESULT
    5691             :             return false;
    5692             : 
    5693           0 :         if (iterKind == IteratorKind::Async) {
    5694           2 :             if (!emit1(JSOP_SWAP))                        // ... RESULT RVAL
    5695             :                 return false;
    5696           0 :             if (!emit1(JSOP_SETRVAL))                     // ... RESULT
    5697             :                 return false;
    5698             :         }
    5699             :     }
    5700             : 
    5701           0 :     if (!ifReturnMethodIsDefined.emitElse())              // ... ITER RET
    5702             :         return false;
    5703             : 
    5704           0 :     if (!emit1(JSOP_POP))                                 // ... ITER
    5705             :         return false;
    5706             : 
    5707        1608 :     if (!ifReturnMethodIsDefined.emitEnd())
    5708             :         return false;
    5709             : 
    5710           0 :     return emit1(JSOP_POP);                               // ...
    5711             : }
    5712             : 
    5713             : template <typename InnerEmitter>
    5714             : bool
    5715           0 : BytecodeEmitter::wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, InnerEmitter emitter)
    5716             : {
    5717           0 :     MOZ_ASSERT(this->stackDepth >= iterDepth);
    5718             : 
    5719             :     // Pad a nop at the beginning of the bytecode covered by the trynote so
    5720             :     // that when unwinding environments, we may unwind to the scope
    5721             :     // corresponding to the pc *before* the start, in case the first bytecode
    5722             :     // emitted by |emitter| is the start of an inner scope. See comment above
    5723             :     // UnwindEnvironmentToTryPc.
    5724        1129 :     if (!emit1(JSOP_TRY_DESTRUCTURING_ITERCLOSE))
    5725             :         return false;
    5726             : 
    5727        1129 :     ptrdiff_t start = offset();
    5728           0 :     if (!emitter(this))
    5729             :         return false;
    5730        1129 :     ptrdiff_t end = offset();
    5731        1129 :     if (start != end)
    5732         578 :         return tryNoteList.append(JSTRY_DESTRUCTURING_ITERCLOSE, iterDepth, start, end);
    5733             :     return true;
    5734             : }
    5735             : 
    5736             : bool
    5737           0 : BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern)
    5738             : {
    5739          41 :     if (!emit1(JSOP_DUP))                                 // VALUE VALUE
    5740             :         return false;
    5741          41 :     if (!emit1(JSOP_UNDEFINED))                           // VALUE VALUE UNDEFINED
    5742             :         return false;
    5743          41 :     if (!emit1(JSOP_STRICTEQ))                            // VALUE EQL?
    5744             :         return false;
    5745             :     // Emit source note to enable ion compilation.
    5746          41 :     if (!newSrcNote(SRC_IF))
    5747             :         return false;
    5748          41 :     JumpList jump;
    5749          41 :     if (!emitJump(JSOP_IFEQ, &jump))                      // VALUE
    5750             :         return false;
    5751          41 :     if (!emit1(JSOP_POP))                                 // .
    5752             :         return false;
    5753          41 :     if (!emitInitializerInBranch(defaultExpr, pattern))   // DEFAULTVALUE
    5754             :         return false;
    5755          41 :     if (!emitJumpTargetAndPatch(jump))
    5756             :         return false;
    5757          41 :     return true;
    5758             : }
    5759             : 
    5760             : bool
    5761         838 : BytecodeEmitter::setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name)
    5762             : {
    5763         838 :     MOZ_ASSERT(maybeFun->isDirectRHSAnonFunction());
    5764             : 
    5765         838 :     if (maybeFun->isKind(ParseNodeKind::Function)) {
    5766             :         // Function doesn't have 'name' property at this point.
    5767             :         // Set function's name at compile time.
    5768        1662 :         JSFunction* fun = maybeFun->pn_funbox->function();
    5769             : 
    5770             :         // The inferred name may already be set if this function is an
    5771             :         // interpreted lazy function and we OOM'ed after we set the inferred
    5772             :         // name the first time.
    5773         831 :         if (fun->hasInferredName()) {
    5774           0 :             MOZ_ASSERT(fun->isInterpretedLazy());
    5775           0 :             MOZ_ASSERT(fun->inferredName() == name);
    5776             : 
    5777             :             return true;
    5778             :         }
    5779             : 
    5780         831 :         fun->setInferredName(name);
    5781         831 :         return true;
    5782             :     }
    5783             : 
    5784           7 :     MOZ_ASSERT(maybeFun->isKind(ParseNodeKind::Class));
    5785             : 
    5786             :     uint32_t nameIndex;
    5787           7 :     if (!makeAtomIndex(name, &nameIndex))
    5788             :         return false;
    5789           7 :     if (!emitIndexOp(JSOP_STRING, nameIndex))   // FUN NAME
    5790             :         return false;
    5791           7 :     uint8_t kind = uint8_t(FunctionPrefixKind::None);
    5792           7 :     if (!emit2(JSOP_SETFUNNAME, kind))          // FUN
    5793             :         return false;
    5794           7 :     return true;
    5795             : }
    5796             : 
    5797             : bool
    5798       15121 : BytecodeEmitter::emitInitializer(ParseNode* initializer, ParseNode* pattern)
    5799             : {
    5800       15121 :     if (!emitTree(initializer))
    5801             :         return false;
    5802             : 
    5803       15121 :     if (initializer->isDirectRHSAnonFunction()) {
    5804         312 :         MOZ_ASSERT(!pattern->isInParens());
    5805         624 :         RootedAtom name(cx, pattern->name());
    5806         312 :         if (!setOrEmitSetFunName(initializer, name))
    5807           0 :             return false;
    5808             :     }
    5809             : 
    5810             :     return true;
    5811             : }
    5812             : 
    5813             : bool
    5814         584 : BytecodeEmitter::emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern)
    5815             : {
    5816        1168 :     TDZCheckCache tdzCache(this);
    5817        1168 :     return emitInitializer(initializer, pattern);
    5818             : }
    5819             : 
    5820             : bool
    5821         309 : BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav)
    5822             : {
    5823         309 :     MOZ_ASSERT(pattern->isKind(ParseNodeKind::Array));
    5824         309 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    5825         309 :     MOZ_ASSERT(this->stackDepth != 0);
    5826             : 
    5827             :     // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
    5828             :     //
    5829             :     // Lines that are annotated "covered by trynote" mean that upon throwing
    5830             :     // an exception, IteratorClose is called on iter only if done is false.
    5831             :     //
    5832             :     //   let x, y;
    5833             :     //   let a, b, c, d;
    5834             :     //   let iter, next, lref, result, done, value; // stack values
    5835             :     //
    5836             :     //   iter = x[Symbol.iterator]();
    5837             :     //   next = iter.next;
    5838             :     //
    5839             :     //   // ==== emitted by loop for a ====
    5840             :     //   lref = GetReference(a);              // covered by trynote
    5841             :     //
    5842             :     //   result = Call(next, iter);
    5843             :     //   done = result.done;
    5844             :     //
    5845             :     //   if (done)
    5846             :     //     value = undefined;
    5847             :     //   else
    5848             :     //     value = result.value;
    5849             :     //
    5850             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5851             :     //
    5852             :     //   // ==== emitted by loop for b ====
    5853             :     //   lref = GetReference(b);              // covered by trynote
    5854             :     //
    5855             :     //   if (done) {
    5856             :     //     value = undefined;
    5857             :     //   } else {
    5858             :     //     result = Call(next, iter);
    5859             :     //     done = result.done;
    5860             :     //     if (done)
    5861             :     //       value = undefined;
    5862             :     //     else
    5863             :     //       value = result.value;
    5864             :     //   }
    5865             :     //
    5866             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5867             :     //
    5868             :     //   // ==== emitted by loop for elision ====
    5869             :     //   if (done) {
    5870             :     //     value = undefined;
    5871             :     //   } else {
    5872             :     //     result = Call(next, iter);
    5873             :     //     done = result.done;
    5874             :     //     if (done)
    5875             :     //       value = undefined;
    5876             :     //     else
    5877             :     //       value = result.value;
    5878             :     //   }
    5879             :     //
    5880             :     //   // ==== emitted by loop for c ====
    5881             :     //   lref = GetReference(c);              // covered by trynote
    5882             :     //
    5883             :     //   if (done) {
    5884             :     //     value = undefined;
    5885             :     //   } else {
    5886             :     //     result = Call(next, iter);
    5887             :     //     done = result.done;
    5888             :     //     if (done)
    5889             :     //       value = undefined;
    5890             :     //     else
    5891             :     //       value = result.value;
    5892             :     //   }
    5893             :     //
    5894             :     //   if (value === undefined)
    5895             :     //     value = y;                         // covered by trynote
    5896             :     //
    5897             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5898             :     //
    5899             :     //   // ==== emitted by loop for d ====
    5900             :     //   lref = GetReference(d);              // covered by trynote
    5901             :     //
    5902             :     //   if (done)
    5903             :     //     value = [];
    5904             :     //   else
    5905             :     //     value = [...iter];
    5906             :     //
    5907             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5908             :     //
    5909             :     //   // === emitted after loop ===
    5910             :     //   if (!done)
    5911             :     //      IteratorClose(iter);
    5912             : 
    5913             :     // Use an iterator to destructure the RHS, instead of index lookup. We
    5914             :     // must leave the *original* value on the stack.
    5915         309 :     if (!emit1(JSOP_DUP))                                         // ... OBJ OBJ
    5916             :         return false;
    5917           0 :     if (!emitIterator())                                          // ... OBJ NEXT ITER
    5918             :         return false;
    5919             : 
    5920             :     // For an empty pattern [], call IteratorClose unconditionally. Nothing
    5921             :     // else needs to be done.
    5922         309 :     if (!pattern->pn_head) {
    5923           0 :         if (!emit1(JSOP_SWAP))                                    // ... OBJ ITER NEXT
    5924             :             return false;
    5925           0 :         if (!emit1(JSOP_POP))                                     // ... OBJ ITER
    5926             :             return false;
    5927             : 
    5928           0 :         return emitIteratorCloseInInnermostScope();               // ... OBJ
    5929             :     }
    5930             : 
    5931             :     // Push an initial FALSE value for DONE.
    5932           0 :     if (!emit1(JSOP_FALSE))                                       // ... OBJ NEXT ITER FALSE
    5933             :         return false;
    5934             : 
    5935             :     // JSTRY_DESTRUCTURING_ITERCLOSE expects the iterator and the done value
    5936             :     // to be the second to top and the top of the stack, respectively.
    5937             :     // IteratorClose is called upon exception only if done is false.
    5938         309 :     int32_t tryNoteDepth = stackDepth;
    5939             : 
    5940           0 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    5941           0 :         bool isFirst = member == pattern->pn_head;
    5942        1814 :         DebugOnly<bool> hasNext = !!member->pn_next;
    5943             : 
    5944         605 :         size_t emitted = 0;
    5945             : 
    5946             :         // Spec requires LHS reference to be evaluated first.
    5947         605 :         ParseNode* lhsPattern = member;
    5948           0 :         if (lhsPattern->isKind(ParseNodeKind::Assign))
    5949           1 :             lhsPattern = lhsPattern->pn_left;
    5950             : 
    5951           0 :         bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
    5952         605 :         if (!isElision) {
    5953           0 :             auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) {
    5954             :                 return bce->emitDestructuringLHSRef(lhsPattern, &emitted); // ... OBJ NEXT ITER DONE *LREF
    5955        1128 :             };
    5956         564 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitLHSRef))
    5957           0 :                 return false;
    5958             :         }
    5959             : 
    5960             :         // Pick the DONE value to the top of the stack.
    5961         605 :         if (emitted) {
    5962           0 :             if (!emit2(JSOP_PICK, emitted))                       // ... OBJ NEXT ITER *LREF DONE
    5963             :                 return false;
    5964             :         }
    5965             : 
    5966           0 :         if (isFirst) {
    5967             :             // If this element is the first, DONE is always FALSE, so pop it.
    5968             :             //
    5969             :             // Non-first elements should emit if-else depending on the
    5970             :             // member pattern, below.
    5971         309 :             if (!emit1(JSOP_POP))                                 // ... OBJ NEXT ITER *LREF
    5972             :                 return false;
    5973             :         }
    5974             : 
    5975         605 :         if (member->isKind(ParseNodeKind::Spread)) {
    5976           1 :             InternalIfEmitter ifThenElse(this);
    5977           0 :             if (!isFirst) {
    5978             :                 // If spread is not the first element of the pattern,
    5979             :                 // iterator can already be completed.
    5980             :                                                                   // ... OBJ NEXT ITER *LREF DONE
    5981           1 :                 if (!ifThenElse.emitThenElse())                   // ... OBJ NEXT ITER *LREF
    5982           0 :                     return false;
    5983             : 
    5984           1 :                 if (!emitUint32Operand(JSOP_NEWARRAY, 0))         // ... OBJ NEXT ITER *LREF ARRAY
    5985             :                     return false;
    5986           0 :                 if (!ifThenElse.emitElse())                       // ... OBJ NEXT ITER *LREF
    5987             :                     return false;
    5988             :             }
    5989             : 
    5990             :             // If iterator is not completed, create a new array with the rest
    5991             :             // of the iterator.
    5992           1 :             if (!emitDupAt(emitted + 1))                          // ... OBJ NEXT ITER *LREF NEXT
    5993             :                 return false;
    5994           1 :             if (!emitDupAt(emitted + 1))                          // ... OBJ NEXT ITER *LREF NEXT ITER
    5995             :                 return false;
    5996           0 :             if (!emitUint32Operand(JSOP_NEWARRAY, 0))             // ... OBJ NEXT ITER *LREF NEXT ITER ARRAY
    5997             :                 return false;
    5998           1 :             if (!emitNumberOp(0))                                 // ... OBJ NEXT ITER *LREF NEXT ITER ARRAY INDEX
    5999             :                 return false;
    6000           1 :             if (!emitSpread())                                    // ... OBJ NEXT ITER *LREF ARRAY INDEX
    6001             :                 return false;
    6002           1 :             if (!emit1(JSOP_POP))                                 // ... OBJ NEXT ITER *LREF ARRAY
    6003             :                 return false;
    6004             : 
    6005           1 :             if (!isFirst) {
    6006           0 :                 if (!ifThenElse.emitEnd())
    6007             :                     return false;
    6008           1 :                 MOZ_ASSERT(ifThenElse.pushed() == 1);
    6009             :             }
    6010             : 
    6011             :             // At this point the iterator is done. Unpick a TRUE value for DONE above ITER.
    6012           0 :             if (!emit1(JSOP_TRUE))                                // ... OBJ NEXT ITER *LREF ARRAY TRUE
    6013             :                 return false;
    6014           0 :             if (!emit2(JSOP_UNPICK, emitted + 1))                 // ... OBJ NEXT ITER TRUE *LREF ARRAY
    6015             :                 return false;
    6016             : 
    6017             :             auto emitAssignment = [member, flav](BytecodeEmitter* bce) {
    6018             :                 return bce->emitSetOrInitializeDestructuring(member, flav); // ... OBJ NEXT ITER TRUE
    6019           2 :             };
    6020           1 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitAssignment))
    6021             :                 return false;
    6022             : 
    6023           0 :             MOZ_ASSERT(!hasNext);
    6024           1 :             break;
    6025             :         }
    6026             : 
    6027         604 :         ParseNode* pndefault = nullptr;
    6028         604 :         if (member->isKind(ParseNodeKind::Assign))
    6029           1 :             pndefault = member->pn_right;
    6030             : 
    6031         604 :         MOZ_ASSERT(!member->isKind(ParseNodeKind::Spread));
    6032             : 
    6033        1208 :         InternalIfEmitter ifAlreadyDone(this);
    6034           0 :         if (!isFirst) {
    6035             :                                                                   // ... OBJ NEXT ITER *LREF DONE
    6036         295 :             if (!ifAlreadyDone.emitThenElse())                    // ... OBJ NEXT ITER *LREF
    6037             :                 return false;
    6038             : 
    6039           0 :             if (!emit1(JSOP_UNDEFINED))                           // ... OBJ NEXT ITER *LREF UNDEF
    6040             :                 return false;
    6041           0 :             if (!emit1(JSOP_NOP_DESTRUCTURING))                   // ... OBJ NEXT ITER *LREF UNDEF
    6042             :                 return false;
    6043             : 
    6044             :             // The iterator is done. Unpick a TRUE value for DONE above ITER.
    6045           0 :             if (!emit1(JSOP_TRUE))                                // ... OBJ NEXT ITER *LREF UNDEF TRUE
    6046             :                 return false;
    6047           0 :             if (!emit2(JSOP_UNPICK, emitted + 1))                 // ... OBJ NEXT ITER TRUE *LREF UNDEF
    6048             :                 return false;
    6049             : 
    6050           0 :             if (!ifAlreadyDone.emitElse())                        // ... OBJ NEXT ITER *LREF
    6051             :                 return false;
    6052             :         }
    6053             : 
    6054           0 :         if (!emitDupAt(emitted + 1))                              // ... OBJ NEXT ITER *LREF NEXT
    6055             :             return false;
    6056           0 :         if (!emitDupAt(emitted + 1))                              // ... OBJ NEXT ITER *LREF NEXT ITER
    6057             :             return false;
    6058         604 :         if (!emitIteratorNext(pattern))                           // ... OBJ NEXT ITER *LREF RESULT
    6059             :             return false;
    6060         604 :         if (!emit1(JSOP_DUP))                                     // ... OBJ NEXT ITER *LREF RESULT RESULT
    6061             :             return false;
    6062        1812 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))          // ... OBJ NEXT ITER *LREF RESULT DONE
    6063             :             return false;
    6064             : 
    6065         604 :         if (!emit1(JSOP_DUP))                                     // ... OBJ NEXT ITER *LREF RESULT DONE DONE
    6066             :             return false;
    6067         604 :         if (!emit2(JSOP_UNPICK, emitted + 2))                     // ... OBJ NEXT ITER DONE *LREF RESULT DONE
    6068             :             return false;
    6069             : 
    6070        1208 :         InternalIfEmitter ifDone(this);
    6071           0 :         if (!ifDone.emitThenElse())                               // ... OBJ NEXT ITER DONE *LREF RESULT
    6072             :             return false;
    6073             : 
    6074           0 :         if (!emit1(JSOP_POP))                                     // ... OBJ NEXT ITER DONE *LREF
    6075             :             return false;
    6076         604 :         if (!emit1(JSOP_UNDEFINED))                               // ... OBJ NEXT ITER DONE *LREF UNDEF
    6077             :             return false;
    6078         604 :         if (!emit1(JSOP_NOP_DESTRUCTURING))                       // ... OBJ NEXT ITER DONE *LREF UNDEF
    6079             :             return false;
    6080             : 
    6081           0 :         if (!ifDone.emitElse())                                   // ... OBJ NEXT ITER DONE *LREF RESULT
    6082             :             return false;
    6083             : 
    6084           0 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP))         // ... OBJ NEXT ITER DONE *LREF VALUE
    6085             :             return false;
    6086             : 
    6087         604 :         if (!ifDone.emitEnd())
    6088             :             return false;
    6089         604 :         MOZ_ASSERT(ifDone.pushed() == 0);
    6090             : 
    6091           0 :         if (!isFirst) {
    6092           0 :             if (!ifAlreadyDone.emitEnd())
    6093             :                 return false;
    6094           0 :             MOZ_ASSERT(ifAlreadyDone.pushed() == 2);
    6095             :         }
    6096             : 
    6097         604 :         if (pndefault) {
    6098           0 :             auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
    6099             :                 return bce->emitDefault(pndefault, lhsPattern);    // ... OBJ NEXT ITER DONE *LREF VALUE
    6100           2 :             };
    6101             : 
    6102           0 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitDefault))
    6103           0 :                 return false;
    6104             :         }
    6105             : 
    6106           0 :         if (!isElision) {
    6107             :             auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
    6108             :                 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); // ... OBJ NEXT ITER DONE
    6109           0 :             };
    6110             : 
    6111           0 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitAssignment))
    6112           0 :                 return false;
    6113             :         } else {
    6114          41 :             if (!emit1(JSOP_POP))                                 // ... OBJ NEXT ITER DONE
    6115             :                 return false;
    6116             :         }
    6117             :     }
    6118             : 
    6119             :     // The last DONE value is on top of the stack. If not DONE, call
    6120             :     // IteratorClose.
    6121             :                                                                   // ... OBJ NEXT ITER DONE
    6122           0 :     InternalIfEmitter ifDone(this);
    6123           0 :     if (!ifDone.emitThenElse())                                   // ... OBJ NEXT ITER
    6124             :         return false;
    6125         309 :     if (!emitPopN(2))                                             // ... OBJ
    6126             :         return false;
    6127         309 :     if (!ifDone.emitElse())                                       // ... OBJ NEXT ITER
    6128             :         return false;
    6129         309 :     if (!emit1(JSOP_SWAP))                                        // ... OBJ ITER NEXT
    6130             :         return false;
    6131           0 :     if (!emit1(JSOP_POP))                                         // ... OBJ ITER
    6132             :         return false;
    6133         309 :     if (!emitIteratorCloseInInnermostScope())                     // ... OBJ
    6134             :         return false;
    6135         309 :     if (!ifDone.emitEnd())
    6136             :         return false;
    6137             : 
    6138           0 :     return true;
    6139             : }
    6140             : 
    6141             : bool
    6142          58 : BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName)
    6143             : {
    6144          58 :     MOZ_ASSERT(computedPropName->isKind(ParseNodeKind::ComputedName));
    6145           0 :     return emitTree(computedPropName->pn_kid) && emit1(JSOP_TOID);
    6146             : }
    6147             : 
    6148             : bool
    6149           0 : BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
    6150             : {
    6151         563 :     MOZ_ASSERT(pattern->isKind(ParseNodeKind::Object));
    6152           0 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    6153             : 
    6154         563 :     MOZ_ASSERT(this->stackDepth > 0);                             // ... RHS
    6155             : 
    6156         563 :     if (!emit1(JSOP_CHECKOBJCOERCIBLE))                           // ... RHS
    6157             :         return false;
    6158             : 
    6159           0 :     bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
    6160        1093 :                                         pattern->last()->isKind(ParseNodeKind::Spread);
    6161         563 :     if (needsRestPropertyExcludedSet) {
    6162           0 :         if (!emitDestructuringObjRestExclusionSet(pattern))       // ... RHS SET
    6163             :             return false;
    6164             : 
    6165           0 :         if (!emit1(JSOP_SWAP))                                    // ... SET RHS
    6166             :             return false;
    6167             :     }
    6168             : 
    6169        1635 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    6170             :         ParseNode* subpattern;
    6171        2144 :         if (member->isKind(ParseNodeKind::MutateProto) ||
    6172           0 :             member->isKind(ParseNodeKind::Spread))
    6173             :         {
    6174           0 :             subpattern = member->pn_kid;
    6175             :         } else {
    6176        1072 :             subpattern = member->pn_right;
    6177             :         }
    6178             : 
    6179           0 :         ParseNode* lhs = subpattern;
    6180        1072 :         MOZ_ASSERT_IF(member->isKind(ParseNodeKind::Spread),
    6181             :                       !lhs->isKind(ParseNodeKind::Assign));
    6182           0 :         if (lhs->isKind(ParseNodeKind::Assign))
    6183           0 :             lhs = lhs->pn_left;
    6184             : 
    6185             :         size_t emitted;
    6186        1072 :         if (!emitDestructuringLHSRef(lhs, &emitted))              // ... *SET RHS *LREF
    6187           0 :             return false;
    6188             : 
    6189             :         // Duplicate the value being destructured to use as a reference base.
    6190        1072 :         if (!emitDupAt(emitted))                                  // ... *SET RHS *LREF RHS
    6191             :             return false;
    6192             : 
    6193        1072 :         if (member->isKind(ParseNodeKind::Spread)) {
    6194           0 :             if (!updateSourceCoordNotes(member->pn_pos.begin))
    6195             :                 return false;
    6196             : 
    6197           0 :             if (!emitNewInit(JSProto_Object))                     // ... *SET RHS *LREF RHS TARGET
    6198             :                 return false;
    6199           0 :             if (!emit1(JSOP_DUP))                                 // ... *SET RHS *LREF RHS TARGET TARGET
    6200             :                 return false;
    6201           0 :             if (!emit2(JSOP_PICK, 2))                             // ... *SET RHS *LREF TARGET TARGET RHS
    6202             :                 return false;
    6203             : 
    6204           0 :             if (needsRestPropertyExcludedSet) {
    6205           0 :                 if (!emit2(JSOP_PICK, emitted + 4))               // ... RHS *LREF TARGET TARGET RHS SET
    6206             :                     return false;
    6207             :             }
    6208             : 
    6209             :             CopyOption option = needsRestPropertyExcludedSet
    6210           0 :                                 ? CopyOption::Filtered
    6211           0 :                                 : CopyOption::Unfiltered;
    6212           0 :             if (!emitCopyDataProperties(option))                  // ... RHS *LREF TARGET
    6213             :                 return false;
    6214             : 
    6215             :             // Destructure TARGET per this member's lhs.
    6216           0 :             if (!emitSetOrInitializeDestructuring(lhs, flav))     // ... RHS
    6217             :                 return false;
    6218             : 
    6219           0 :             MOZ_ASSERT(member == pattern->last(), "Rest property is always last");
    6220           0 :             break;
    6221             :         }
    6222             : 
    6223             :         // Now push the property name currently being matched, which is the
    6224             :         // current property name "label" on the left of a colon in the object
    6225             :         // initialiser.
    6226           1 :         bool needsGetElem = true;
    6227             : 
    6228           0 :         if (member->isKind(ParseNodeKind::MutateProto)) {
    6229           0 :             if (!emitAtomOp(cx->names().proto, JSOP_GETPROP))     // ... *SET RHS *LREF PROP
    6230             :                 return false;
    6231             :             needsGetElem = false;
    6232             :         } else {
    6233           0 :             MOZ_ASSERT(member->isKind(ParseNodeKind::Colon) ||
    6234             :                        member->isKind(ParseNodeKind::Shorthand));
    6235             : 
    6236           0 :             ParseNode* key = member->pn_left;
    6237        1072 :             if (key->isKind(ParseNodeKind::Number)) {
    6238           0 :                 if (!emitNumberOp(key->pn_dval))                  // ... *SET RHS *LREF RHS KEY
    6239             :                     return false;
    6240           0 :             } else if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
    6241           0 :                        key->isKind(ParseNodeKind::String))
    6242             :             {
    6243        1072 :                 if (!emitAtomOp(key->pn_atom, JSOP_GETPROP))      // ... *SET RHS *LREF PROP
    6244             :                     return false;
    6245             :                 needsGetElem = false;
    6246             :             } else {
    6247           0 :                 if (!emitComputedPropertyName(key))               // ... *SET RHS *LREF RHS KEY
    6248             :                     return false;
    6249             : 
    6250             :                 // Add the computed property key to the exclusion set.
    6251           0 :                 if (needsRestPropertyExcludedSet) {
    6252           0 :                     if (!emitDupAt(emitted + 3))                  // ... SET RHS *LREF RHS KEY SET
    6253             :                         return false;
    6254           0 :                     if (!emitDupAt(1))                            // ... SET RHS *LREF RHS KEY SET KEY
    6255             :                         return false;
    6256           0 :                     if (!emit1(JSOP_UNDEFINED))                   // ... SET RHS *LREF RHS KEY SET KEY UNDEFINED
    6257             :                         return false;
    6258           0 :                     if (!emit1(JSOP_INITELEM))                    // ... SET RHS *LREF RHS KEY SET
    6259             :                         return false;
    6260           0 :                     if (!emit1(JSOP_POP))                         // ... SET RHS *LREF RHS KEY
    6261             :                         return false;
    6262             :                 }
    6263             :             }
    6264             :         }
    6265             : 
    6266             :         // Get the property value if not done already.
    6267           0 :         if (needsGetElem && !emitElemOpBase(JSOP_GETELEM))        // ... *SET RHS *LREF PROP
    6268             :             return false;
    6269             : 
    6270        1072 :         if (subpattern->isKind(ParseNodeKind::Assign)) {
    6271          40 :             if (!emitDefault(subpattern->pn_right, lhs))          // ... *SET RHS *LREF VALUE
    6272             :                 return false;
    6273             :         }
    6274             : 
    6275             :         // Destructure PROP per this member's lhs.
    6276        1072 :         if (!emitSetOrInitializeDestructuring(subpattern, flav))  // ... *SET RHS
    6277             :             return false;
    6278             :     }
    6279             : 
    6280             :     return true;
    6281             : }
    6282             : 
    6283             : bool
    6284           0 : BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
    6285             : {
    6286           0 :     MOZ_ASSERT(pattern->isKind(ParseNodeKind::Object));
    6287           0 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    6288           0 :     MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread));
    6289             : 
    6290           0 :     ptrdiff_t offset = this->offset();
    6291           0 :     if (!emitNewInit(JSProto_Object))
    6292             :         return false;
    6293             : 
    6294             :     // Try to construct the shape of the object as we go, so we can emit a
    6295             :     // JSOP_NEWOBJECT with the final shape instead.
    6296             :     // In the case of computed property names and indices, we cannot fix the
    6297             :     // shape at bytecode compile time. When the shape cannot be determined,
    6298             :     // |obj| is nulled out.
    6299             : 
    6300             :     // No need to do any guessing for the object kind, since we know the upper
    6301             :     // bound of how many properties we plan to have.
    6302           0 :     gc::AllocKind kind = gc::GetGCObjectKind(pattern->pn_count - 1);
    6303           0 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
    6304           0 :     if (!obj)
    6305             :         return false;
    6306             : 
    6307           0 :     RootedAtom pnatom(cx);
    6308           0 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    6309           0 :         if (member->isKind(ParseNodeKind::Spread))
    6310             :             break;
    6311             : 
    6312           0 :         bool isIndex = false;
    6313           0 :         if (member->isKind(ParseNodeKind::MutateProto)) {
    6314           0 :             pnatom.set(cx->names().proto);
    6315             :         } else {
    6316           0 :             ParseNode* key = member->pn_left;
    6317           0 :             if (key->isKind(ParseNodeKind::Number)) {
    6318           0 :                 if (!emitNumberOp(key->pn_dval))
    6319             :                     return false;
    6320             :                 isIndex = true;
    6321           0 :             } else if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
    6322           0 :                        key->isKind(ParseNodeKind::String))
    6323             :             {
    6324           0 :                 pnatom.set(key->pn_atom);
    6325             :             } else {
    6326             :                 // Otherwise this is a computed property name which needs to
    6327             :                 // be added dynamically.
    6328           0 :                 obj.set(nullptr);
    6329           0 :                 continue;
    6330             :             }
    6331             :         }
    6332             : 
    6333             :         // Initialize elements with |undefined|.
    6334           0 :         if (!emit1(JSOP_UNDEFINED))
    6335             :             return false;
    6336             : 
    6337           0 :         if (isIndex) {
    6338           0 :             obj.set(nullptr);
    6339           0 :             if (!emit1(JSOP_INITELEM))
    6340             :                 return false;
    6341             :         } else {
    6342             :             uint32_t index;
    6343           0 :             if (!makeAtomIndex(pnatom, &index))
    6344           0 :                 return false;
    6345             : 
    6346           0 :             if (obj) {
    6347           0 :                 MOZ_ASSERT(!obj->inDictionaryMode());
    6348           0 :                 Rooted<jsid> id(cx, AtomToId(pnatom));
    6349           0 :                 if (!NativeDefineDataProperty(cx, obj, id, UndefinedHandleValue, JSPROP_ENUMERATE))
    6350           0 :                     return false;
    6351           0 :                 if (obj->inDictionaryMode())
    6352           0 :                     obj.set(nullptr);
    6353             :             }
    6354             : 
    6355           0 :             if (!emitIndex32(JSOP_INITPROP, index))
    6356             :                 return false;
    6357             :         }
    6358             :     }
    6359             : 
    6360           0 :     if (obj) {
    6361             :         // The object survived and has a predictable shape: update the
    6362             :         // original bytecode.
    6363           0 :         if (!replaceNewInitWithNewObject(obj, offset))
    6364             :             return false;
    6365             :     }
    6366             : 
    6367             :     return true;
    6368             : }
    6369             : 
    6370             : bool
    6371         872 : BytecodeEmitter::emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav)
    6372             : {
    6373         872 :     if (pattern->isKind(ParseNodeKind::Array))
    6374         309 :         return emitDestructuringOpsArray(pattern, flav);
    6375         563 :     return emitDestructuringOpsObject(pattern, flav);
    6376             : }
    6377             : 
    6378             : bool
    6379         754 : BytecodeEmitter::emitTemplateString(ParseNode* pn)
    6380             : {
    6381         754 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    6382             : 
    6383           0 :     bool pushedString = false;
    6384             : 
    6385        3668 :     for (ParseNode* pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
    6386           0 :         bool isString = (pn2->getKind() == ParseNodeKind::String ||
    6387           0 :                          pn2->getKind() == ParseNodeKind::TemplateString);
    6388             : 
    6389             :         // Skip empty strings. These are very common: a template string like
    6390             :         // `${a}${b}` has three empty strings and without this optimization
    6391             :         // we'd emit four JSOP_ADD operations instead of just one.
    6392        2914 :         if (isString && pn2->pn_atom->empty())
    6393             :             continue;
    6394             : 
    6395        2418 :         if (!isString) {
    6396             :             // We update source notes before emitting the expression
    6397        1080 :             if (!updateSourceCoordNotes(pn2->pn_pos.begin))
    6398             :                 return false;
    6399             :         }
    6400             : 
    6401           0 :         if (!emitTree(pn2))
    6402             :             return false;
    6403             : 
    6404        2418 :         if (!isString) {
    6405             :             // We need to convert the expression to a string
    6406        1080 :             if (!emit1(JSOP_TOSTRING))
    6407             :                 return false;
    6408             :         }
    6409             : 
    6410        2418 :         if (pushedString) {
    6411             :             // We've pushed two strings onto the stack. Add them together, leaving just one.
    6412           0 :             if (!emit1(JSOP_ADD))
    6413             :                 return false;
    6414             :         } else {
    6415             :             pushedString = true;
    6416             :         }
    6417             :     }
    6418             : 
    6419           0 :     if (!pushedString) {
    6420             :         // All strings were empty, this can happen for something like `${""}`.
    6421             :         // Just push an empty string.
    6422           0 :         if (!emitAtomOp(cx->names().empty, JSOP_STRING))
    6423             :             return false;
    6424             :     }
    6425             : 
    6426             :     return true;
    6427             : }
    6428             : 
    6429             : bool
    6430           0 : BytecodeEmitter::emitDeclarationList(ParseNode* declList)
    6431             : {
    6432           0 :     MOZ_ASSERT(declList->isArity(PN_LIST));
    6433           0 :     MOZ_ASSERT(declList->isOp(JSOP_NOP));
    6434             : 
    6435             :     ParseNode* next;
    6436           0 :     for (ParseNode* decl = declList->pn_head; decl; decl = next) {
    6437           0 :         if (!updateSourceCoordNotes(decl->pn_pos.begin))
    6438             :             return false;
    6439           0 :         next = decl->pn_next;
    6440             : 
    6441           0 :         if (decl->isKind(ParseNodeKind::Assign)) {
    6442           1 :             MOZ_ASSERT(decl->isOp(JSOP_NOP));
    6443             : 
    6444         524 :             ParseNode* pattern = decl->pn_left;
    6445         973 :             MOZ_ASSERT(pattern->isKind(ParseNodeKind::Array) ||
    6446             :                        pattern->isKind(ParseNodeKind::Object));
    6447             : 
    6448         524 :             if (!emitTree(decl->pn_right))
    6449             :                 return false;
    6450             : 
    6451         524 :             if (!emitDestructuringOps(pattern, DestructuringDeclaration))
    6452             :                 return false;
    6453             : 
    6454         524 :             if (!emit1(JSOP_POP))
    6455             :                 return false;
    6456             :         } else {
    6457       15294 :             if (!emitSingleDeclaration(declList, decl, decl->expr()))
    6458             :                 return false;
    6459             :         }
    6460             :     }
    6461             :     return true;
    6462             : }
    6463             : 
    6464             : bool
    6465       15294 : BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
    6466             :                                        ParseNode* initializer)
    6467             : {
    6468       15294 :     MOZ_ASSERT(decl->isKind(ParseNodeKind::Name));
    6469             : 
    6470             :     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
    6471           0 :     if (!initializer && declList->isKind(ParseNodeKind::Var))
    6472             :         return true;
    6473             : 
    6474           1 :     auto emitRhs = [initializer, declList, decl](BytecodeEmitter* bce, const NameLocation&, bool) {
    6475       15049 :         if (!initializer) {
    6476             :             // Lexical declarations are initialized to undefined without an
    6477             :             // initializer.
    6478           0 :             MOZ_ASSERT(declList->isKind(ParseNodeKind::Let),
    6479             :                        "var declarations without initializers handled above, "
    6480             :                        "and const declarations must have initializers");
    6481         512 :             Unused << declList; // silence clang -Wunused-lambda-capture in opt builds
    6482         512 :             return bce->emit1(JSOP_UNDEFINED);
    6483             :         }
    6484             : 
    6485             :         MOZ_ASSERT(initializer);
    6486           0 :         return bce->emitInitializer(initializer, decl);
    6487       15049 :     };
    6488             : 
    6489       15049 :     if (!emitInitializeName(decl, emitRhs))
    6490             :         return false;
    6491             : 
    6492             :     // Pop the RHS.
    6493           0 :     return emit1(JSOP_POP);
    6494             : }
    6495             : 
    6496             : static bool
    6497       12895 : EmitAssignmentRhs(BytecodeEmitter* bce, ParseNode* rhs, uint8_t offset)
    6498             : {
    6499             :     // If there is a RHS tree, emit the tree.
    6500           0 :     if (rhs)
    6501       12891 :         return bce->emitTree(rhs);
    6502             : 
    6503             :     // Otherwise the RHS value to assign is already on the stack, i.e., the
    6504             :     // next enumeration value in a for-in or for-of loop. Depending on how
    6505             :     // many other values have been pushed on the stack, we need to get the
    6506             :     // already-pushed RHS value.
    6507           4 :     if (offset != 1 && !bce->emit2(JSOP_PICK, offset - 1))
    6508             :         return false;
    6509             : 
    6510           0 :     return true;
    6511             : }
    6512             : 
    6513             : static inline JSOp
    6514       12895 : CompoundAssignmentParseNodeKindToJSOp(ParseNodeKind pnk)
    6515             : {
    6516       12895 :     switch (pnk) {
    6517             :       case ParseNodeKind::Assign:       return JSOP_NOP;
    6518         320 :       case ParseNodeKind::AddAssign:    return JSOP_ADD;
    6519          12 :       case ParseNodeKind::SubAssign:    return JSOP_SUB;
    6520          91 :       case ParseNodeKind::BitOrAssign:  return JSOP_BITOR;
    6521           7 :       case ParseNodeKind::BitXorAssign: return JSOP_BITXOR;
    6522           6 :       case ParseNodeKind::BitAndAssign: return JSOP_BITAND;
    6523           0 :       case ParseNodeKind::LshAssign:    return JSOP_LSH;
    6524           1 :       case ParseNodeKind::RshAssign:    return JSOP_RSH;
    6525           0 :       case ParseNodeKind::UrshAssign:   return JSOP_URSH;
    6526          12 :       case ParseNodeKind::MulAssign:    return JSOP_MUL;
    6527           5 :       case ParseNodeKind::DivAssign:    return JSOP_DIV;
    6528           0 :       case ParseNodeKind::ModAssign:    return JSOP_MOD;
    6529           0 :       case ParseNodeKind::PowAssign:    return JSOP_POW;
    6530           0 :       default: MOZ_CRASH("unexpected compound assignment op");
    6531             :     }
    6532             : }
    6533             : 
    6534             : bool
    6535       12895 : BytecodeEmitter::emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rhs)
    6536             : {
    6537       12895 :     JSOp op = CompoundAssignmentParseNodeKindToJSOp(pnk);
    6538             : 
    6539             :     // Name assignments are handled separately because choosing ops and when
    6540             :     // to emit BINDNAME is involved and should avoid duplication.
    6541           0 :     if (lhs->isKind(ParseNodeKind::Name)) {
    6542             :         auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc,
    6543           0 :                                       bool emittedBindOp)
    6544       24478 :         {
    6545             :             // For compound assignments, first get the LHS value, then emit
    6546             :             // the RHS and the op.
    6547           0 :             if (op != JSOP_NOP) {
    6548         384 :                 if (!bce->emitGetNameAtLocationForCompoundAssignment(lhs->name(), lhsLoc))
    6549             :                     return false;
    6550             :             }
    6551             : 
    6552             :             // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on
    6553             :             // the top of the stack and we need to pick the right RHS value.
    6554           0 :             if (!EmitAssignmentRhs(bce, rhs, emittedBindOp ? 2 : 1))
    6555             :                 return false;
    6556             : 
    6557        9580 :             if (rhs && rhs->isDirectRHSAnonFunction()) {
    6558          46 :                 MOZ_ASSERT(!lhs->isInParens());
    6559          46 :                 MOZ_ASSERT(op == JSOP_NOP);
    6560          92 :                 RootedAtom name(bce->cx, lhs->name());
    6561          92 :                 if (!bce->setOrEmitSetFunName(rhs, name))
    6562           0 :                     return false;
    6563             :             }
    6564             : 
    6565             :             // Emit the compound assignment op if there is one.
    6566        4792 :             if (op != JSOP_NOP) {
    6567           1 :                 if (!bce->emit1(op))
    6568             :                     return false;
    6569             :             }
    6570             : 
    6571             :             return true;
    6572        4792 :         };
    6573             : 
    6574        4792 :         return emitSetName(lhs, emitRhs);
    6575             :     }
    6576             : 
    6577             :     // Deal with non-name assignments.
    6578        8103 :     uint32_t atomIndex = (uint32_t) -1;
    6579        8103 :     uint8_t offset = 1;
    6580             : 
    6581        8103 :     switch (lhs->getKind()) {
    6582             :       case ParseNodeKind::Dot:
    6583           0 :         if (lhs->as<PropertyAccess>().isSuper()) {
    6584           0 :             if (!emitSuperPropLHS(&lhs->as<PropertyAccess>().expression()))
    6585             :                 return false;
    6586             :             offset += 2;
    6587             :         } else {
    6588        7541 :             if (!emitTree(lhs->expr()))
    6589             :                 return false;
    6590             :             offset += 1;
    6591             :         }
    6592        7541 :         if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
    6593             :             return false;
    6594             :         break;
    6595             :       case ParseNodeKind::Elem: {
    6596         533 :         MOZ_ASSERT(lhs->isArity(PN_BINARY));
    6597           0 :         EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign;
    6598        1066 :         if (lhs->as<PropertyByValue>().isSuper()) {
    6599           0 :             if (!emitSuperElemOperands(lhs, opt))
    6600             :                 return false;
    6601             :             offset += 3;
    6602             :         } else {
    6603         533 :             if (!emitElemOperands(lhs, opt))
    6604             :                 return false;
    6605             :             offset += 2;
    6606             :         }
    6607             :         break;
    6608             :       }
    6609             :       case ParseNodeKind::Array:
    6610             :       case ParseNodeKind::Object:
    6611             :         break;
    6612             :       case ParseNodeKind::Call:
    6613           0 :         if (!emitTree(lhs))
    6614             :             return false;
    6615             : 
    6616             :         // Assignment to function calls is forbidden, but we have to make the
    6617             :         // call first.  Now we can throw.
    6618           0 :         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS))
    6619             :             return false;
    6620             : 
    6621             :         // Rebalance the stack to placate stack-depth assertions.
    6622           0 :         if (!emit1(JSOP_POP))
    6623             :             return false;
    6624             :         break;
    6625             :       default:
    6626           0 :         MOZ_ASSERT(0);
    6627             :     }
    6628             : 
    6629        8103 :     if (op != JSOP_NOP) {
    6630          70 :         MOZ_ASSERT(rhs);
    6631          70 :         switch (lhs->getKind()) {
    6632             :           case ParseNodeKind::Dot: {
    6633             :             JSOp getOp;
    6634           0 :             if (lhs->as<PropertyAccess>().isSuper()) {
    6635           0 :                 if (!emit1(JSOP_DUP2))
    6636             :                     return false;
    6637             :                 getOp = JSOP_GETPROP_SUPER;
    6638             :             } else {
    6639          58 :                 if (!emit1(JSOP_DUP))
    6640             :                     return false;
    6641         174 :                 bool isLength = (lhs->pn_atom == cx->names().length);
    6642           0 :                 getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
    6643             :             }
    6644          58 :             if (!emitIndex32(getOp, atomIndex))
    6645             :                 return false;
    6646             :             break;
    6647             :           }
    6648             :           case ParseNodeKind::Elem: {
    6649             :             JSOp elemOp;
    6650           0 :             if (lhs->as<PropertyByValue>().isSuper()) {
    6651           0 :                 if (!emitDupAt(2))
    6652             :                     return false;
    6653           0 :                 if (!emitDupAt(2))
    6654             :                     return false;
    6655           0 :                 if (!emitDupAt(2))
    6656             :                     return false;
    6657             :                 elemOp = JSOP_GETELEM_SUPER;
    6658             :             } else {
    6659           0 :                 if (!emit1(JSOP_DUP2))
    6660             :                     return false;
    6661             :                 elemOp = JSOP_GETELEM;
    6662             :             }
    6663          12 :             if (!emitElemOpBase(elemOp))
    6664             :                 return false;
    6665             :             break;
    6666             :           }
    6667             :           case ParseNodeKind::Call:
    6668             :             // We just emitted a JSOP_THROWMSG and popped the call's return
    6669             :             // value.  Push a random value to make sure the stack depth is
    6670             :             // correct.
    6671           0 :             if (!emit1(JSOP_NULL))
    6672             :                 return false;
    6673             :             break;
    6674             :           default:;
    6675             :         }
    6676             :     }
    6677             : 
    6678           0 :     if (!EmitAssignmentRhs(this, rhs, offset))
    6679             :         return false;
    6680             : 
    6681             :     /* If += etc., emit the binary operator with a source note. */
    6682           0 :     if (op != JSOP_NOP) {
    6683          70 :         if (!newSrcNote(SRC_ASSIGNOP))
    6684             :             return false;
    6685           0 :         if (!emit1(op))
    6686             :             return false;
    6687             :     }
    6688             : 
    6689             :     /* Finally, emit the specialized assignment bytecode. */
    6690           0 :     switch (lhs->getKind()) {
    6691             :       case ParseNodeKind::Dot: {
    6692           0 :         JSOp setOp = lhs->as<PropertyAccess>().isSuper() ?
    6693           0 :                        (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) :
    6694           0 :                        (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP);
    6695        7541 :         if (!emitIndexOp(setOp, atomIndex))
    6696             :             return false;
    6697             :         break;
    6698             :       }
    6699             :       case ParseNodeKind::Call:
    6700             :         // We threw above, so nothing to do here.
    6701             :         break;
    6702             :       case ParseNodeKind::Elem: {
    6703        1066 :         JSOp setOp = lhs->as<PropertyByValue>().isSuper() ?
    6704           0 :                        sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER :
    6705        1066 :                        sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
    6706         533 :         if (!emit1(setOp))
    6707             :             return false;
    6708             :         break;
    6709             :       }
    6710             :       case ParseNodeKind::Array:
    6711             :       case ParseNodeKind::Object:
    6712          29 :         if (!emitDestructuringOps(lhs, DestructuringAssignment))
    6713             :             return false;
    6714             :         break;
    6715             :       default:
    6716           0 :         MOZ_ASSERT(0);
    6717             :     }
    6718             :     return true;
    6719             : }
    6720             : 
    6721             : bool
    6722           0 : ParseNode::getConstantValue(JSContext* cx, AllowConstantObjects allowObjects,
    6723             :                             MutableHandleValue vp, Value* compare, size_t ncompare,
    6724             :                             NewObjectKind newKind)
    6725             : {
    6726           1 :     MOZ_ASSERT(newKind == TenuredObject || newKind == SingletonObject);
    6727             : 
    6728        2384 :     switch (getKind()) {
    6729             :       case ParseNodeKind::Number:
    6730           0 :         vp.setNumber(pn_dval);
    6731           0 :         return true;
    6732             :       case ParseNodeKind::TemplateString:
    6733             :       case ParseNodeKind::String:
    6734           0 :         vp.setString(pn_atom);
    6735        2027 :         return true;
    6736             :       case ParseNodeKind::True:
    6737           0 :         vp.setBoolean(true);
    6738           0 :         return true;
    6739             :       case ParseNodeKind::False:
    6740           0 :         vp.setBoolean(false);
    6741           0 :         return true;
    6742             :       case ParseNodeKind::Null:
    6743           2 :         vp.setNull();
    6744           0 :         return true;
    6745             :       case ParseNodeKind::RawUndefined:
    6746           0 :         vp.setUndefined();
    6747           0 :         return true;
    6748             :       case ParseNodeKind::CallSiteObj:
    6749             :       case ParseNodeKind::Array: {
    6750             :         unsigned count;
    6751             :         ParseNode* pn;
    6752             : 
    6753           0 :         if (allowObjects == DontAllowObjects) {
    6754           7 :             vp.setMagic(JS_GENERIC_MAGIC);
    6755           7 :             return true;
    6756             :         }
    6757             : 
    6758         168 :         ObjectGroup::NewArrayKind arrayKind = ObjectGroup::NewArrayKind::Normal;
    6759         168 :         if (allowObjects == ForCopyOnWriteArray) {
    6760           1 :             arrayKind = ObjectGroup::NewArrayKind::CopyOnWrite;
    6761         125 :             allowObjects = DontAllowObjects;
    6762             :         }
    6763             : 
    6764         168 :         if (getKind() == ParseNodeKind::CallSiteObj) {
    6765           7 :             count = pn_count - 1;
    6766           0 :             pn = pn_head->pn_next;
    6767             :         } else {
    6768         161 :             MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
    6769           0 :             count = pn_count;
    6770         161 :             pn = pn_head;
    6771             :         }
    6772             : 
    6773         168 :         AutoValueVector values(cx);
    6774         504 :         if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), count))
    6775             :             return false;
    6776             :         size_t idx;
    6777           0 :         for (idx = 0; pn; idx++, pn = pn->pn_next) {
    6778           0 :             if (!pn->getConstantValue(cx, allowObjects, values[idx], values.begin(), idx))
    6779             :                 return false;
    6780        3548 :             if (values[idx].isMagic(JS_GENERIC_MAGIC)) {
    6781           0 :                 vp.setMagic(JS_GENERIC_MAGIC);
    6782           9 :                 return true;
    6783             :             }
    6784             :         }
    6785           0 :         MOZ_ASSERT(idx == count);
    6786             : 
    6787           0 :         ArrayObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
    6788           0 :                                                        newKind, arrayKind);
    6789         159 :         if (!obj)
    6790             :             return false;
    6791             : 
    6792         159 :         if (!CombineArrayElementTypes(cx, obj, compare, ncompare))
    6793             :             return false;
    6794             : 
    6795         318 :         vp.setObject(*obj);
    6796         159 :         return true;
    6797             :       }
    6798             :       case ParseNodeKind::Object: {
    6799          22 :         MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
    6800             : 
    6801          22 :         if (allowObjects == DontAllowObjects) {
    6802           0 :             vp.setMagic(JS_GENERIC_MAGIC);
    6803           0 :             return true;
    6804             :         }
    6805          20 :         MOZ_ASSERT(allowObjects == AllowObjects);
    6806             : 
    6807         100 :         Rooted<IdValueVector> properties(cx, IdValueVector(cx));
    6808             : 
    6809          60 :         RootedValue value(cx), idvalue(cx);
    6810         448 :         for (ParseNode* pn = pn_head; pn; pn = pn->pn_next) {
    6811         428 :             if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
    6812           0 :                 return false;
    6813         428 :             if (value.isMagic(JS_GENERIC_MAGIC)) {
    6814           0 :                 vp.setMagic(JS_GENERIC_MAGIC);
    6815           0 :                 return true;
    6816             :             }
    6817             : 
    6818         428 :             ParseNode* pnid = pn->pn_left;
    6819           0 :             if (pnid->isKind(ParseNodeKind::Number)) {
    6820           0 :                 idvalue = NumberValue(pnid->pn_dval);
    6821             :             } else {
    6822         781 :                 MOZ_ASSERT(pnid->isKind(ParseNodeKind::ObjectPropertyName) ||
    6823             :                            pnid->isKind(ParseNodeKind::String));
    6824        1284 :                 MOZ_ASSERT(pnid->pn_atom != cx->names().proto);
    6825        1284 :                 idvalue = StringValue(pnid->pn_atom);
    6826             :             }
    6827             : 
    6828         856 :             RootedId id(cx);
    6829           0 :             if (!ValueToId<CanGC>(cx, idvalue, &id))
    6830           0 :                 return false;
    6831             : 
    6832           0 :             if (!properties.append(IdValuePair(id, value)))
    6833             :                 return false;
    6834             :         }
    6835             : 
    6836           0 :         JSObject* obj = ObjectGroup::newPlainObject(cx, properties.begin(), properties.length(),
    6837          20 :                                                     newKind);
    6838           0 :         if (!obj)
    6839             :             return false;
    6840             : 
    6841           0 :         if (!CombinePlainObjectPropertyTypes(cx, obj, compare, ncompare))
    6842             :             return false;
    6843             : 
    6844           0 :         vp.setObject(*obj);
    6845          20 :         return true;
    6846             :       }
    6847             :       default:
    6848           0 :         MOZ_CRASH("Unexpected node");
    6849             :     }
    6850             :     return false;
    6851             : }
    6852             : 
    6853             : bool
    6854          43 : BytecodeEmitter::emitSingletonInitialiser(ParseNode* pn)
    6855             : {
    6856             :     NewObjectKind newKind =
    6857          43 :         (pn->getKind() == ParseNodeKind::Object) ? SingletonObject : TenuredObject;
    6858             : 
    6859         129 :     RootedValue value(cx);
    6860          43 :     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value, nullptr, 0, newKind))
    6861             :         return false;
    6862             : 
    6863           0 :     MOZ_ASSERT_IF(newKind == SingletonObject, value.toObject().isSingleton());
    6864             : 
    6865          86 :     ObjectBox* objbox = parser->newObjectBox(&value.toObject());
    6866          43 :     if (!objbox)
    6867             :         return false;
    6868             : 
    6869           0 :     return emitObjectOp(objbox, JSOP_OBJECT);
    6870             : }
    6871             : 
    6872             : bool
    6873           7 : BytecodeEmitter::emitCallSiteObject(ParseNode* pn)
    6874             : {
    6875           0 :     RootedValue value(cx);
    6876           0 :     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value))
    6877             :         return false;
    6878             : 
    6879           0 :     MOZ_ASSERT(value.isObject());
    6880             : 
    6881           0 :     ObjectBox* objbox1 = parser->newObjectBox(&value.toObject());
    6882           7 :     if (!objbox1)
    6883             :         return false;
    6884             : 
    6885          14 :     if (!pn->as<CallSiteNode>().getRawArrayValue(cx, &value))
    6886             :         return false;
    6887             : 
    6888           7 :     MOZ_ASSERT(value.isObject());
    6889             : 
    6890          14 :     ObjectBox* objbox2 = parser->newObjectBox(&value.toObject());
    6891           7 :     if (!objbox2)
    6892             :         return false;
    6893             : 
    6894           7 :     return emitObjectPairOp(objbox1, objbox2, JSOP_CALLSITEOBJ);
    6895             : }
    6896             : 
    6897             : /* See the SRC_FOR source note offsetBias comments later in this file. */
    6898             : JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
    6899             : JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
    6900             : 
    6901             : namespace {
    6902             : 
    6903             : class EmitLevelManager
    6904             : {
    6905             :     BytecodeEmitter* bce;
    6906             :   public:
    6907      475437 :     explicit EmitLevelManager(BytecodeEmitter* bce) : bce(bce) { bce->emitLevel++; }
    6908      475441 :     ~EmitLevelManager() { bce->emitLevel--; }
    6909             : };
    6910             : 
    6911             : } /* anonymous namespace */
    6912             : 
    6913             : bool
    6914        1003 : BytecodeEmitter::emitCatch(ParseNode* pn)
    6915             : {
    6916             :     // We must be nested under a try-finally statement.
    6917        2006 :     MOZ_ASSERT(innermostNestableControl->is<TryFinallyControl>());
    6918             : 
    6919             :     /* Pick up the pending exception and bind it to the catch variable. */
    6920        1003 :     if (!emit1(JSOP_EXCEPTION))
    6921             :         return false;
    6922             : 
    6923           0 :     ParseNode* pn2 = pn->pn_left;
    6924        1003 :     if (!pn2) {
    6925             :         // Catch parameter was omitted; just discard the exception.
    6926           0 :         if (!emit1(JSOP_POP))
    6927             :             return false;
    6928             :     } else {
    6929        1003 :         switch (pn2->getKind()) {
    6930             :           case ParseNodeKind::Array:
    6931             :           case ParseNodeKind::Object:
    6932           0 :             if (!emitDestructuringOps(pn2, DestructuringDeclaration))
    6933             :                 return false;
    6934           1 :             if (!emit1(JSOP_POP))
    6935             :                 return false;
    6936             :             break;
    6937             : 
    6938             :           case ParseNodeKind::Name:
    6939           0 :             if (!emitLexicalInitialization(pn2))
    6940             :                 return false;
    6941           0 :             if (!emit1(JSOP_POP))
    6942             :                 return false;
    6943             :             break;
    6944             : 
    6945             :           default:
    6946           0 :             MOZ_ASSERT(0);
    6947             :         }
    6948             :     }
    6949             : 
    6950             :     /* Emit the catch body. */
    6951        1003 :     return emitTree(pn->pn_right);
    6952             : }
    6953             : 
    6954             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
    6955             : // comment on EmitSwitch.
    6956             : MOZ_NEVER_INLINE bool
    6957        1074 : BytecodeEmitter::emitTry(ParseNode* pn)
    6958             : {
    6959        1074 :     ParseNode* catchScope = pn->pn_kid2;
    6960        1074 :     ParseNode* finallyNode = pn->pn_kid3;
    6961             : 
    6962             :     TryEmitter::Kind kind;
    6963        1074 :     if (catchScope) {
    6964        1003 :         if (finallyNode)
    6965             :             kind = TryEmitter::Kind::TryCatchFinally;
    6966             :         else
    6967         974 :             kind = TryEmitter::Kind::TryCatch;
    6968             :     } else {
    6969          71 :         MOZ_ASSERT(finallyNode);
    6970             :         kind = TryEmitter::Kind::TryFinally;
    6971             :     }
    6972        2148 :     TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
    6973             : 
    6974        1074 :     if (!tryCatch.emitTry())
    6975             :         return false;
    6976             : 
    6977           0 :     if (!emitTree(pn->pn_kid1))
    6978             :         return false;
    6979             : 
    6980             :     // If this try has a catch block, emit it.
    6981           0 :     if (catchScope) {
    6982             :         // The emitted code for a catch block looks like:
    6983             :         //
    6984             :         // [pushlexicalenv]             only if any local aliased
    6985             :         // exception
    6986             :         // setlocal 0; pop              assign or possibly destructure exception
    6987             :         // < catch block contents >
    6988             :         // debugleaveblock
    6989             :         // [poplexicalenv]              only if any local aliased
    6990             :         // if there is a finally block:
    6991             :         //   gosub <finally>
    6992             :         //   goto <after finally>
    6993        1003 :         if (!tryCatch.emitCatch())
    6994             :             return false;
    6995             : 
    6996             :         // Emit the lexical scope and catch body.
    6997        1003 :         MOZ_ASSERT(catchScope->isKind(ParseNodeKind::LexicalScope));
    6998        1003 :         if (!emitTree(catchScope))
    6999             :             return false;
    7000             :     }
    7001             : 
    7002             :     // Emit the finally handler, if there is one.
    7003        1074 :     if (finallyNode) {
    7004         300 :         if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin)))
    7005             :             return false;
    7006             : 
    7007         100 :         if (!emitTree(finallyNode))
    7008             :             return false;
    7009             :     }
    7010             : 
    7011        1074 :     if (!tryCatch.emitEnd())
    7012             :         return false;
    7013             : 
    7014        1074 :     return true;
    7015             : }
    7016             : 
    7017             : bool
    7018           0 : BytecodeEmitter::emitIf(ParseNode* pn)
    7019             : {
    7020           0 :     IfEmitter ifThenElse(this);
    7021             : 
    7022             :   if_again:
    7023             :     /* Emit code for the condition before pushing stmtInfo. */
    7024           0 :     if (!emitTree(pn->pn_kid1))
    7025             :         return false;
    7026             : 
    7027       13516 :     ParseNode* elseNode = pn->pn_kid3;
    7028       13516 :     if (elseNode) {
    7029        2054 :         if (!ifThenElse.emitThenElse())
    7030             :             return false;
    7031             :     } else {
    7032       11462 :         if (!ifThenElse.emitThen())
    7033             :             return false;
    7034             :     }
    7035             : 
    7036             :     /* Emit code for the then part. */
    7037           0 :     if (!emitTree(pn->pn_kid2))
    7038             :         return false;
    7039             : 
    7040       13516 :     if (elseNode) {
    7041        2054 :         if (elseNode->isKind(ParseNodeKind::If)) {
    7042         682 :             pn = elseNode;
    7043             : 
    7044         682 :             if (!ifThenElse.emitElseIf())
    7045             :                 return false;
    7046             : 
    7047             :             goto if_again;
    7048             :         }
    7049             : 
    7050        1372 :         if (!ifThenElse.emitElse())
    7051             :             return false;
    7052             : 
    7053             :         /* Emit code for the else part. */
    7054        1372 :         if (!emitTree(elseNode))
    7055             :             return false;
    7056             :     }
    7057             : 
    7058       12834 :     if (!ifThenElse.emitEnd())
    7059             :         return false;
    7060             : 
    7061       12834 :     return true;
    7062             : }
    7063             : 
    7064             : bool
    7065           0 : BytecodeEmitter::emitHoistedFunctionsInList(ParseNode* list)
    7066             : {
    7067         120 :     MOZ_ASSERT(list->pn_xflags & PNX_FUNCDEFS);
    7068             : 
    7069           0 :     for (ParseNode* pn = list->pn_head; pn; pn = pn->pn_next) {
    7070        1588 :         ParseNode* maybeFun = pn;
    7071             : 
    7072           0 :         if (!sc->strict()) {
    7073         272 :             while (maybeFun->isKind(ParseNodeKind::Label))
    7074           0 :                 maybeFun = maybeFun->as<LabeledStatement>().statement();
    7075             :         }
    7076             : 
    7077        1588 :         if (maybeFun->isKind(ParseNodeKind::Function) && maybeFun->functionIsHoisted()) {
    7078         208 :             if (!emitTree(maybeFun))
    7079             :                 return false;
    7080             :         }
    7081             :     }
    7082             : 
    7083             :     return true;
    7084             : }
    7085             : 
    7086             : bool
    7087       30359 : BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote)
    7088             : {
    7089           0 :     if (body->isKind(ParseNodeKind::StatementList) && body->pn_xflags & PNX_FUNCDEFS) {
    7090             :         // This block contains function statements whose definitions are
    7091             :         // hoisted to the top of the block. Emit these as a separate pass
    7092             :         // before the rest of the block.
    7093         120 :         if (!emitHoistedFunctionsInList(body))
    7094             :             return false;
    7095             :     }
    7096             : 
    7097             :     // Line notes were updated by emitLexicalScope.
    7098           0 :     return emitTree(body, ValueUsage::WantValue, emitLineNote);
    7099             : }
    7100             : 
    7101             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    7102             : // the comment on emitSwitch.
    7103             : MOZ_NEVER_INLINE bool
    7104           0 : BytecodeEmitter::emitLexicalScope(ParseNode* pn)
    7105             : {
    7106           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::LexicalScope));
    7107             : 
    7108           0 :     TDZCheckCache tdzCache(this);
    7109             : 
    7110           0 :     ParseNode* body = pn->scopeBody();
    7111           0 :     if (pn->isEmptyScope())
    7112       23634 :         return emitLexicalScopeBody(body);
    7113             : 
    7114             :     // We are about to emit some bytecode for what the spec calls "declaration
    7115             :     // instantiation". Assign these instructions to the opening `{` of the
    7116             :     // block. (Using the location of each declaration we're instantiating is
    7117             :     // too weird when stepping in the debugger.)
    7118           0 :     if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
    7119        6725 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    7120             :             return false;
    7121             :     }
    7122             : 
    7123       16288 :     EmitterScope emitterScope(this);
    7124             :     ScopeKind kind;
    7125        8144 :     if (body->isKind(ParseNodeKind::Catch)) {
    7126           0 :         kind = (!body->pn_left || body->pn_left->isKind(ParseNodeKind::Name))
    7127        1003 :                ? ScopeKind::SimpleCatch
    7128             :                : ScopeKind::Catch;
    7129             :     } else {
    7130             :         kind = ScopeKind::Lexical;
    7131             :     }
    7132             : 
    7133           0 :     if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
    7134             :         return false;
    7135             : 
    7136        8144 :     if (body->isKind(ParseNodeKind::For)) {
    7137             :         // for loops need to emit {FRESHEN,RECREATE}LEXICALENV if there are
    7138             :         // lexical declarations in the head. Signal this by passing a
    7139             :         // non-nullptr lexical scope.
    7140           0 :         if (!emitFor(body, &emitterScope))
    7141             :             return false;
    7142             :     } else {
    7143        6725 :         if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE))
    7144             :             return false;
    7145             :     }
    7146             : 
    7147        8144 :     return emitterScope.leave(this);
    7148             : }
    7149             : 
    7150             : bool
    7151           0 : BytecodeEmitter::emitWith(ParseNode* pn)
    7152             : {
    7153           0 :     if (!emitTree(pn->pn_left))
    7154             :         return false;
    7155             : 
    7156           0 :     EmitterScope emitterScope(this);
    7157           0 :     if (!emitterScope.enterWith(this))
    7158             :         return false;
    7159             : 
    7160           0 :     if (!emitTree(pn->pn_right))
    7161             :         return false;
    7162             : 
    7163           0 :     return emitterScope.leave(this);
    7164             : }
    7165             : 
    7166             : bool
    7167           0 : BytecodeEmitter::emitCopyDataProperties(CopyOption option)
    7168             : {
    7169          39 :     DebugOnly<int32_t> depth = this->stackDepth;
    7170             : 
    7171             :     uint32_t argc;
    7172           0 :     if (option == CopyOption::Filtered) {
    7173           0 :         MOZ_ASSERT(depth > 2);                 // TARGET SOURCE SET
    7174           0 :         argc = 3;
    7175             : 
    7176           0 :         if (!emitAtomOp(cx->names().CopyDataProperties,
    7177           0 :                         JSOP_GETINTRINSIC))    // TARGET SOURCE SET COPYDATAPROPERTIES
    7178             :         {
    7179             :             return false;
    7180             :         }
    7181             :     } else {
    7182           0 :         MOZ_ASSERT(depth > 1);                 // TARGET SOURCE
    7183           0 :         argc = 2;
    7184             : 
    7185          39 :         if (!emitAtomOp(cx->names().CopyDataPropertiesUnfiltered,
    7186           0 :                         JSOP_GETINTRINSIC))    // TARGET SOURCE COPYDATAPROPERTIES
    7187             :         {
    7188             :             return false;
    7189             :         }
    7190             :     }
    7191             : 
    7192          13 :     if (!emit1(JSOP_UNDEFINED))                // TARGET SOURCE *SET COPYDATAPROPERTIES UNDEFINED
    7193             :         return false;
    7194           0 :     if (!emit2(JSOP_PICK, argc + 1))           // SOURCE *SET COPYDATAPROPERTIES UNDEFINED TARGET
    7195             :         return false;
    7196          13 :     if (!emit2(JSOP_PICK, argc + 1))           // *SET COPYDATAPROPERTIES UNDEFINED TARGET SOURCE
    7197             :         return false;
    7198          13 :     if (option == CopyOption::Filtered) {
    7199           0 :         if (!emit2(JSOP_PICK, argc + 1))       // COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
    7200             :             return false;
    7201             :     }
    7202           0 :     if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
    7203             :         return false;
    7204          13 :     checkTypeSet(JSOP_CALL_IGNORES_RV);
    7205             : 
    7206          13 :     if (!emit1(JSOP_POP))                      // -
    7207             :         return false;
    7208             : 
    7209          13 :     MOZ_ASSERT(depth - int(argc) == this->stackDepth);
    7210             :     return true;
    7211             : }
    7212             : 
    7213             : bool
    7214        1672 : BytecodeEmitter::emitIterator()
    7215             : {
    7216             :     // Convert iterable to iterator.
    7217        1672 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7218             :         return false;
    7219           0 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator)))   // OBJ OBJ @@ITERATOR
    7220             :         return false;
    7221           0 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7222             :         return false;
    7223        1672 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7224             :         return false;
    7225        1672 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7226             :         return false;
    7227           0 :     checkTypeSet(JSOP_CALLITER);
    7228        1672 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7229             :         return false;
    7230        1672 :     if (!emit1(JSOP_DUP))                                         // ITER ITER
    7231             :         return false;
    7232        5016 :     if (!emitAtomOp(cx->names().next, JSOP_GETPROP))              // ITER NEXT
    7233             :         return false;
    7234           0 :     if (!emit1(JSOP_SWAP))                                        // NEXT ITER
    7235             :         return false;
    7236        1672 :     return true;
    7237             : }
    7238             : 
    7239             : bool
    7240           2 : BytecodeEmitter::emitAsyncIterator()
    7241             : {
    7242             :     // Convert iterable to iterator.
    7243           2 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7244             :         return false;
    7245           0 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::asyncIterator))) // OBJ OBJ @@ASYNCITERATOR
    7246             :         return false;
    7247           0 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7248             :         return false;
    7249             : 
    7250           2 :     InternalIfEmitter ifAsyncIterIsUndefined(this);
    7251           0 :     if (!emitPushNotUndefinedOrNull())                            // OBJ ITERFN !UNDEF-OR-NULL
    7252             :         return false;
    7253           2 :     if (!emit1(JSOP_NOT))                                         // OBJ ITERFN UNDEF-OR-NULL
    7254             :         return false;
    7255           0 :     if (!ifAsyncIterIsUndefined.emitThenElse())                   // OBJ ITERFN
    7256             :         return false;
    7257             : 
    7258           2 :     if (!emit1(JSOP_POP))                                         // OBJ
    7259             :         return false;
    7260           0 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7261             :         return false;
    7262           2 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator)))   // OBJ OBJ @@ITERATOR
    7263             :         return false;
    7264           2 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7265             :         return false;
    7266           0 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7267             :         return false;
    7268           2 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7269             :         return false;
    7270           2 :     checkTypeSet(JSOP_CALLITER);
    7271           0 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7272             :         return false;
    7273             : 
    7274           2 :     if (!emit1(JSOP_DUP))                                         // ITER ITER
    7275             :         return false;
    7276           6 :     if (!emitAtomOp(cx->names().next, JSOP_GETPROP))              // ITER SYNCNEXT
    7277             :         return false;
    7278             : 
    7279           2 :     if (!emit1(JSOP_TOASYNCITER))                                 // ITER
    7280             :         return false;
    7281             : 
    7282           2 :     if (!ifAsyncIterIsUndefined.emitElse())                       // OBJ ITERFN
    7283             :         return false;
    7284             : 
    7285           2 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7286             :         return false;
    7287           0 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7288             :         return false;
    7289           2 :     checkTypeSet(JSOP_CALLITER);
    7290           2 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7291             :         return false;
    7292             : 
    7293           2 :     if (!ifAsyncIterIsUndefined.emitEnd())                        // ITER
    7294             :         return false;
    7295             : 
    7296           2 :     if (!emit1(JSOP_DUP))                                         // ITER ITER
    7297             :         return false;
    7298           6 :     if (!emitAtomOp(cx->names().next, JSOP_GETPROP))              // ITER NEXT
    7299             :         return false;
    7300           2 :     if (!emit1(JSOP_SWAP))                                        // NEXT ITER
    7301             :         return false;
    7302             : 
    7303           2 :     return true;
    7304             : }
    7305             : 
    7306             : bool
    7307         243 : BytecodeEmitter::emitSpread(bool allowSelfHosted)
    7308             : {
    7309         486 :     LoopControl loopInfo(this, StatementKind::Spread);
    7310             : 
    7311             :     // Jump down to the loop condition to minimize overhead assuming at least
    7312             :     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
    7313             :     // find the loop-closing jump.
    7314             :     unsigned noteIndex;
    7315           0 :     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
    7316             :         return false;
    7317             : 
    7318             :     // Jump down to the loop condition to minimize overhead, assuming at least
    7319             :     // one iteration.  (This is also what we do for loops; whether this
    7320             :     // assumption holds for spreads is an unanswered question.)
    7321           0 :     JumpList initialJump;
    7322           0 :     if (!emitJump(JSOP_GOTO, &initialJump))               // NEXT ITER ARR I (during the goto)
    7323             :         return false;
    7324             : 
    7325         243 :     JumpTarget top{ -1 };
    7326         243 :     if (!emitLoopHead(nullptr, &top))                     // NEXT ITER ARR I
    7327             :         return false;
    7328             : 
    7329             :     // When we enter the goto above, we have NEXT ITER ARR I on the stack. But
    7330             :     // when we reach this point on the loop backedge (if spreading produces at
    7331             :     // least one value), we've additionally pushed a RESULT iteration value.
    7332             :     // Increment manually to reflect this.
    7333           0 :     this->stackDepth++;
    7334             : 
    7335         243 :     JumpList beq;
    7336           0 :     JumpTarget breakTarget{ -1 };
    7337             :     {
    7338             : #ifdef DEBUG
    7339         243 :         auto loopDepth = this->stackDepth;
    7340             : #endif
    7341             : 
    7342             :         // Emit code to assign result.value to the iteration variable.
    7343         729 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // NEXT ITER ARR I VALUE
    7344             :             return false;
    7345           0 :         if (!emit1(JSOP_INITELEM_INC))                    // NEXT ITER ARR (I+1)
    7346             :             return false;
    7347             : 
    7348         243 :         MOZ_ASSERT(this->stackDepth == loopDepth - 1);
    7349             : 
    7350             :         // Spread operations can't contain |continue|, so don't bother setting loop
    7351             :         // and enclosing "update" offsets, as we do with for-loops.
    7352             : 
    7353             :         // COME FROM the beginning of the loop to here.
    7354         243 :         if (!emitLoopEntry(nullptr, initialJump))         // NEXT ITER ARR I
    7355             :             return false;
    7356             : 
    7357         243 :         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT
    7358             :             return false;
    7359           0 :         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT ITER
    7360             :             return false;
    7361         243 :         if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted))  // ITER ARR I RESULT
    7362             :             return false;
    7363         243 :         if (!emit1(JSOP_DUP))                             // NEXT ITER ARR I RESULT RESULT
    7364             :             return false;
    7365         729 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // NEXT ITER ARR I RESULT DONE
    7366             :             return false;
    7367             : 
    7368           0 :         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget)) // NEXT ITER ARR I RESULT
    7369             :             return false;
    7370             : 
    7371           0 :         MOZ_ASSERT(this->stackDepth == loopDepth);
    7372             :     }
    7373             : 
    7374             :     // Let Ion know where the closing jump of this loop is.
    7375           0 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7376             :         return false;
    7377             : 
    7378             :     // No breaks or continues should occur in spreads.
    7379           0 :     MOZ_ASSERT(loopInfo.breaks.offset == -1);
    7380           0 :     MOZ_ASSERT(loopInfo.continues.offset == -1);
    7381             : 
    7382           0 :     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
    7383             :         return false;
    7384             : 
    7385         243 :     if (!emit2(JSOP_PICK, 4))                             // ITER ARR FINAL_INDEX RESULT NEXT
    7386             :         return false;
    7387         243 :     if (!emit2(JSOP_PICK, 4))                             // ARR FINAL_INDEX RESULT NEXT ITER
    7388             :         return false;
    7389             : 
    7390           0 :     return emitPopN(3);                                   // ARR FINAL_INDEX
    7391             : }
    7392             : 
    7393             : bool
    7394        1254 : BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
    7395             : {
    7396        2368 :     MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||
    7397             :                forHead->isKind(ParseNodeKind::ForOf));
    7398        1254 :     MOZ_ASSERT(forHead->isArity(PN_TERNARY));
    7399             : 
    7400        1254 :     MOZ_ASSERT(this->stackDepth >= 1,
    7401             :                "must have a per-iteration value for initializing");
    7402             : 
    7403        1254 :     ParseNode* target = forHead->pn_kid1;
    7404        1254 :     MOZ_ASSERT(!forHead->pn_kid2);
    7405             : 
    7406             :     // If the for-in/of loop didn't have a variable declaration, per-loop
    7407             :     // initialization is just assigning the iteration value to a target
    7408             :     // expression.
    7409           0 :     if (!parser->astGenerator().isDeclarationList(target))
    7410           4 :         return emitAssignment(target, ParseNodeKind::Assign, nullptr); // ... ITERVAL
    7411             : 
    7412             :     // Otherwise, per-loop initialization is (possibly) declaration
    7413             :     // initialization.  If the declaration is a lexical declaration, it must be
    7414             :     // initialized.  If the declaration is a variable declaration, an
    7415             :     // assignment to that name (which does *not* necessarily assign to the
    7416             :     // variable!) must be generated.
    7417             : 
    7418        1250 :     if (!updateSourceCoordNotes(target->pn_pos.begin))
    7419             :         return false;
    7420             : 
    7421           0 :     MOZ_ASSERT(target->isForLoopDeclaration());
    7422        1250 :     target = parser->astGenerator().singleBindingFromDeclaration(target);
    7423             : 
    7424           0 :     if (target->isKind(ParseNodeKind::Name)) {
    7425             :         auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
    7426        1056 :                                       bool emittedBindOp)
    7427             :         {
    7428           0 :             if (emittedBindOp) {
    7429             :                 // Per-iteration initialization in for-in/of loops computes the
    7430             :                 // iteration value *before* initializing.  Thus the
    7431             :                 // initializing value may be buried under a bind-specific value
    7432             :                 // on the stack.  Swap it to the top of the stack.
    7433           0 :                 MOZ_ASSERT(bce->stackDepth >= 2);
    7434           0 :                 return bce->emit1(JSOP_SWAP);
    7435             :             }
    7436             : 
    7437             :             // In cases of emitting a frame slot or environment slot,
    7438             :             // nothing needs be done.
    7439        1056 :             MOZ_ASSERT(bce->stackDepth >= 1);
    7440             :             return true;
    7441             :         };
    7442             : 
    7443             :         // The caller handles removing the iteration value from the stack.
    7444           0 :         return emitInitializeName(target, emitSwapScopeAndRhs);
    7445             :     }
    7446             : 
    7447           0 :     MOZ_ASSERT(!target->isKind(ParseNodeKind::Assign),
    7448             :                "for-in/of loop destructuring declarations can't have initializers");
    7449             : 
    7450         204 :     MOZ_ASSERT(target->isKind(ParseNodeKind::Array) ||
    7451             :                target->isKind(ParseNodeKind::Object));
    7452           0 :     return emitDestructuringOps(target, DestructuringDeclaration);
    7453             : }
    7454             : 
    7455             : bool
    7456           0 : BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope)
    7457             : {
    7458        1114 :     MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::For));
    7459        1114 :     MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
    7460             : 
    7461        1114 :     ParseNode* forOfHead = forOfLoop->pn_left;
    7462        1114 :     MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf));
    7463        1114 :     MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
    7464             : 
    7465           1 :     unsigned iflags = forOfLoop->pn_iflags;
    7466        1114 :     IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
    7467           0 :                             ? IteratorKind::Async
    7468        1114 :                             : IteratorKind::Sync;
    7469           0 :     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
    7470        1114 :     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
    7471             : 
    7472           0 :     ParseNode* forHeadExpr = forOfHead->pn_kid3;
    7473             : 
    7474             :     // Certain builtins (e.g. Array.from) are implemented in self-hosting
    7475             :     // as for-of loops.
    7476        1114 :     bool allowSelfHostedIter = false;
    7477           0 :     if (emitterMode == BytecodeEmitter::SelfHosting &&
    7478        1124 :         forHeadExpr->isKind(ParseNodeKind::Call) &&
    7479          15 :         forHeadExpr->pn_head->name() == cx->names().allowContentIter)
    7480             :     {
    7481           5 :         allowSelfHostedIter = true;
    7482             :     }
    7483             : 
    7484             :     // Evaluate the expression being iterated. The forHeadExpr should use a
    7485             :     // distinct TDZCheckCache to evaluate since (abstractly) it runs in its own
    7486             :     // LexicalEnvironment.
    7487        1114 :     if (!emitTreeInBranch(forHeadExpr))                   // ITERABLE
    7488             :         return false;
    7489        1114 :     if (iterKind == IteratorKind::Async) {
    7490           0 :         if (!emitAsyncIterator())                         // NEXT ITER
    7491             :             return false;
    7492             :     } else {
    7493           0 :         if (!emitIterator())                              // NEXT ITER
    7494             :             return false;
    7495             :     }
    7496             : 
    7497        1114 :     int32_t iterDepth = stackDepth;
    7498             : 
    7499             :     // For-of loops have the iterator next method, the iterator itself, and
    7500             :     // the result.value on the stack.
    7501             :     // Push an undefined to balance the stack.
    7502        1114 :     if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER UNDEF
    7503             :         return false;
    7504             : 
    7505        2228 :     ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
    7506             : 
    7507             :     // Annotate so IonMonkey can find the loop-closing jump.
    7508             :     unsigned noteIndex;
    7509           0 :     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
    7510             :         return false;
    7511             : 
    7512           0 :     JumpList initialJump;
    7513        1114 :     if (!emitJump(JSOP_GOTO, &initialJump))               // NEXT ITER UNDEF
    7514             :         return false;
    7515             : 
    7516        1114 :     JumpTarget top{ -1 };
    7517           0 :     if (!emitLoopHead(nullptr, &top))                     // NEXT ITER UNDEF
    7518             :         return false;
    7519             : 
    7520             :     // If the loop had an escaping lexical declaration, replace the current
    7521             :     // environment with an dead zoned one to implement TDZ semantics.
    7522        1114 :     if (headLexicalEmitterScope) {
    7523             :         // The environment chain only includes an environment for the for-of
    7524             :         // loop head *if* a scope binding is captured, thereby requiring
    7525             :         // recreation each iteration. If a lexical scope exists for the head,
    7526             :         // it must be the innermost one. If that scope has closed-over
    7527             :         // bindings inducing an environment, recreate the current environment.
    7528        2204 :         DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
    7529        2296 :         MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::Let) ||
    7530             :                    forOfTarget->isKind(ParseNodeKind::Const));
    7531        1102 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
    7532        1102 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7533             : 
    7534           0 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7535         236 :             if (!emit1(JSOP_RECREATELEXICALENV))          // NEXT ITER UNDEF
    7536             :                 return false;
    7537             :         }
    7538             : 
    7539             :         // For uncaptured bindings, put them back in TDZ.
    7540        1102 :         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
    7541             :             return false;
    7542             :     }
    7543             : 
    7544           0 :     JumpList beq;
    7545        1114 :     JumpTarget breakTarget{ -1 };
    7546             :     {
    7547             : #ifdef DEBUG
    7548           0 :         auto loopDepth = this->stackDepth;
    7549             : #endif
    7550             : 
    7551             :         // Make sure this code is attributed to the "for".
    7552        1114 :         if (!updateSourceCoordNotes(forOfHead->pn_pos.begin))
    7553           0 :             return false;
    7554             : 
    7555        1114 :         if (!emit1(JSOP_POP))                             // NEXT ITER
    7556             :             return false;
    7557           0 :         if (!emit1(JSOP_DUP2))                            // NEXT ITER NEXT ITER
    7558             :             return false;
    7559             : 
    7560        1114 :         if (!emitIteratorNext(forOfHead, iterKind, allowSelfHostedIter))
    7561             :             return false;                                 // NEXT ITER RESULT
    7562             : 
    7563           0 :         if (!emit1(JSOP_DUP))                             // NEXT ITER RESULT RESULT
    7564             :             return false;
    7565           0 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // NEXT ITER RESULT DONE
    7566             :             return false;
    7567             : 
    7568           0 :         InternalIfEmitter ifDone(this);
    7569             : 
    7570        1114 :         if (!ifDone.emitThen())                           // NEXT ITER RESULT
    7571             :             return false;
    7572             : 
    7573             :         // Remove RESULT from the stack to release it.
    7574           0 :         if (!emit1(JSOP_POP))                             // NEXT ITER
    7575             :             return false;
    7576           0 :         if (!emit1(JSOP_UNDEFINED))                       // NEXT ITER UNDEF
    7577             :             return false;
    7578             : 
    7579             :         // If the iteration is done, leave loop here, instead of the branch at
    7580             :         // the end of the loop.
    7581           0 :         if (!loopInfo.emitSpecialBreakForDone(this))      // NEXT ITER UNDEF
    7582             :             return false;
    7583             : 
    7584        1114 :         if (!ifDone.emitEnd())                            // NEXT ITER RESULT
    7585             :             return false;
    7586             : 
    7587             :         // Emit code to assign result.value to the iteration variable.
    7588             :         //
    7589             :         // Note that ES 13.7.5.13, step 5.c says getting result.value does not
    7590             :         // call IteratorClose, so start JSTRY_ITERCLOSE after the GETPROP.
    7591        3342 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // NEXT ITER VALUE
    7592             :             return false;
    7593             : 
    7594        1114 :         if (!loopInfo.emitBeginCodeNeedingIteratorClose(this))
    7595             :             return false;
    7596             : 
    7597        1114 :         if (!emitInitializeForInOrOfTarget(forOfHead))    // NEXT ITER VALUE
    7598             :             return false;
    7599             : 
    7600           0 :         MOZ_ASSERT(stackDepth == loopDepth,
    7601             :                    "the stack must be balanced around the initializing "
    7602             :                    "operation");
    7603             : 
    7604             :         // Remove VALUE from the stack to release it.
    7605           0 :         if (!emit1(JSOP_POP))                             // NEXT ITER
    7606             :             return false;
    7607        1114 :         if (!emit1(JSOP_UNDEFINED))                       // NEXT ITER UNDEF
    7608             :             return false;
    7609             : 
    7610             :         // Perform the loop body.
    7611        1114 :         ParseNode* forBody = forOfLoop->pn_right;
    7612        1114 :         if (!emitTree(forBody))                           // NEXT ITER UNDEF
    7613             :             return false;
    7614             : 
    7615        1114 :         MOZ_ASSERT(stackDepth == loopDepth,
    7616             :                    "the stack must be balanced around the for-of body");
    7617             : 
    7618        1114 :         if (!loopInfo.emitEndCodeNeedingIteratorClose(this))
    7619             :             return false;
    7620             : 
    7621             :         // Set offset for continues.
    7622           0 :         loopInfo.continueTarget = { offset() };
    7623             : 
    7624        1114 :         if (!emitLoopEntry(forHeadExpr, initialJump))     // NEXT ITER UNDEF
    7625             :             return false;
    7626             : 
    7627           0 :         if (!emit1(JSOP_FALSE))                           // NEXT ITER UNDEF FALSE
    7628             :             return false;
    7629        1114 :         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    7630             :             return false;                                 // NEXT ITER UNDEF
    7631             : 
    7632           0 :         MOZ_ASSERT(this->stackDepth == loopDepth);
    7633             :     }
    7634             : 
    7635             :     // Let Ion know where the closing jump of this loop is.
    7636        1114 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7637             :         return false;
    7638             : 
    7639        1114 :     if (!loopInfo.patchBreaksAndContinues(this))
    7640             :         return false;
    7641             : 
    7642        1114 :     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
    7643             :         return false;
    7644             : 
    7645        1114 :     return emitPopN(3);                                   //
    7646             : }
    7647             : 
    7648             : bool
    7649           0 : BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
    7650             : {
    7651         140 :     MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::For));
    7652         140 :     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
    7653         140 :     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
    7654             : 
    7655           0 :     ParseNode* forInHead = forInLoop->pn_left;
    7656         140 :     MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn));
    7657           0 :     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
    7658             : 
    7659             :     // Annex B: Evaluate the var-initializer expression if present.
    7660             :     // |for (var i = initializer in expr) { ... }|
    7661         140 :     ParseNode* forInTarget = forInHead->pn_kid1;
    7662           0 :     if (parser->astGenerator().isDeclarationList(forInTarget)) {
    7663         138 :         ParseNode* decl = parser->astGenerator().singleBindingFromDeclaration(forInTarget);
    7664         138 :         if (decl->isKind(ParseNodeKind::Name)) {
    7665           0 :             if (ParseNode* initializer = decl->expr()) {
    7666           0 :                 MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Var),
    7667             :                            "for-in initializers are only permitted for |var| declarations");
    7668             : 
    7669           0 :                 if (!updateSourceCoordNotes(decl->pn_pos.begin))
    7670           0 :                     return false;
    7671             : 
    7672             :                 auto emitRhs = [decl, initializer](BytecodeEmitter* bce, const NameLocation&, bool) {
    7673             :                     return bce->emitInitializer(initializer, decl);
    7674           0 :                 };
    7675             : 
    7676           0 :                 if (!emitInitializeName(decl, emitRhs))
    7677             :                     return false;
    7678             : 
    7679             :                 // Pop the initializer.
    7680           0 :                 if (!emit1(JSOP_POP))
    7681             :                     return false;
    7682             :             }
    7683             :         }
    7684             :     }
    7685             : 
    7686             :     // Evaluate the expression being iterated.
    7687           0 :     ParseNode* expr = forInHead->pn_kid3;
    7688         140 :     if (!emitTreeInBranch(expr))                          // EXPR
    7689             :         return false;
    7690             : 
    7691           0 :     MOZ_ASSERT(forInLoop->pn_iflags == 0);
    7692             : 
    7693         140 :     if (!emit1(JSOP_ITER))                                // ITER
    7694             :         return false;
    7695             : 
    7696             :     // For-in loops have both the iterator and the value on the stack. Push
    7697             :     // undefined to balance the stack.
    7698         140 :     if (!emit1(JSOP_UNDEFINED))                           // ITER ITERVAL
    7699             :         return false;
    7700             : 
    7701         280 :     LoopControl loopInfo(this, StatementKind::ForInLoop);
    7702             : 
    7703             :     /* Annotate so IonMonkey can find the loop-closing jump. */
    7704             :     unsigned noteIndex;
    7705         140 :     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
    7706             :         return false;
    7707             : 
    7708             :     // Jump down to the loop condition to minimize overhead (assuming at least
    7709             :     // one iteration, just like the other loop forms).
    7710         140 :     JumpList initialJump;
    7711         140 :     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ITERVAL
    7712             :         return false;
    7713             : 
    7714           0 :     JumpTarget top{ -1 };
    7715         140 :     if (!emitLoopHead(nullptr, &top))                     // ITER ITERVAL
    7716             :         return false;
    7717             : 
    7718             :     // If the loop had an escaping lexical declaration, replace the current
    7719             :     // environment with an dead zoned one to implement TDZ semantics.
    7720         140 :     if (headLexicalEmitterScope) {
    7721             :         // The environment chain only includes an environment for the for-in
    7722             :         // loop head *if* a scope binding is captured, thereby requiring
    7723             :         // recreation each iteration. If a lexical scope exists for the head,
    7724             :         // it must be the innermost one. If that scope has closed-over
    7725             :         // bindings inducing an environment, recreate the current environment.
    7726         122 :         MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Let) ||
    7727             :                    forInTarget->isKind(ParseNodeKind::Const));
    7728         118 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
    7729         118 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7730             : 
    7731         118 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7732          16 :             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER ITERVAL
    7733             :                 return false;
    7734             :         }
    7735             : 
    7736             :         // For uncaptured bindings, put them back in TDZ.
    7737         118 :         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
    7738             :             return false;
    7739             :     }
    7740             : 
    7741             :     {
    7742             : #ifdef DEBUG
    7743         140 :         auto loopDepth = this->stackDepth;
    7744             : #endif
    7745           0 :         MOZ_ASSERT(loopDepth >= 2);
    7746             : 
    7747         140 :         if (!emit1(JSOP_ITERNEXT))                        // ITER ITERVAL
    7748             :             return false;
    7749             : 
    7750         140 :         if (!emitInitializeForInOrOfTarget(forInHead))    // ITER ITERVAL
    7751             :             return false;
    7752             : 
    7753         140 :         MOZ_ASSERT(this->stackDepth == loopDepth,
    7754             :                    "iterator and iterval must be left on the stack");
    7755             :     }
    7756             : 
    7757             :     // Perform the loop body.
    7758         140 :     ParseNode* forBody = forInLoop->pn_right;
    7759           0 :     if (!emitTree(forBody))                               // ITER ITERVAL
    7760             :         return false;
    7761             : 
    7762             :     // Set offset for continues.
    7763         140 :     loopInfo.continueTarget = { offset() };
    7764             : 
    7765             :     // Make sure this code is attributed to the "for".
    7766         140 :     if (!updateSourceCoordNotes(forInHead->pn_pos.begin))
    7767             :         return false;
    7768             : 
    7769           0 :     if (!emitLoopEntry(nullptr, initialJump))             // ITER ITERVAL
    7770             :         return false;
    7771         140 :     if (!emit1(JSOP_POP))                                 // ITER
    7772             :         return false;
    7773         140 :     if (!emit1(JSOP_MOREITER))                            // ITER NEXTITERVAL?
    7774             :         return false;
    7775         140 :     if (!emit1(JSOP_ISNOITER))                            // ITER NEXTITERVAL? ISNOITER
    7776             :         return false;
    7777             : 
    7778         140 :     JumpList beq;
    7779           0 :     JumpTarget breakTarget{ -1 };
    7780           0 :     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    7781             :         return false;                                     // ITER NEXTITERVAL
    7782             : 
    7783             :     // Set the srcnote offset so we can find the closing jump.
    7784         140 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7785             :         return false;
    7786             : 
    7787         140 :     if (!loopInfo.patchBreaksAndContinues(this))
    7788             :         return false;
    7789             : 
    7790             :     // Pop the enumeration value.
    7791         140 :     if (!emit1(JSOP_POP))                                 // ITER
    7792             :         return false;
    7793             : 
    7794         140 :     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, offset()))
    7795             :         return false;
    7796             : 
    7797           0 :     return emit1(JSOP_ENDITER);                           //
    7798             : }
    7799             : 
    7800             : /* C-style `for (init; cond; update) ...` loop. */
    7801             : bool
    7802           0 : BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
    7803             : {
    7804         706 :     LoopControl loopInfo(this, StatementKind::ForLoop);
    7805             : 
    7806         353 :     ParseNode* forHead = pn->pn_left;
    7807           0 :     ParseNode* forBody = pn->pn_right;
    7808             : 
    7809             :     // If the head of this for-loop declared any lexical variables, the parser
    7810             :     // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
    7811             :     // representing the implicit scope of those variables. By the time we get here,
    7812             :     // we have already entered that scope. So far, so good.
    7813             :     //
    7814             :     // ### Scope freshening
    7815             :     //
    7816             :     // Each iteration of a `for (let V...)` loop creates a fresh loop variable
    7817             :     // binding for V, even if the loop is a C-style `for(;;)` loop:
    7818             :     //
    7819             :     //     var funcs = [];
    7820             :     //     for (let i = 0; i < 2; i++)
    7821             :     //         funcs.push(function() { return i; });
    7822             :     //     assertEq(funcs[0](), 0);  // the two closures capture...
    7823             :     //     assertEq(funcs[1](), 1);  // ...two different `i` bindings
    7824             :     //
    7825             :     // This is implemented by "freshening" the implicit block -- changing the
    7826             :     // scope chain to a fresh clone of the instantaneous block object -- each
    7827             :     // iteration, just before evaluating the "update" in for(;;) loops.
    7828             :     //
    7829             :     // No freshening occurs in `for (const ...;;)` as there's no point: you
    7830             :     // can't reassign consts. This is observable through the Debugger API. (The
    7831             :     // ES6 spec also skips cloning the environment in this case.)
    7832         353 :     bool forLoopRequiresFreshening = false;
    7833         353 :     if (ParseNode* init = forHead->pn_kid1) {
    7834             :         // Emit the `init` clause, whether it's an expression or a variable
    7835             :         // declaration. (The loop variables were hoisted into an enclosing
    7836             :         // scope, but we still need to emit code for the initializers.)
    7837         330 :         if (!updateSourceCoordNotes(init->pn_pos.begin))
    7838             :             return false;
    7839           1 :         if (init->isForLoopDeclaration()) {
    7840           0 :             if (!emitTree(init))
    7841             :                 return false;
    7842             :         } else {
    7843             :             // 'init' is an expression, not a declaration. emitTree left its
    7844             :             // value on the stack.
    7845           8 :             if (!emitTree(init, ValueUsage::IgnoreValue))
    7846             :                 return false;
    7847           0 :             if (!emit1(JSOP_POP))
    7848             :                 return false;
    7849             :         }
    7850             : 
    7851             :         // ES 13.7.4.8 step 2. The initial freshening.
    7852             :         //
    7853             :         // If an initializer let-declaration may be captured during loop iteration,
    7854             :         // the current scope has an environment.  If so, freshen the current
    7855             :         // environment to expose distinct bindings for each loop iteration.
    7856         330 :         forLoopRequiresFreshening = init->isKind(ParseNodeKind::Let) && headLexicalEmitterScope;
    7857           0 :         if (forLoopRequiresFreshening) {
    7858             :             // The environment chain only includes an environment for the for(;;)
    7859             :             // loop head's let-declaration *if* a scope binding is captured, thus
    7860             :             // requiring a fresh environment each iteration. If a lexical scope
    7861             :             // exists for the head, it must be the innermost one. If that scope
    7862             :             // has closed-over bindings inducing an environment, recreate the
    7863             :             // current environment.
    7864         199 :             MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
    7865           0 :             MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7866             : 
    7867         199 :             if (headLexicalEmitterScope->hasEnvironment()) {
    7868          16 :                 if (!emit1(JSOP_FRESHENLEXICALENV))
    7869             :                     return false;
    7870             :             }
    7871             :         }
    7872             :     }
    7873             : 
    7874             :     /*
    7875             :      * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
    7876             :      * Use tmp to hold the biased srcnote "top" offset, which differs
    7877             :      * from the top local variable by the length of the JSOP_GOTO
    7878             :      * emitted in between tmp and top if this loop has a condition.
    7879             :      */
    7880             :     unsigned noteIndex;
    7881           0 :     if (!newSrcNote(SRC_FOR, &noteIndex))
    7882             :         return false;
    7883           0 :     if (!emit1(JSOP_NOP))
    7884             :         return false;
    7885         353 :     ptrdiff_t tmp = offset();
    7886             : 
    7887           0 :     JumpList jmp;
    7888         353 :     if (forHead->pn_kid2) {
    7889             :         /* Goto the loop condition, which branches back to iterate. */
    7890           0 :         if (!emitJump(JSOP_GOTO, &jmp))
    7891             :             return false;
    7892             :     }
    7893             : 
    7894             :     /* Emit code for the loop body. */
    7895         353 :     JumpTarget top{ -1 };
    7896           0 :     if (!emitLoopHead(forBody, &top))
    7897             :         return false;
    7898         353 :     if (jmp.offset == -1 && !emitLoopEntry(forBody, jmp))
    7899             :         return false;
    7900             : 
    7901         353 :     if (!emitTreeInBranch(forBody))
    7902             :         return false;
    7903             : 
    7904             :     // Set loop and enclosing "update" offsets, for continue.  Note that we
    7905             :     // continue to immediately *before* the block-freshening: continuing must
    7906             :     // refresh the block.
    7907           0 :     if (!emitJumpTarget(&loopInfo.continueTarget))
    7908             :         return false;
    7909             : 
    7910             :     // ES 13.7.4.8 step 3.e. The per-iteration freshening.
    7911           0 :     if (forLoopRequiresFreshening) {
    7912         199 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
    7913           0 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7914             : 
    7915         199 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7916          16 :             if (!emit1(JSOP_FRESHENLEXICALENV))
    7917             :                 return false;
    7918             :         }
    7919             :     }
    7920             : 
    7921             :     // Check for update code to do before the condition (if any).
    7922             :     // The update code may not be executed at all; it needs its own TDZ cache.
    7923           0 :     if (ParseNode* update = forHead->pn_kid3) {
    7924         686 :         TDZCheckCache tdzCache(this);
    7925             : 
    7926         343 :         if (!updateSourceCoordNotes(update->pn_pos.begin))
    7927           0 :             return false;
    7928           0 :         if (!emitTree(update, ValueUsage::IgnoreValue))
    7929             :             return false;
    7930         343 :         if (!emit1(JSOP_POP))
    7931             :             return false;
    7932             : 
    7933             :         /* Restore the absolute line number for source note readers. */
    7934           0 :         uint32_t lineNum = parser->errorReporter().lineAt(pn->pn_pos.end);
    7935         686 :         if (currentLine() != lineNum) {
    7936         342 :             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum)))
    7937             :                 return false;
    7938           0 :             current->currentLine = lineNum;
    7939         342 :             current->lastColumn = 0;
    7940             :         }
    7941             :     }
    7942             : 
    7943         353 :     ptrdiff_t tmp3 = offset();
    7944             : 
    7945           0 :     if (forHead->pn_kid2) {
    7946             :         /* Fix up the goto from top to target the loop condition. */
    7947         345 :         MOZ_ASSERT(jmp.offset >= 0);
    7948         345 :         if (!emitLoopEntry(forHead->pn_kid2, jmp))
    7949             :             return false;
    7950             : 
    7951         345 :         if (!emitTree(forHead->pn_kid2))
    7952             :             return false;
    7953           0 :     } else if (!forHead->pn_kid3) {
    7954             :         // If there is no condition clause and no update clause, mark
    7955             :         // the loop-ending "goto" with the location of the "for".
    7956             :         // This ensures that the debugger will stop on each loop
    7957             :         // iteration.
    7958           7 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    7959             :             return false;
    7960             :     }
    7961             : 
    7962             :     /* Set the first note offset so we can find the loop condition. */
    7963           0 :     if (!setSrcNoteOffset(noteIndex, 0, tmp3 - tmp))
    7964             :         return false;
    7965         353 :     if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTarget.offset - tmp))
    7966             :         return false;
    7967             : 
    7968             :     /* If no loop condition, just emit a loop-closing jump. */
    7969         353 :     JumpList beq;
    7970         353 :     JumpTarget breakTarget{ -1 };
    7971         353 :     if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
    7972             :         return false;
    7973             : 
    7974             :     /* The third note offset helps us find the loop-closing jump. */
    7975         353 :     if (!setSrcNoteOffset(noteIndex, 2, beq.offset - tmp))
    7976             :         return false;
    7977             : 
    7978           0 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    7979             :         return false;
    7980             : 
    7981         353 :     if (!loopInfo.patchBreaksAndContinues(this))
    7982             :         return false;
    7983             : 
    7984           0 :     return true;
    7985             : }
    7986             : 
    7987             : bool
    7988        1607 : BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
    7989             : {
    7990        1607 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::For));
    7991             : 
    7992           1 :     if (pn->pn_left->isKind(ParseNodeKind::ForHead))
    7993           1 :         return emitCStyleFor(pn, headLexicalEmitterScope);
    7994             : 
    7995        1254 :     if (!updateLineNumberNotes(pn->pn_pos.begin))
    7996             :         return false;
    7997             : 
    7998        2508 :     if (pn->pn_left->isKind(ParseNodeKind::ForIn))
    7999         140 :         return emitForIn(pn, headLexicalEmitterScope);
    8000             : 
    8001           0 :     MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::ForOf));
    8002           0 :     return emitForOf(pn, headLexicalEmitterScope);
    8003             : }
    8004             : 
    8005             : MOZ_NEVER_INLINE bool
    8006           0 : BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
    8007             : {
    8008       12436 :     FunctionBox* funbox = pn->pn_funbox;
    8009           0 :     RootedFunction fun(cx, funbox->function());
    8010           0 :     RootedAtom name(cx, fun->explicitName());
    8011           0 :     MOZ_ASSERT_IF(fun->isInterpretedLazy(), fun->lazyScript());
    8012             : 
    8013             :     // Set the |wasEmitted| flag in the funbox once the function has been
    8014             :     // emitted. Function definitions that need hoisting to the top of the
    8015             :     // function will be seen by emitFunction in two places.
    8016           0 :     if (funbox->wasEmitted) {
    8017             :         // Annex B block-scoped functions are hoisted like any other
    8018             :         // block-scoped function to the top of their scope. When their
    8019             :         // definitions are seen for the second time, we need to emit the
    8020             :         // assignment that assigns the function to the outer 'var' binding.
    8021         208 :         if (funbox->isAnnexB) {
    8022           0 :             auto emitRhs = [&name](BytecodeEmitter* bce, const NameLocation&, bool) {
    8023             :                 // The RHS is the value of the lexically bound name in the
    8024             :                 // innermost scope.
    8025           0 :                 return bce->emitGetName(name);
    8026           0 :             };
    8027             : 
    8028             :             // Get the location of the 'var' binding in the body scope. The
    8029             :             // name must be found, else there is a bug in the Annex B handling
    8030             :             // in Parser.
    8031             :             //
    8032             :             // In sloppy eval contexts, this location is dynamic.
    8033           0 :             Maybe<NameLocation> lhsLoc = locationOfNameBoundInScope(name, varEmitterScope);
    8034             : 
    8035             :             // If there are parameter expressions, the var name could be a
    8036             :             // parameter.
    8037           0 :             if (!lhsLoc && sc->isFunctionBox() && sc->asFunctionBox()->hasExtraBodyVarScope())
    8038           0 :                 lhsLoc = locationOfNameBoundInScope(name, varEmitterScope->enclosingInFrame());
    8039             : 
    8040           0 :             if (!lhsLoc) {
    8041           0 :                 lhsLoc = Some(NameLocation::DynamicAnnexBVar());
    8042             :             } else {
    8043           0 :                 MOZ_ASSERT(lhsLoc->bindingKind() == BindingKind::Var ||
    8044             :                            lhsLoc->bindingKind() == BindingKind::FormalParameter ||
    8045             :                            (lhsLoc->bindingKind() == BindingKind::Let &&
    8046             :                             sc->asFunctionBox()->hasParameterExprs));
    8047             :             }
    8048             : 
    8049           0 :             if (!emitSetOrInitializeNameAtLocation(name, *lhsLoc, emitRhs, false))
    8050           0 :                 return false;
    8051           0 :             if (!emit1(JSOP_POP))
    8052             :                 return false;
    8053             :         }
    8054             : 
    8055           0 :         MOZ_ASSERT_IF(fun->hasScript(), fun->nonLazyScript());
    8056           0 :         MOZ_ASSERT(pn->functionIsHoisted());
    8057             :         return true;
    8058             :     }
    8059             : 
    8060           0 :     funbox->wasEmitted = true;
    8061             : 
    8062             :     // Mark as singletons any function which will only be executed once, or
    8063             :     // which is inner to a lambda we only expect to run once. In the latter
    8064             :     // case, if the lambda runs multiple times then CloneFunctionObject will
    8065             :     // make a deep clone of its contents.
    8066       24456 :     if (fun->isInterpreted()) {
    8067       12228 :         bool singleton = checkRunOnceContext();
    8068           0 :         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
    8069             :             return false;
    8070             : 
    8071           0 :         SharedContext* outersc = sc;
    8072       24456 :         if (fun->isInterpretedLazy()) {
    8073             :             // We need to update the static scope chain regardless of whether
    8074             :             // the LazyScript has already been initialized, due to the case
    8075             :             // where we previously successfully compiled an inner function's
    8076             :             // lazy script but failed to compile the outer script after the
    8077             :             // fact. If we attempt to compile the outer script again, the
    8078             :             // static scope chain will be newly allocated and will mismatch
    8079             :             // the previously compiled LazyScript's.
    8080           0 :             fun->lazyScript()->setEnclosingScope(innermostScope());
    8081           0 :             if (emittingRunOnceLambda)
    8082           0 :                 fun->lazyScript()->setTreatAsRunOnce();
    8083             :         } else {
    8084       12228 :             MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
    8085             : 
    8086             :             // Inherit most things (principals, version, etc) from the
    8087             :             // parent.  Use default values for the rest.
    8088       24455 :             Rooted<JSScript*> parent(cx, script);
    8089       24456 :             MOZ_ASSERT(parent->mutedErrors() == parser->options().mutedErrors());
    8090       12228 :             const TransitiveCompileOptions& transitiveOptions = parser->options();
    8091           0 :             CompileOptions options(cx, transitiveOptions);
    8092             : 
    8093           0 :             Rooted<JSObject*> sourceObject(cx, script->sourceObject());
    8094       36684 :             Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
    8095             :                                                           funbox->bufStart, funbox->bufEnd,
    8096             :                                                           funbox->toStringStart,
    8097           0 :                                                           funbox->toStringEnd));
    8098           0 :             if (!script)
    8099           0 :                 return false;
    8100             : 
    8101             :             BytecodeEmitter bce2(this, parser, funbox, script, /* lazyScript = */ nullptr,
    8102       48912 :                                  pn->pn_pos, emitterMode);
    8103       12227 :             if (!bce2.init())
    8104           0 :                 return false;
    8105             : 
    8106             :             /* We measured the max scope depth when we parsed the function. */
    8107       12227 :             if (!bce2.emitFunctionScript(pn->pn_body))
    8108             :                 return false;
    8109             : 
    8110       12228 :             if (funbox->isLikelyConstructorWrapper())
    8111           2 :                 script->setLikelyConstructorWrapper();
    8112             :         }
    8113             : 
    8114       12227 :         if (outersc->isFunctionBox())
    8115        3365 :             outersc->asFunctionBox()->setHasInnerFunctions();
    8116             :     } else {
    8117           0 :         MOZ_ASSERT(IsAsmJSModule(fun));
    8118             :     }
    8119             : 
    8120             :     // Make the function object a literal in the outer script's pool.
    8121           0 :     unsigned index = objectList.add(pn->pn_funbox);
    8122             : 
    8123             :     // Non-hoisted functions simply emit their respective op.
    8124           0 :     if (!pn->functionIsHoisted()) {
    8125             :         // JSOP_LAMBDA_ARROW is always preceded by a new.target
    8126       31785 :         MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW));
    8127           0 :         if (funbox->isAsync()) {
    8128         632 :             MOZ_ASSERT(!needsProto);
    8129           0 :             return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(),
    8130        1896 :                                     fun->isGenerator());
    8131             :         }
    8132             : 
    8133       19926 :         if (fun->isArrow()) {
    8134        4586 :             if (sc->allowNewTarget()) {
    8135        2058 :                 if (!emit1(JSOP_NEWTARGET))
    8136             :                     return false;
    8137             :             } else {
    8138           0 :                 if (!emit1(JSOP_NULL))
    8139             :                     return false;
    8140             :             }
    8141             :         }
    8142             : 
    8143           0 :         if (needsProto) {
    8144         158 :             MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA);
    8145          79 :             pn->setOp(JSOP_FUNWITHPROTO);
    8146             :         }
    8147             : 
    8148       19928 :         if (pn->getOp() == JSOP_DEFFUN) {
    8149           0 :             if (!emitIndex32(JSOP_LAMBDA, index))
    8150             :                 return false;
    8151           0 :             return emit1(JSOP_DEFFUN);
    8152             :         }
    8153             : 
    8154             :         // This is a FunctionExpression, ArrowFunctionExpression, or class
    8155             :         // constructor. Emit the single instruction (without location info).
    8156        9964 :         return emitIndex32(pn->getOp(), index);
    8157             :     }
    8158             : 
    8159        1632 :     MOZ_ASSERT(!needsProto);
    8160             : 
    8161             :     bool topLevelFunction;
    8162        1674 :     if (sc->isFunctionBox() || (sc->isEvalContext() && sc->strict())) {
    8163             :         // No nested functions inside other functions are top-level.
    8164             :         topLevelFunction = false;
    8165             :     } else {
    8166             :         // In sloppy eval scripts, top-level functions in are accessed
    8167             :         // dynamically. In global and module scripts, top-level functions are
    8168             :         // those bound in the var scope.
    8169        2848 :         NameLocation loc = lookupName(name);
    8170        2848 :         topLevelFunction = loc.kind() == NameLocation::Kind::Dynamic ||
    8171        1424 :                            loc.bindingKind() == BindingKind::Var;
    8172             :     }
    8173             : 
    8174        1632 :     if (topLevelFunction) {
    8175        1424 :         if (sc->isModuleContext()) {
    8176             :             // For modules, we record the function and instantiate the binding
    8177             :             // during ModuleInstantiate(), before the script is run.
    8178             : 
    8179           0 :             RootedModuleObject module(cx, sc->asModuleContext()->module());
    8180           0 :             if (!module->noteFunctionDeclaration(cx, name, fun))
    8181           0 :                 return false;
    8182             :         } else {
    8183        1424 :             MOZ_ASSERT(sc->isGlobalContext() || sc->isEvalContext());
    8184           0 :             MOZ_ASSERT(pn->getOp() == JSOP_NOP);
    8185        1424 :             switchToPrologue();
    8186           0 :             if (funbox->isAsync()) {
    8187           0 :                 if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(),
    8188         108 :                                       fun->isGenerator()))
    8189             :                 {
    8190             :                     return false;
    8191             :                 }
    8192             :             } else {
    8193        1370 :                 if (!emitIndex32(JSOP_LAMBDA, index))
    8194             :                     return false;
    8195             :             }
    8196        1424 :             if (!emit1(JSOP_DEFFUN))
    8197             :                 return false;
    8198             :             switchToMain();
    8199             :         }
    8200             :     } else {
    8201             :         // For functions nested within functions and blocks, make a lambda and
    8202             :         // initialize the binding name of the function in the current scope.
    8203             : 
    8204         208 :         bool isAsync = funbox->isAsync();
    8205           0 :         bool isGenerator = funbox->isGenerator();
    8206             :         auto emitLambda = [index, isAsync, isGenerator](BytecodeEmitter* bce,
    8207           0 :                                                         const NameLocation&, bool) {
    8208         208 :             if (isAsync) {
    8209           5 :                 return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false,
    8210           5 :                                              /* isArrow = */ false, isGenerator);
    8211             :             }
    8212         203 :             return bce->emitIndexOp(JSOP_LAMBDA, index);
    8213         208 :         };
    8214             : 
    8215         416 :         if (!emitInitializeName(name, emitLambda))
    8216             :             return false;
    8217         208 :         if (!emit1(JSOP_POP))
    8218             :             return false;
    8219             :     }
    8220             : 
    8221             :     return true;
    8222             : }
    8223             : 
    8224             : bool
    8225           0 : BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) {
    8226         691 :     if (isArrow) {
    8227         230 :         if (sc->allowNewTarget()) {
    8228         114 :             if (!emit1(JSOP_NEWTARGET))
    8229             :                 return false;
    8230             :         } else {
    8231           1 :             if (!emit1(JSOP_NULL))
    8232             :                 return false;
    8233             :         }
    8234         115 :         if (!emitIndex32(JSOP_LAMBDA_ARROW, index))
    8235             :             return false;
    8236             :     } else {
    8237           0 :         if (!emitIndex32(JSOP_LAMBDA, index))
    8238             :             return false;
    8239             :     }
    8240             : 
    8241             :     return true;
    8242             : }
    8243             : 
    8244             : bool
    8245         691 : BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
    8246             :                                   bool isGenerator)
    8247             : {
    8248             :     // needsHomeObject can be true for propertyList for extended class.
    8249             :     // In that case push both unwrapped and wrapped function, in order to
    8250             :     // initialize home object of unwrapped function, and set wrapped function
    8251             :     // as a property.
    8252             :     //
    8253             :     //   lambda       // unwrapped
    8254             :     //   dup          // unwrapped unwrapped
    8255             :     //   toasync      // unwrapped wrapped
    8256             :     //
    8257             :     // Emitted code is surrounded by the following code.
    8258             :     //
    8259             :     //                    // classObj classCtor classProto
    8260             :     //   (emitted code)   // classObj classCtor classProto unwrapped wrapped
    8261             :     //   swap             // classObj classCtor classProto wrapped unwrapped
    8262             :     //   inithomeobject 1 // classObj classCtor classProto wrapped unwrapped
    8263             :     //                    //   initialize the home object of unwrapped
    8264             :     //                    //   with classProto here
    8265             :     //   pop              // classObj classCtor classProto wrapped
    8266             :     //   inithiddenprop   // classObj classCtor classProto wrapped
    8267             :     //                    //   initialize the property of the classProto
    8268             :     //                    //   with wrapped function here
    8269             :     //   pop              // classObj classCtor classProto
    8270             :     //
    8271             :     // needsHomeObject is false for other cases, push wrapped function only.
    8272         691 :     if (!emitAsyncWrapperLambda(index, isArrow))
    8273             :         return false;
    8274         691 :     if (needsHomeObject) {
    8275           5 :         if (!emit1(JSOP_DUP))
    8276             :             return false;
    8277             :     }
    8278         691 :     if (isGenerator) {
    8279           2 :         if (!emit1(JSOP_TOASYNCGEN))
    8280             :             return false;
    8281             :     } else {
    8282         689 :         if (!emit1(JSOP_TOASYNC))
    8283             :             return false;
    8284             :     }
    8285             :     return true;
    8286             : }
    8287             : 
    8288             : bool
    8289         290 : BytecodeEmitter::emitDo(ParseNode* pn)
    8290             : {
    8291             :     /* Emit an annotated nop so IonBuilder can recognize the 'do' loop. */
    8292             :     unsigned noteIndex;
    8293         290 :     if (!newSrcNote(SRC_WHILE, &noteIndex))
    8294             :         return false;
    8295           0 :     if (!emit1(JSOP_NOP))
    8296             :         return false;
    8297             : 
    8298             :     unsigned noteIndex2;
    8299           0 :     if (!newSrcNote(SRC_WHILE, &noteIndex2))
    8300             :         return false;
    8301             : 
    8302             :     /* Compile the loop body. */
    8303             :     JumpTarget top;
    8304         290 :     if (!emitLoopHead(pn->pn_left, &top))
    8305             :         return false;
    8306             : 
    8307         580 :     LoopControl loopInfo(this, StatementKind::DoLoop);
    8308             : 
    8309           0 :     JumpList empty;
    8310         290 :     if (!emitLoopEntry(nullptr, empty))
    8311             :         return false;
    8312             : 
    8313         290 :     if (!emitTree(pn->pn_left))
    8314             :         return false;
    8315             : 
    8316             :     // Set the offset for continues.
    8317           0 :     if (!emitJumpTarget(&loopInfo.continueTarget))
    8318             :         return false;
    8319             : 
    8320             :     /* Compile the loop condition, now that continues know where to go. */
    8321           0 :     if (!emitTree(pn->pn_right))
    8322             :         return false;
    8323             : 
    8324         290 :     JumpList beq;
    8325           0 :     JumpTarget breakTarget{ -1 };
    8326         290 :     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
    8327             :         return false;
    8328             : 
    8329         290 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    8330             :         return false;
    8331             : 
    8332             :     /*
    8333             :      * Update the annotations with the update and back edge positions, for
    8334             :      * IonBuilder.
    8335             :      *
    8336             :      * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
    8337             :      * note gets bigger.
    8338             :      */
    8339         290 :     if (!setSrcNoteOffset(noteIndex2, 0, beq.offset - top.offset))
    8340             :         return false;
    8341         290 :     if (!setSrcNoteOffset(noteIndex, 0, 1 + (loopInfo.continueTarget.offset - top.offset)))
    8342             :         return false;
    8343             : 
    8344           0 :     if (!loopInfo.patchBreaksAndContinues(this))
    8345             :         return false;
    8346             : 
    8347           0 :     return true;
    8348             : }
    8349             : 
    8350             : bool
    8351           0 : BytecodeEmitter::emitWhile(ParseNode* pn)
    8352             : {
    8353             :     /*
    8354             :      * Minimize bytecodes issued for one or more iterations by jumping to
    8355             :      * the condition below the body and closing the loop if the condition
    8356             :      * is true with a backward branch. For iteration count i:
    8357             :      *
    8358             :      *  i    test at the top                 test at the bottom
    8359             :      *  =    ===============                 ==================
    8360             :      *  0    ifeq-pass                       goto; ifne-fail
    8361             :      *  1    ifeq-fail; goto; ifne-pass      goto; ifne-pass; ifne-fail
    8362             :      *  2    2*(ifeq-fail; goto); ifeq-pass  goto; 2*ifne-pass; ifne-fail
    8363             :      *  . . .
    8364             :      *  N    N*(ifeq-fail; goto); ifeq-pass  goto; N*ifne-pass; ifne-fail
    8365             :      */
    8366             : 
    8367             :     // If we have a single-line while, like "while (x) ;", we want to
    8368             :     // emit the line note before the initial goto, so that the
    8369             :     // debugger sees a single entry point.  This way, if there is a
    8370             :     // breakpoint on the line, it will only fire once; and "next"ing
    8371             :     // will skip the whole loop.  However, for the multi-line case we
    8372             :     // want to emit the line note after the initial goto, so that
    8373             :     // "cont" stops on each iteration -- but without a stop before the
    8374             :     // first iteration.
    8375           0 :     if (parser->errorReporter().lineAt(pn->pn_pos.begin) ==
    8376         267 :         parser->errorReporter().lineAt(pn->pn_pos.end))
    8377             :     {
    8378           1 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    8379             :             return false;
    8380             :     }
    8381             : 
    8382           0 :     JumpTarget top{ -1 };
    8383           0 :     if (!emitJumpTarget(&top))
    8384             :         return false;
    8385             : 
    8386         534 :     LoopControl loopInfo(this, StatementKind::WhileLoop);
    8387           0 :     loopInfo.continueTarget = top;
    8388             : 
    8389             :     unsigned noteIndex;
    8390           0 :     if (!newSrcNote(SRC_WHILE, &noteIndex))
    8391             :         return false;
    8392             : 
    8393         267 :     JumpList jmp;
    8394           0 :     if (!emitJump(JSOP_GOTO, &jmp))
    8395             :         return false;
    8396             : 
    8397           0 :     if (!emitLoopHead(pn->pn_right, &top))
    8398             :         return false;
    8399             : 
    8400         267 :     if (!emitTreeInBranch(pn->pn_right))
    8401             :         return false;
    8402             : 
    8403           0 :     if (!emitLoopEntry(pn->pn_left, jmp))
    8404             :         return false;
    8405           0 :     if (!emitTree(pn->pn_left))
    8406             :         return false;
    8407             : 
    8408           0 :     JumpList beq;
    8409           0 :     JumpTarget breakTarget{ -1 };
    8410         267 :     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
    8411             :         return false;
    8412             : 
    8413         267 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    8414             :         return false;
    8415             : 
    8416           0 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
    8417             :         return false;
    8418             : 
    8419           0 :     if (!loopInfo.patchBreaksAndContinues(this))
    8420             :         return false;
    8421             : 
    8422         267 :     return true;
    8423             : }
    8424             : 
    8425             : bool
    8426        1260 : BytecodeEmitter::emitBreak(PropertyName* label)
    8427             : {
    8428             :     BreakableControl* target;
    8429             :     SrcNoteType noteType;
    8430        1260 :     if (label) {
    8431             :         // Any statement with the matching label may be the break target.
    8432           0 :         auto hasSameLabel = [label](LabelControl* labelControl) {
    8433           0 :             return labelControl->label() == label;
    8434           0 :         };
    8435           0 :         target = findInnermostNestableControl<LabelControl>(hasSameLabel);
    8436           0 :         noteType = SRC_BREAK2LABEL;
    8437             :     } else {
    8438             :         auto isNotLabel = [](BreakableControl* control) {
    8439           0 :             return !control->is<LabelControl>();
    8440             :         };
    8441        2520 :         target = findInnermostNestableControl<BreakableControl>(isNotLabel);
    8442        1260 :         noteType = (target->kind() == StatementKind::Switch) ? SRC_SWITCHBREAK : SRC_BREAK;
    8443             :     }
    8444             : 
    8445           0 :     return emitGoto(target, &target->breaks, noteType);
    8446             : }
    8447             : 
    8448             : bool
    8449         265 : BytecodeEmitter::emitContinue(PropertyName* label)
    8450             : {
    8451           0 :     LoopControl* target = nullptr;
    8452         265 :     if (label) {
    8453             :         // Find the loop statement enclosed by the matching label.
    8454           0 :         NestableControl* control = innermostNestableControl;
    8455           0 :         while (!control->is<LabelControl>() || control->as<LabelControl>().label() != label) {
    8456           0 :             if (control->is<LoopControl>())
    8457           0 :                 target = &control->as<LoopControl>();
    8458           0 :             control = control->enclosing();
    8459             :         }
    8460             :     } else {
    8461         530 :         target = findInnermostNestableControl<LoopControl>();
    8462             :     }
    8463           0 :     return emitGoto(target, &target->continues, SRC_CONTINUE);
    8464             : }
    8465             : 
    8466             : bool
    8467       22826 : BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
    8468             : {
    8469       22826 :     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
    8470       22826 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Name));
    8471       68482 :     MOZ_ASSERT(pn->name() == cx->names().dotThis);
    8472             : 
    8473       22828 :     if (!emitTree(pn))
    8474             :         return false;
    8475       45656 :     if (sc->needsThisTDZChecks() && !emit1(JSOP_CHECKTHIS))
    8476             :         return false;
    8477             : 
    8478           0 :     return true;
    8479             : }
    8480             : 
    8481             : bool
    8482           0 : BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn)
    8483             : {
    8484           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::SuperBase));
    8485          60 :     return emitGetFunctionThis(pn->pn_kid);
    8486             : }
    8487             : 
    8488             : bool
    8489           0 : BytecodeEmitter::emitThisLiteral(ParseNode* pn)
    8490             : {
    8491       23660 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::This));
    8492             : 
    8493       23660 :     if (ParseNode* thisName = pn->pn_kid)
    8494           0 :         return emitGetFunctionThis(thisName);
    8495             : 
    8496           0 :     if (sc->thisBinding() == ThisBinding::Module)
    8497           0 :         return emit1(JSOP_UNDEFINED);
    8498             : 
    8499           0 :     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
    8500         894 :     return emit1(JSOP_GLOBALTHIS);
    8501             : }
    8502             : 
    8503             : bool
    8504           0 : BytecodeEmitter::emitCheckDerivedClassConstructorReturn()
    8505             : {
    8506           0 :     MOZ_ASSERT(lookupName(cx->names().dotThis).hasKnownSlot());
    8507         237 :     if (!emitGetName(cx->names().dotThis))
    8508             :         return false;
    8509           0 :     if (!emit1(JSOP_CHECKRETURN))
    8510             :         return false;
    8511          79 :     return true;
    8512             : }
    8513             : 
    8514             : bool
    8515       11321 : BytecodeEmitter::emitReturn(ParseNode* pn)
    8516             : {
    8517       11321 :     if (!updateSourceCoordNotes(pn->pn_pos.begin))
    8518             :         return false;
    8519             : 
    8520       22642 :     bool needsIteratorResult = sc->isFunctionBox() && sc->asFunctionBox()->needsIteratorResult();
    8521       11321 :     if (needsIteratorResult) {
    8522           0 :         if (!emitPrepareIteratorResult())
    8523             :             return false;
    8524             :     }
    8525             : 
    8526             :     /* Push a return value */
    8527       11321 :     if (ParseNode* pn2 = pn->pn_kid) {
    8528        9792 :         if (!emitTree(pn2))
    8529             :             return false;
    8530             : 
    8531           0 :         bool isAsyncGenerator = sc->asFunctionBox()->isAsync() &&
    8532       10718 :                                 sc->asFunctionBox()->isGenerator();
    8533        9792 :         if (isAsyncGenerator) {
    8534           0 :             if (!emitAwaitInInnermostScope())
    8535             :                 return false;
    8536             :         }
    8537             :     } else {
    8538             :         /* No explicit return value provided */
    8539        1529 :         if (!emit1(JSOP_UNDEFINED))
    8540             :             return false;
    8541             :     }
    8542             : 
    8543       11321 :     if (needsIteratorResult) {
    8544           0 :         if (!emitFinishIteratorResult(true))
    8545             :             return false;
    8546             :     }
    8547             : 
    8548             :     // We know functionBodyEndPos is set because "return" is only
    8549             :     // valid in a function, and so we've passed through
    8550             :     // emitFunctionScript.
    8551           0 :     MOZ_ASSERT(functionBodyEndPosSet);
    8552       11321 :     if (!updateSourceCoordNotes(functionBodyEndPos))
    8553             :         return false;
    8554             : 
    8555             :     /*
    8556             :      * EmitNonLocalJumpFixup may add fixup bytecode to close open try
    8557             :      * blocks having finally clauses and to exit intermingled let blocks.
    8558             :      * We can't simply transfer control flow to our caller in that case,
    8559             :      * because we must gosub to those finally clauses from inner to outer,
    8560             :      * with the correct stack pointer (i.e., after popping any with,
    8561             :      * for/in, etc., slots nested inside the finally's try).
    8562             :      *
    8563             :      * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
    8564             :      * extra JSOP_RETRVAL after the fixups.
    8565             :      */
    8566       11321 :     ptrdiff_t top = offset();
    8567             : 
    8568       22642 :     bool needsFinalYield = sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
    8569             :     bool isDerivedClassConstructor =
    8570           0 :         sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
    8571             : 
    8572       11321 :     if (!emit1((needsFinalYield || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
    8573             :         return false;
    8574             : 
    8575             :     // Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
    8576             :     // to ensure that the error is thrown while the scope-chain is still intact.
    8577           0 :     if (isDerivedClassConstructor) {
    8578           0 :         if (!emitCheckDerivedClassConstructorReturn())
    8579             :             return false;
    8580             :     }
    8581             : 
    8582       22642 :     NonLocalExitControl nle(this, NonLocalExitControl::Return);
    8583             : 
    8584           0 :     if (!nle.prepareForNonLocalJumpToOutermost())
    8585             :         return false;
    8586             : 
    8587           0 :     if (needsFinalYield) {
    8588             :         // We know that .generator is on the function scope, as we just exited
    8589             :         // all nested scopes.
    8590             :         NameLocation loc =
    8591           0 :             *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, varEmitterScope);
    8592        1896 :         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
    8593           0 :             return false;
    8594         632 :         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
    8595             :             return false;
    8596       10689 :     } else if (isDerivedClassConstructor) {
    8597           0 :         MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
    8598           0 :         if (!emit1(JSOP_RETRVAL))
    8599             :             return false;
    8600       10689 :     } else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
    8601           0 :         code()[top] = JSOP_SETRVAL;
    8602        3923 :         if (!emit1(JSOP_RETRVAL))
    8603             :             return false;
    8604             :     }
    8605             : 
    8606             :     return true;
    8607             : }
    8608             : 
    8609             : bool
    8610           0 : BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope)
    8611             : {
    8612           0 :     NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, &currentScope);
    8613        6045 :     return emitGetNameAtLocation(cx->names().dotGenerator, loc);
    8614             : }
    8615             : 
    8616             : bool
    8617         729 : BytecodeEmitter::emitInitialYield(ParseNode* pn)
    8618             : {
    8619         729 :     if (!emitTree(pn->pn_kid))
    8620             :         return false;
    8621             : 
    8622         729 :     if (!emitYieldOp(JSOP_INITIALYIELD))
    8623             :         return false;
    8624             : 
    8625         729 :     if (!emit1(JSOP_POP))
    8626             :         return false;
    8627             : 
    8628           0 :     return true;
    8629             : }
    8630             : 
    8631             : bool
    8632           0 : BytecodeEmitter::emitYield(ParseNode* pn)
    8633             : {
    8634          44 :     MOZ_ASSERT(sc->isFunctionBox());
    8635           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Yield));
    8636             : 
    8637          88 :     bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
    8638          44 :     if (needsIteratorResult) {
    8639           0 :         if (!emitPrepareIteratorResult())
    8640             :             return false;
    8641             :     }
    8642           0 :     if (pn->pn_kid) {
    8643           0 :         if (!emitTree(pn->pn_kid))
    8644             :             return false;
    8645             :     } else {
    8646           0 :         if (!emit1(JSOP_UNDEFINED))
    8647             :             return false;
    8648             :     }
    8649             : 
    8650             :     // 11.4.3.7 AsyncGeneratorYield step 5.
    8651          88 :     bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
    8652           0 :     if (isAsyncGenerator) {
    8653           1 :         if (!emitAwaitInInnermostScope())                 // RESULT
    8654             :             return false;
    8655             :     }
    8656             : 
    8657          44 :     if (needsIteratorResult) {
    8658           0 :         if (!emitFinishIteratorResult(false))
    8659             :             return false;
    8660             :     }
    8661             : 
    8662          44 :     if (!emitGetDotGeneratorInInnermostScope())
    8663             :         return false;
    8664             : 
    8665           0 :     if (!emitYieldOp(JSOP_YIELD))
    8666             :         return false;
    8667             : 
    8668          44 :     return true;
    8669             : }
    8670             : 
    8671             : bool
    8672        1222 : BytecodeEmitter::emitAwaitInInnermostScope(ParseNode* pn)
    8673             : {
    8674           0 :     MOZ_ASSERT(sc->isFunctionBox());
    8675           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Await));
    8676             : 
    8677           0 :     if (!emitTree(pn->pn_kid))
    8678             :         return false;
    8679        1222 :     return emitAwaitInInnermostScope();
    8680             : }
    8681             : 
    8682             : bool
    8683        1233 : BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope)
    8684             : {
    8685           0 :     if (!emitGetDotGeneratorInScope(currentScope))
    8686             :         return false;
    8687           0 :     if (!emitYieldOp(JSOP_AWAIT))
    8688             :         return false;
    8689           0 :     return true;
    8690             : }
    8691             : 
    8692             : bool
    8693           9 : BytecodeEmitter::emitYieldStar(ParseNode* iter)
    8694             : {
    8695           9 :     MOZ_ASSERT(sc->isFunctionBox());
    8696           0 :     MOZ_ASSERT(sc->asFunctionBox()->isGenerator());
    8697             : 
    8698           0 :     bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
    8699             : 
    8700           0 :     if (!emitTree(iter))                                  // ITERABLE
    8701             :         return false;
    8702           0 :     if (isAsyncGenerator) {
    8703           0 :         if (!emitAsyncIterator())                         // NEXT ITER
    8704             :             return false;
    8705             :     } else {
    8706           7 :         if (!emitIterator())                              // NEXT ITER
    8707             :             return false;
    8708             :     }
    8709             : 
    8710             :     // Initial send value is undefined.
    8711           0 :     if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER RECEIVED
    8712             :         return false;
    8713             : 
    8714             :     int32_t savedDepthTemp;
    8715           9 :     int32_t startDepth = stackDepth;
    8716           9 :     MOZ_ASSERT(startDepth >= 3);
    8717             : 
    8718             :     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
    8719           0 :                         TryEmitter::ControlKind::NonSyntactic);
    8720           9 :     if (!tryCatch.emitJumpOverCatchAndFinally())          // NEXT ITER RESULT
    8721             :         return false;
    8722             : 
    8723           9 :     JumpTarget tryStart{ offset() };
    8724           9 :     if (!tryCatch.emitTry())                              // NEXT ITER RESULT
    8725             :         return false;
    8726             : 
    8727           9 :     MOZ_ASSERT(this->stackDepth == startDepth);
    8728             : 
    8729             :     // 11.4.3.7 AsyncGeneratorYield step 5.
    8730           0 :     if (isAsyncGenerator) {
    8731           0 :         if (!emitAwaitInInnermostScope())                 // NEXT ITER RESULT
    8732             :             return false;
    8733             :     }
    8734             : 
    8735             :     // Load the generator object.
    8736           9 :     if (!emitGetDotGeneratorInInnermostScope())           // NEXT ITER RESULT GENOBJ
    8737             :         return false;
    8738             : 
    8739             :     // Yield RESULT as-is, without re-boxing.
    8740           9 :     if (!emitYieldOp(JSOP_YIELD))                         // NEXT ITER RECEIVED
    8741             :         return false;
    8742             : 
    8743           0 :     if (!tryCatch.emitCatch())                            // NEXT ITER RESULT
    8744             :         return false;
    8745             : 
    8746           9 :     stackDepth = startDepth;                              // NEXT ITER RESULT
    8747           9 :     if (!emit1(JSOP_EXCEPTION))                           // NEXT ITER RESULT EXCEPTION
    8748             :         return false;
    8749           0 :     if (!emitDupAt(2))                                    // NEXT ITER RESULT EXCEPTION ITER
    8750             :         return false;
    8751           9 :     if (!emit1(JSOP_DUP))                                 // NEXT ITER RESULT EXCEPTION ITER ITER
    8752             :         return false;
    8753          27 :     if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP))   // NEXT ITER RESULT EXCEPTION ITER THROW
    8754             :         return false;
    8755           9 :     if (!emit1(JSOP_DUP))                                 // NEXT ITER RESULT EXCEPTION ITER THROW THROW
    8756             :         return false;
    8757           0 :     if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER RESULT EXCEPTION ITER THROW THROW UNDEFINED
    8758             :         return false;
    8759           0 :     if (!emit1(JSOP_EQ))                                  // NEXT ITER RESULT EXCEPTION ITER THROW ?EQL
    8760             :         return false;
    8761             : 
    8762           9 :     InternalIfEmitter ifThrowMethodIsNotDefined(this);
    8763           0 :     if (!ifThrowMethodIsNotDefined.emitThen())            // NEXT ITER RESULT EXCEPTION ITER THROW
    8764             :         return false;
    8765           0 :     savedDepthTemp = stackDepth;
    8766           9 :     if (!emit1(JSOP_POP))                                 // NEXT ITER RESULT EXCEPTION ITER
    8767             :         return false;
    8768             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.2
    8769             :     //
    8770             :     // If the iterator does not have a "throw" method, it calls IteratorClose
    8771             :     // and then throws a TypeError.
    8772           9 :     IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync;
    8773           9 :     if (!emitIteratorCloseInInnermostScope(iterKind))     // NEXT ITER RESULT EXCEPTION
    8774             :         return false;
    8775           0 :     if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw
    8776             :         return false;
    8777           9 :     stackDepth = savedDepthTemp;
    8778           9 :     if (!ifThrowMethodIsNotDefined.emitEnd())             // NEXT ITER OLDRESULT EXCEPTION ITER THROW
    8779             :         return false;
    8780             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.4.
    8781             :     // RESULT = ITER.throw(EXCEPTION)                     // NEXT ITER OLDRESULT EXCEPTION ITER THROW
    8782           0 :     if (!emit1(JSOP_SWAP))                                // NEXT ITER OLDRESULT EXCEPTION THROW ITER
    8783             :         return false;
    8784           9 :     if (!emit2(JSOP_PICK, 2))                             // NEXT ITER OLDRESULT THROW ITER EXCEPTION
    8785             :         return false;
    8786           9 :     if (!emitCall(JSOP_CALL, 1, iter))                    // NEXT ITER OLDRESULT RESULT
    8787             :         return false;
    8788           9 :     checkTypeSet(JSOP_CALL);
    8789             : 
    8790           9 :     if (isAsyncGenerator) {
    8791           2 :         if (!emitAwaitInInnermostScope())                 // NEXT ITER OLDRESULT RESULT
    8792             :             return false;
    8793             :     }
    8794             : 
    8795           9 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) // NEXT ITER OLDRESULT RESULT
    8796             :         return false;
    8797           9 :     if (!emit1(JSOP_SWAP))                                // NEXT ITER RESULT OLDRESULT
    8798             :         return false;
    8799           9 :     if (!emit1(JSOP_POP))                                 // NEXT ITER RESULT
    8800             :         return false;
    8801           0 :     MOZ_ASSERT(this->stackDepth == startDepth);
    8802           9 :     JumpList checkResult;
    8803             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.ii.
    8804             :     //
    8805             :     // Note that there is no GOSUB to the finally block here. If the iterator has a
    8806             :     // "throw" method, it does not perform IteratorClose.
    8807           9 :     if (!emitJump(JSOP_GOTO, &checkResult))               // goto checkResult
    8808             :         return false;
    8809             : 
    8810           0 :     if (!tryCatch.emitFinally())
    8811             :          return false;
    8812             : 
    8813             :     // ES 14.4.13, yield * AssignmentExpression, step 5.c
    8814             :     //
    8815             :     // Call iterator.return() for receiving a "forced return" completion from
    8816             :     // the generator.
    8817             : 
    8818           0 :     InternalIfEmitter ifGeneratorClosing(this);
    8819           9 :     if (!emit1(JSOP_ISGENCLOSING))                        // NEXT ITER RESULT FTYPE FVALUE CLOSING
    8820             :         return false;
    8821           9 :     if (!ifGeneratorClosing.emitThen())                   // NEXT ITER RESULT FTYPE FVALUE
    8822             :         return false;
    8823             : 
    8824             :     // Step ii.
    8825             :     //
    8826             :     // Get the "return" method.
    8827           9 :     if (!emitDupAt(3))                                    // NEXT ITER RESULT FTYPE FVALUE ITER
    8828             :         return false;
    8829           9 :     if (!emit1(JSOP_DUP))                                 // NEXT ITER RESULT FTYPE FVALUE ITER ITER
    8830             :         return false;
    8831          27 :     if (!emitAtomOp(cx->names().return_, JSOP_CALLPROP))  // NEXT ITER RESULT FTYPE FVALUE ITER RET
    8832             :         return false;
    8833             : 
    8834             :     // Step iii.
    8835             :     //
    8836             :     // Do nothing if "return" is undefined or null.
    8837           0 :     InternalIfEmitter ifReturnMethodIsDefined(this);
    8838           9 :     if (!emitPushNotUndefinedOrNull())                    // NEXT ITER RESULT FTYPE FVALUE ITER RET NOT-UNDEF-OR-NULL
    8839             :         return false;
    8840             : 
    8841             :     // Step iv.
    8842             :     //
    8843             :     // Call "return" with the argument passed to Generator.prototype.return,
    8844             :     // which is currently in rval.value.
    8845           9 :     if (!ifReturnMethodIsDefined.emitThenElse())          // NEXT ITER OLDRESULT FTYPE FVALUE ITER RET
    8846             :         return false;
    8847           9 :     if (!emit1(JSOP_SWAP))                                // NEXT ITER OLDRESULT FTYPE FVALUE RET ITER
    8848             :         return false;
    8849           9 :     if (!emit1(JSOP_GETRVAL))                             // NEXT ITER OLDRESULT FTYPE FVALUE RET ITER RVAL
    8850             :         return false;
    8851          27 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // NEXT ITER OLDRESULT FTYPE FVALUE RET ITER VALUE
    8852             :         return false;
    8853           9 :     if (!emitCall(JSOP_CALL, 1))                          // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
    8854             :         return false;
    8855           9 :     checkTypeSet(JSOP_CALL);
    8856             : 
    8857           9 :     if (iterKind == IteratorKind::Async) {
    8858           0 :         if (!emitAwaitInInnermostScope())                 // ... FTYPE FVALUE RESULT
    8859             :             return false;
    8860             :     }
    8861             : 
    8862             :     // Step v.
    8863           0 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
    8864             :         return false;
    8865             : 
    8866             :     // Steps vi-viii.
    8867             :     //
    8868             :     // Check if the returned object from iterator.return() is done. If not,
    8869             :     // continuing yielding.
    8870           9 :     InternalIfEmitter ifReturnDone(this);
    8871           0 :     if (!emit1(JSOP_DUP))                                 // NEXT ITER OLDRESULT FTYPE FVALUE RESULT RESULT
    8872             :         return false;
    8873           0 :     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // NEXT ITER OLDRESULT FTYPE FVALUE RESULT DONE
    8874             :         return false;
    8875           9 :     if (!ifReturnDone.emitThenElse())                     // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
    8876             :         return false;
    8877          27 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // NEXT ITER OLDRESULT FTYPE FVALUE VALUE
    8878             :         return false;
    8879             : 
    8880           9 :     if (!emitPrepareIteratorResult())                     // NEXT ITER OLDRESULT FTYPE FVALUE VALUE RESULT
    8881             :         return false;
    8882           0 :     if (!emit1(JSOP_SWAP))                                // NEXT ITER OLDRESULT FTYPE FVALUE RESULT VALUE
    8883             :         return false;
    8884           0 :     if (!emitFinishIteratorResult(true))                  // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
    8885             :         return false;
    8886           0 :     if (!emit1(JSOP_SETRVAL))                             // NEXT ITER OLDRESULT FTYPE FVALUE
    8887             :         return false;
    8888           9 :     savedDepthTemp = this->stackDepth;
    8889           9 :     if (!ifReturnDone.emitElse())                         // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
    8890             :         return false;
    8891           9 :     if (!emit2(JSOP_UNPICK, 3))                           // NEXT ITER RESULT OLDRESULT FTYPE FVALUE
    8892             :         return false;
    8893           0 :     if (!emitPopN(3))                                     // NEXT ITER RESULT
    8894             :         return false;
    8895             :     {
    8896             :         // goto tryStart;
    8897           9 :         JumpList beq;
    8898           9 :         JumpTarget breakTarget{ -1 };
    8899           9 :         if (!emitBackwardJump(JSOP_GOTO, tryStart, &beq, &breakTarget)) // NEXT ITER RESULT
    8900           0 :             return false;
    8901             :     }
    8902           9 :     this->stackDepth = savedDepthTemp;
    8903           9 :     if (!ifReturnDone.emitEnd())
    8904             :         return false;
    8905             : 
    8906           0 :     if (!ifReturnMethodIsDefined.emitElse())              // NEXT ITER RESULT FTYPE FVALUE ITER RET
    8907             :         return false;
    8908           0 :     if (!emitPopN(2))                                     // NEXT ITER RESULT FTYPE FVALUE
    8909             :         return false;
    8910           9 :     if (!ifReturnMethodIsDefined.emitEnd())
    8911             :         return false;
    8912             : 
    8913           9 :     if (!ifGeneratorClosing.emitEnd())
    8914             :         return false;
    8915             : 
    8916           0 :     if (!tryCatch.emitEnd())
    8917             :         return false;
    8918             : 
    8919             :     // After the try-catch-finally block: send the received value to the iterator.
    8920             :     // result = iter.next(received)                              // NEXT ITER RECEIVED
    8921           9 :     if (!emit2(JSOP_UNPICK, 2))                                  // RECEIVED NEXT ITER
    8922             :         return false;
    8923           9 :     if (!emit1(JSOP_DUP2))                                       // RECEIVED NEXT ITER NEXT ITER
    8924             :         return false;
    8925           0 :     if (!emit2(JSOP_PICK, 4))                                    // NEXT ITER NEXT ITER RECEIVED
    8926             :         return false;
    8927           9 :     if (!emitCall(JSOP_CALL, 1, iter))                           // NEXT ITER RESULT
    8928             :         return false;
    8929           9 :     checkTypeSet(JSOP_CALL);
    8930             : 
    8931           9 :     if (isAsyncGenerator) {
    8932           0 :         if (!emitAwaitInInnermostScope())                        // NEXT ITER RESULT RESULT
    8933             :             return false;
    8934             :     }
    8935             : 
    8936           0 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext))        // NEXT ITER RESULT
    8937             :         return false;
    8938           0 :     MOZ_ASSERT(this->stackDepth == startDepth);
    8939             : 
    8940           0 :     if (!emitJumpTargetAndPatch(checkResult))                    // checkResult:
    8941             :         return false;
    8942             : 
    8943             :     // if (!result.done) goto tryStart;                          // NEXT ITER RESULT
    8944           9 :     if (!emit1(JSOP_DUP))                                        // NEXT ITER RESULT RESULT
    8945             :         return false;
    8946           0 :     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))             // NEXT ITER RESULT DONE
    8947             :         return false;
    8948             :     // if (!DONE) goto tryStart;
    8949             :     {
    8950           9 :         JumpList beq;
    8951           9 :         JumpTarget breakTarget{ -1 };
    8952           0 :         if (!emitBackwardJump(JSOP_IFEQ, tryStart, &beq, &breakTarget)) // NEXT ITER RESULT
    8953           0 :             return false;
    8954             :     }
    8955             : 
    8956             :     // result.value
    8957           1 :     if (!emit2(JSOP_UNPICK, 2))                                  // RESULT NEXT ITER
    8958             :         return false;
    8959           1 :     if (!emitPopN(2))                                            // RESULT
    8960             :         return false;
    8961          27 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))            // VALUE
    8962             :         return false;
    8963             : 
    8964           0 :     MOZ_ASSERT(this->stackDepth == startDepth - 2);
    8965             : 
    8966             :     return true;
    8967             : }
    8968             : 
    8969             : bool
    8970       30549 : BytecodeEmitter::emitStatementList(ParseNode* pn)
    8971             : {
    8972       30549 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    8973      107261 :     for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
    8974       76712 :         if (!emitTree(pn2))
    8975             :             return false;
    8976             :     }
    8977             :     return true;
    8978             : }
    8979             : 
    8980             : bool
    8981       32140 : BytecodeEmitter::emitExpressionStatement(ParseNode* pn)
    8982             : {
    8983           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::ExpressionStatement));
    8984             : 
    8985             :     /*
    8986             :      * Top-level or called-from-a-native JS_Execute/EvaluateScript,
    8987             :      * debugger, and eval frames may need the value of the ultimate
    8988             :      * expression statement as the script's result, despite the fact
    8989             :      * that it appears useless to the compiler.
    8990             :      *
    8991             :      * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
    8992             :      * calling JS_Compile* to suppress JSOP_SETRVAL.
    8993             :      */
    8994           0 :     bool wantval = false;
    8995           0 :     bool useful = false;
    8996       32140 :     if (sc->isFunctionBox())
    8997           0 :         MOZ_ASSERT(!script->noScriptRval());
    8998             :     else
    8999        8301 :         useful = wantval = !script->noScriptRval();
    9000             : 
    9001             :     /* Don't eliminate expressions with side effects. */
    9002       32140 :     ParseNode* expr = pn->pn_kid;
    9003       32140 :     if (!useful) {
    9004           0 :         if (!checkSideEffects(expr, &useful))
    9005             :             return false;
    9006             : 
    9007             :         /*
    9008             :          * Don't eliminate apparently useless expressions if they are labeled
    9009             :          * expression statements. The startOffset() test catches the case
    9010             :          * where we are nesting in emitTree for a labeled compound statement.
    9011             :          */
    9012           0 :         if (innermostNestableControl &&
    9013       39182 :             innermostNestableControl->is<LabelControl>() &&
    9014           0 :             innermostNestableControl->as<LabelControl>().startOffset() >= offset())
    9015             :         {
    9016           0 :             useful = true;
    9017             :         }
    9018             :     }
    9019             : 
    9020           0 :     if (useful) {
    9021       31908 :         JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
    9022       31908 :         ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
    9023           0 :         MOZ_ASSERT_IF(expr->isKind(ParseNodeKind::Assign), expr->isOp(JSOP_NOP));
    9024       31908 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    9025             :             return false;
    9026           0 :         if (!emitTree(expr, valueUsage))
    9027             :             return false;
    9028           0 :         if (!emit1(op))
    9029             :             return false;
    9030         232 :     } else if (pn->isDirectivePrologueMember()) {
    9031             :         // Don't complain about directive prologue members; just don't emit
    9032             :         // their code.
    9033             :     } else {
    9034           1 :         if (JSAtom* atom = pn->isStringExprStatement()) {
    9035             :             // Warn if encountering a non-directive prologue member string
    9036             :             // expression statement, that is inconsistent with the current
    9037             :             // directive prologue.  That is, a script *not* starting with
    9038             :             // "use strict" should warn for any "use strict" statements seen
    9039             :             // later in the script, because such statements are misleading.
    9040           0 :             const char* directive = nullptr;
    9041           0 :             if (atom == cx->names().useStrict) {
    9042           0 :                 if (!sc->strictScript)
    9043           0 :                     directive = js_useStrict_str;
    9044           0 :             } else if (atom == cx->names().useAsm) {
    9045           0 :                 if (sc->isFunctionBox()) {
    9046           0 :                     if (IsAsmJSModule(sc->asFunctionBox()->function()))
    9047           0 :                         directive = js_useAsm_str;
    9048             :                 }
    9049             :             }
    9050             : 
    9051           0 :             if (directive) {
    9052           0 :                 if (!reportExtraWarning(expr, JSMSG_CONTRARY_NONDIRECTIVE, directive))
    9053             :                     return false;
    9054             :             }
    9055             :         } else {
    9056           1 :             if (!reportExtraWarning(expr, JSMSG_USELESS_EXPR))
    9057             :                 return false;
    9058             :         }
    9059             :     }
    9060             : 
    9061             :     return true;
    9062             : }
    9063             : 
    9064             : bool
    9065           0 : BytecodeEmitter::emitDeleteName(ParseNode* node)
    9066             : {
    9067           0 :     MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteName));
    9068           0 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9069             : 
    9070           0 :     ParseNode* nameExpr = node->pn_kid;
    9071           0 :     MOZ_ASSERT(nameExpr->isKind(ParseNodeKind::Name));
    9072             : 
    9073           0 :     return emitAtomOp(nameExpr, JSOP_DELNAME);
    9074             : }
    9075             : 
    9076             : bool
    9077         266 : BytecodeEmitter::emitDeleteProperty(ParseNode* node)
    9078             : {
    9079         266 :     MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteProp));
    9080         266 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9081             : 
    9082         266 :     ParseNode* propExpr = node->pn_kid;
    9083         266 :     MOZ_ASSERT(propExpr->isKind(ParseNodeKind::Dot));
    9084             : 
    9085         532 :     if (propExpr->as<PropertyAccess>().isSuper()) {
    9086             :         // Still have to calculate the base, even though we are are going
    9087             :         // to throw unconditionally, as calculating the base could also
    9088             :         // throw.
    9089           0 :         if (!emit1(JSOP_SUPERBASE))
    9090             :             return false;
    9091             : 
    9092           0 :         return emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER);
    9093             :     }
    9094             : 
    9095         532 :     JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
    9096         266 :     return emitPropOp(propExpr, delOp);
    9097             : }
    9098             : 
    9099             : bool
    9100           1 : BytecodeEmitter::emitDeleteElement(ParseNode* node)
    9101             : {
    9102          94 :     MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteElem));
    9103           0 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9104             : 
    9105           0 :     ParseNode* elemExpr = node->pn_kid;
    9106          94 :     MOZ_ASSERT(elemExpr->isKind(ParseNodeKind::Elem));
    9107             : 
    9108           0 :     if (elemExpr->as<PropertyByValue>().isSuper()) {
    9109             :         // Still have to calculate everything, even though we're gonna throw
    9110             :         // since it may have side effects
    9111           0 :         if (!emitTree(elemExpr->pn_right))
    9112             :             return false;
    9113             : 
    9114           0 :         if (!emit1(JSOP_SUPERBASE))
    9115             :             return false;
    9116           0 :         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER))
    9117             :             return false;
    9118             : 
    9119             :         // Another wrinkle: Balance the stack from the emitter's point of view.
    9120             :         // Execution will not reach here, as the last bytecode threw.
    9121           0 :         return emit1(JSOP_POP);
    9122             :     }
    9123             : 
    9124           0 :     JSOp delOp = sc->strict() ? JSOP_STRICTDELELEM : JSOP_DELELEM;
    9125           0 :     return emitElemOp(elemExpr, delOp);
    9126             : }
    9127             : 
    9128             : bool
    9129           0 : BytecodeEmitter::emitDeleteExpression(ParseNode* node)
    9130             : {
    9131           0 :     MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteExpr));
    9132           0 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9133             : 
    9134           0 :     ParseNode* expression = node->pn_kid;
    9135             : 
    9136             :     // If useless, just emit JSOP_TRUE; otherwise convert |delete <expr>| to
    9137             :     // effectively |<expr>, true|.
    9138           0 :     bool useful = false;
    9139           0 :     if (!checkSideEffects(expression, &useful))
    9140             :         return false;
    9141             : 
    9142           0 :     if (useful) {
    9143           0 :         if (!emitTree(expression))
    9144             :             return false;
    9145           0 :         if (!emit1(JSOP_POP))
    9146             :             return false;
    9147             :     }
    9148             : 
    9149           0 :     return emit1(JSOP_TRUE);
    9150             : }
    9151             : 
    9152             : static const char *
    9153         434 : SelfHostedCallFunctionName(JSAtom* name, JSContext* cx)
    9154             : {
    9155           0 :     if (name == cx->names().callFunction)
    9156             :         return "callFunction";
    9157         238 :     if (name == cx->names().callContentFunction)
    9158             :         return "callContentFunction";
    9159           1 :     if (name == cx->names().constructContentFunction)
    9160             :         return "constructContentFunction";
    9161             : 
    9162           0 :     MOZ_CRASH("Unknown self-hosted call function name");
    9163             : }
    9164             : 
    9165             : bool
    9166           0 : BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
    9167             : {
    9168             :     // Special-casing of callFunction to emit bytecode that directly
    9169             :     // invokes the callee with the correct |this| object and arguments.
    9170             :     // callFunction(fun, thisArg, arg0, arg1) thus becomes:
    9171             :     // - emit lookup for fun
    9172             :     // - emit lookup for thisArg
    9173             :     // - emit lookups for arg0, arg1
    9174             :     //
    9175             :     // argc is set to the amount of actually emitted args and the
    9176             :     // emitting of args below is disabled by setting emitArgs to false.
    9177         434 :     ParseNode* pn2 = pn->pn_head;
    9178           0 :     const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
    9179             : 
    9180         434 :     if (pn->pn_count < 3) {
    9181           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
    9182           0 :         return false;
    9183             :     }
    9184             : 
    9185           0 :     JSOp callOp = pn->getOp();
    9186         434 :     if (callOp != JSOP_CALL) {
    9187           0 :         reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
    9188           0 :         return false;
    9189             :     }
    9190             : 
    9191           0 :     bool constructing = pn2->name() == cx->names().constructContentFunction;
    9192         434 :     ParseNode* funNode = pn2->pn_next;
    9193         434 :     if (constructing) {
    9194             :         callOp = JSOP_NEW;
    9195           0 :     } else if (funNode->getKind() == ParseNodeKind::Name &&
    9196        1056 :                funNode->name() == cx->names().std_Function_apply) {
    9197           0 :         callOp = JSOP_FUNAPPLY;
    9198             :     }
    9199             : 
    9200         434 :     if (!emitTree(funNode))
    9201             :         return false;
    9202             : 
    9203             : #ifdef DEBUG
    9204         868 :     if (emitterMode == BytecodeEmitter::SelfHosting &&
    9205        1302 :         pn2->name() == cx->names().callFunction)
    9206             :     {
    9207           0 :         if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
    9208             :             return false;
    9209             :     }
    9210             : #endif
    9211             : 
    9212           0 :     ParseNode* thisOrNewTarget = funNode->pn_next;
    9213         434 :     if (constructing) {
    9214             :         // Save off the new.target value, but here emit a proper |this| for a
    9215             :         // constructing call.
    9216          43 :         if (!emit1(JSOP_IS_CONSTRUCTING))
    9217             :             return false;
    9218             :     } else {
    9219             :         // It's |this|, emit it.
    9220         391 :         if (!emitTree(thisOrNewTarget))
    9221             :             return false;
    9222             :     }
    9223             : 
    9224        1312 :     for (ParseNode* argpn = thisOrNewTarget->pn_next; argpn; argpn = argpn->pn_next) {
    9225         878 :         if (!emitTree(argpn))
    9226             :             return false;
    9227             :     }
    9228             : 
    9229           0 :     if (constructing) {
    9230          43 :         if (!emitTree(thisOrNewTarget))
    9231             :             return false;
    9232             :     }
    9233             : 
    9234         434 :     uint32_t argc = pn->pn_count - 3;
    9235           0 :     if (!emitCall(callOp, argc))
    9236             :         return false;
    9237             : 
    9238             :     checkTypeSet(callOp);
    9239             :     return true;
    9240             : }
    9241             : 
    9242             : bool
    9243           0 : BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
    9244             : {
    9245             :     // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
    9246           0 :     if (pn->pn_count != 4) {
    9247           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
    9248           0 :         return false;
    9249             :     }
    9250             : 
    9251           6 :     ParseNode* funNode = pn->pn_head;  // The resumeGenerator node.
    9252             : 
    9253           6 :     ParseNode* genNode = funNode->pn_next;
    9254           0 :     if (!emitTree(genNode))
    9255             :         return false;
    9256             : 
    9257           1 :     ParseNode* valNode = genNode->pn_next;
    9258           1 :     if (!emitTree(valNode))
    9259             :         return false;
    9260             : 
    9261           0 :     ParseNode* kindNode = valNode->pn_next;
    9262           6 :     MOZ_ASSERT(kindNode->isKind(ParseNodeKind::String));
    9263           0 :     uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
    9264           0 :     MOZ_ASSERT(!kindNode->pn_next);
    9265             : 
    9266          12 :     if (!emitCall(JSOP_RESUME, operand))
    9267             :         return false;
    9268             : 
    9269           6 :     return true;
    9270             : }
    9271             : 
    9272             : bool
    9273           0 : BytecodeEmitter::emitSelfHostedForceInterpreter()
    9274             : {
    9275           1 :     if (!emit1(JSOP_FORCEINTERPRETER))
    9276             :         return false;
    9277           1 :     if (!emit1(JSOP_UNDEFINED))
    9278             :         return false;
    9279           1 :     return true;
    9280             : }
    9281             : 
    9282             : bool
    9283           7 : BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn)
    9284             : {
    9285           0 :     if (pn->pn_count != 2) {
    9286           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", "");
    9287           0 :         return false;
    9288             :     }
    9289             : 
    9290             :     // We're just here as a sentinel. Pass the value through directly.
    9291           0 :     return emitTree(pn->pn_head->pn_next);
    9292             : }
    9293             : 
    9294             : bool
    9295          82 : BytecodeEmitter::emitSelfHostedDefineDataProperty(ParseNode* pn)
    9296             : {
    9297             :     // Only optimize when 3 arguments are passed (we use 4 to include |this|).
    9298          82 :     MOZ_ASSERT(pn->pn_count == 4);
    9299             : 
    9300          82 :     ParseNode* funNode = pn->pn_head;  // The _DefineDataProperty node.
    9301             : 
    9302           0 :     ParseNode* objNode = funNode->pn_next;
    9303           0 :     if (!emitTree(objNode))
    9304             :         return false;
    9305             : 
    9306           0 :     ParseNode* idNode = objNode->pn_next;
    9307          82 :     if (!emitTree(idNode))
    9308             :         return false;
    9309             : 
    9310           0 :     ParseNode* valNode = idNode->pn_next;
    9311           0 :     if (!emitTree(valNode))
    9312             :         return false;
    9313             : 
    9314             :     // This will leave the object on the stack instead of pushing |undefined|,
    9315             :     // but that's fine because the self-hosted code doesn't use the return
    9316             :     // value.
    9317          82 :     return emit1(JSOP_INITELEM);
    9318             : }
    9319             : 
    9320             : bool
    9321           0 : BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
    9322             : {
    9323           0 :     if (pn->pn_count != 3) {
    9324           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "hasOwn", "2", "");
    9325           0 :         return false;
    9326             :     }
    9327             : 
    9328           0 :     ParseNode* funNode = pn->pn_head;  // The hasOwn node.
    9329             : 
    9330          25 :     ParseNode* idNode = funNode->pn_next;
    9331          25 :     if (!emitTree(idNode))
    9332             :         return false;
    9333             : 
    9334          25 :     ParseNode* objNode = idNode->pn_next;
    9335          25 :     if (!emitTree(objNode))
    9336             :         return false;
    9337             : 
    9338           0 :     return emit1(JSOP_HASOWN);
    9339             : }
    9340             : 
    9341             : bool
    9342           1 : BytecodeEmitter::emitSelfHostedGetPropertySuper(ParseNode* pn)
    9343             : {
    9344           1 :     if (pn->pn_count != 4) {
    9345           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "getPropertySuper", "3", "");
    9346           0 :         return false;
    9347             :     }
    9348             : 
    9349           1 :     ParseNode* funNode = pn->pn_head;  // The getPropertySuper node.
    9350             : 
    9351           1 :     ParseNode* objNode = funNode->pn_next;
    9352           1 :     ParseNode* idNode = objNode->pn_next;
    9353           1 :     ParseNode* receiverNode = idNode->pn_next;
    9354             : 
    9355           1 :     if (!emitTree(idNode))
    9356             :         return false;
    9357             : 
    9358           1 :     if (!emitTree(receiverNode))
    9359             :         return false;
    9360             : 
    9361           1 :     if (!emitTree(objNode))
    9362             :         return false;
    9363             : 
    9364           0 :     return emitElemOpBase(JSOP_GETELEM_SUPER);
    9365             : }
    9366             : 
    9367             : bool
    9368           0 : BytecodeEmitter::isRestParameter(ParseNode* pn)
    9369             : {
    9370           0 :     if (!sc->isFunctionBox())
    9371             :         return false;
    9372             : 
    9373           0 :     FunctionBox* funbox = sc->asFunctionBox();
    9374           0 :     RootedFunction fun(cx, funbox->function());
    9375         101 :     if (!funbox->hasRest())
    9376             :         return false;
    9377             : 
    9378           0 :     if (!pn->isKind(ParseNodeKind::Name)) {
    9379           3 :         if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::Call)) {
    9380           1 :             ParseNode* pn2 = pn->pn_head;
    9381           2 :             if (pn2->getKind() == ParseNodeKind::Name &&
    9382           0 :                 pn2->name() == cx->names().allowContentIter)
    9383             :             {
    9384           0 :                 return isRestParameter(pn2->pn_next);
    9385             :             }
    9386             :         }
    9387             :         return false;
    9388             :     }
    9389             : 
    9390          35 :     JSAtom* name = pn->name();
    9391          35 :     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
    9392           1 :     if (paramLoc && lookupName(name) == *paramLoc) {
    9393          70 :         FunctionScope::Data* bindings = funbox->functionScopeBindings();
    9394           1 :         if (bindings->nonPositionalFormalStart > 0) {
    9395             :             // |paramName| can be nullptr when the rest destructuring syntax is
    9396             :             // used: `function f(...[]) {}`.
    9397             :             JSAtom* paramName =
    9398         105 :                 bindings->trailingNames[bindings->nonPositionalFormalStart - 1].name();
    9399          35 :             return paramName && name == paramName;
    9400             :         }
    9401             :     }
    9402             : 
    9403             :     return false;
    9404             : }
    9405             : 
    9406             : bool
    9407       43274 : BytecodeEmitter::emitCallee(ParseNode* callee, ParseNode* call, bool* callop)
    9408             : {
    9409           1 :     switch (callee->getKind()) {
    9410             :       case ParseNodeKind::Name:
    9411       18362 :         if (!emitGetName(callee, *callop))
    9412             :             return false;
    9413             :         break;
    9414             :       case ParseNodeKind::Dot:
    9415       33777 :         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
    9416           1 :         if (callee->as<PropertyAccess>().isSuper()) {
    9417          48 :             if (!emitSuperPropOp(callee, JSOP_GETPROP_SUPER, /* isCall = */ *callop))
    9418             :                 return false;
    9419             :         } else {
    9420           1 :             if (!emitPropOp(callee, *callop ? JSOP_CALLPROP : JSOP_GETPROP))
    9421             :                 return false;
    9422             :         }
    9423             : 
    9424             :         break;
    9425             :       case ParseNodeKind::Elem:
    9426           0 :         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
    9427         120 :         if (callee->as<PropertyByValue>().isSuper()) {
    9428           0 :             if (!emitSuperElemOp(callee, JSOP_GETELEM_SUPER, /* isCall = */ *callop))
    9429             :                 return false;
    9430             :         } else {
    9431          60 :             if (!emitElemOp(callee, *callop ? JSOP_CALLELEM : JSOP_GETELEM))
    9432             :                 return false;
    9433          60 :             if (*callop) {
    9434          60 :                 if (!emit1(JSOP_SWAP))
    9435             :                     return false;
    9436             :             }
    9437             :         }
    9438             : 
    9439             :         break;
    9440             :       case ParseNodeKind::Function:
    9441             :         /*
    9442             :          * Top level lambdas which are immediately invoked should be
    9443             :          * treated as only running once. Every time they execute we will
    9444             :          * create new types and scripts for their contents, to increase
    9445             :          * the quality of type information within them and enable more
    9446             :          * backend optimizations. Note that this does not depend on the
    9447             :          * lambda being invoked at most once (it may be named or be
    9448             :          * accessed via foo.caller indirection), as multiple executions
    9449             :          * will just cause the inner scripts to be repeatedly cloned.
    9450             :          */
    9451         122 :         MOZ_ASSERT(!emittingRunOnceLambda);
    9452           0 :         if (checkRunOnceContext()) {
    9453           0 :             emittingRunOnceLambda = true;
    9454          28 :             if (!emitTree(callee))
    9455             :                 return false;
    9456          28 :             emittingRunOnceLambda = false;
    9457             :         } else {
    9458          94 :             if (!emitTree(callee))
    9459             :                 return false;
    9460             :         }
    9461           0 :         *callop = false;
    9462         122 :         break;
    9463             :       case ParseNodeKind::SuperBase:
    9464          79 :         MOZ_ASSERT(call->isKind(ParseNodeKind::SuperCall));
    9465           0 :         MOZ_ASSERT(parser->astGenerator().isSuperBase(callee));
    9466           0 :         if (!emit1(JSOP_SUPERFUN))
    9467             :             return false;
    9468             :         break;
    9469             :       default:
    9470           0 :         if (!emitTree(callee))
    9471             :             return false;
    9472           0 :         *callop = false;             /* trigger JSOP_UNDEFINED after */
    9473           0 :         break;
    9474             :     }
    9475             : 
    9476             :     return true;
    9477             : }
    9478             : 
    9479             : bool
    9480           0 : BytecodeEmitter::emitPipeline(ParseNode* pn)
    9481             : {
    9482           0 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9483           0 :     MOZ_ASSERT(pn->pn_count >= 2);
    9484             : 
    9485           0 :     if (!emitTree(pn->pn_head))
    9486             :         return false;
    9487             : 
    9488           0 :     ParseNode* callee = pn->pn_head->pn_next;
    9489             : 
    9490           0 :     do {
    9491           0 :         bool callop = true;
    9492           0 :         if (!emitCallee(callee, pn, &callop))
    9493           0 :             return false;
    9494             : 
    9495             :         // Emit room for |this|
    9496           0 :         if (!callop) {
    9497           0 :             if (!emit1(JSOP_UNDEFINED))
    9498             :                 return false;
    9499             :         }
    9500             : 
    9501           0 :         if (!emit2(JSOP_PICK, 2))
    9502             :             return false;
    9503             : 
    9504           0 :         if (!emitCall(JSOP_CALL, 1, pn))
    9505             :             return false;
    9506             : 
    9507           0 :         checkTypeSet(JSOP_CALL);
    9508           0 :     } while ((callee = callee->pn_next));
    9509             : 
    9510             :     return true;
    9511             : }
    9512             : 
    9513             : bool
    9514       43830 : BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9515             : {
    9516             :     bool callop =
    9517       46771 :         pn->isKind(ParseNodeKind::Call) || pn->isKind(ParseNodeKind::TaggedTemplate);
    9518             :     /*
    9519             :      * Emit callable invocation or operator new (constructor call) code.
    9520             :      * First, emit code for the left operand to evaluate the callable or
    9521             :      * constructable object expression.
    9522             :      *
    9523             :      * For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
    9524             :      * This is necessary to interpose the lambda-initialized method read
    9525             :      * barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
    9526             :      * JSOP_{SET,INIT}PROP.
    9527             :      *
    9528             :      * Then (or in a call case that has no explicit reference-base
    9529             :      * object) we emit JSOP_UNDEFINED to produce the undefined |this|
    9530             :      * value required for calls (which non-strict mode functions
    9531             :      * will box into the global object).
    9532             :      */
    9533       43830 :     uint32_t argc = pn->pn_count - 1;
    9534             : 
    9535       43830 :     if (argc >= ARGC_LIMIT) {
    9536           0 :         reportError(pn, callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
    9537           0 :         return false;
    9538             :     }
    9539             : 
    9540           0 :     ParseNode* pn2 = pn->pn_head;
    9541       87660 :     bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
    9542             : 
    9543           0 :     if (pn2->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
    9544             :         // Calls to "forceInterpreter", "callFunction",
    9545             :         // "callContentFunction", or "resumeGenerator" in self-hosted
    9546             :         // code generate inline bytecode.
    9547       15330 :         if (pn2->name() == cx->names().callFunction ||
    9548       11495 :             pn2->name() == cx->names().callContentFunction ||
    9549           0 :             pn2->name() == cx->names().constructContentFunction)
    9550             :         {
    9551         434 :             return emitSelfHostedCallFunction(pn);
    9552             :         }
    9553           0 :         if (pn2->name() == cx->names().resumeGenerator)
    9554           6 :             return emitSelfHostedResumeGenerator(pn);
    9555        8067 :         if (pn2->name() == cx->names().forceInterpreter)
    9556           0 :             return emitSelfHostedForceInterpreter();
    9557           0 :         if (pn2->name() == cx->names().allowContentIter)
    9558           7 :             return emitSelfHostedAllowContentIter(pn);
    9559        8043 :         if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
    9560          82 :             return emitSelfHostedDefineDataProperty(pn);
    9561           0 :         if (pn2->name() == cx->names().hasOwn)
    9562           0 :             return emitSelfHostedHasOwn(pn);
    9563           0 :         if (pn2->name() == cx->names().getPropertySuper)
    9564           1 :             return emitSelfHostedGetPropertySuper(pn);
    9565             :         // Fall through
    9566             :     }
    9567             : 
    9568       43274 :     if (!emitCallee(pn2, pn, &callop))
    9569             :         return false;
    9570             : 
    9571      124114 :     bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
    9572           0 :                    pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
    9573             : 
    9574             : 
    9575             :     // Emit room for |this|.
    9576       43274 :     if (!callop) {
    9577        3081 :         if (isNewOp) {
    9578           0 :             if (!emit1(JSOP_IS_CONSTRUCTING))
    9579             :                 return false;
    9580             :         } else {
    9581         147 :             if (!emit1(JSOP_UNDEFINED))
    9582             :                 return false;
    9583             :         }
    9584             :     }
    9585             : 
    9586             :     /*
    9587             :      * Emit code for each argument in order, then emit the JSOP_*CALL or
    9588             :      * JSOP_NEW bytecode with a two-byte immediate telling how many args
    9589             :      * were pushed on the operand stack.
    9590             :      */
    9591       43273 :     if (!spread) {
    9592           0 :         for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
    9593           0 :             if (!emitTree(pn3))
    9594             :                 return false;
    9595             :         }
    9596             : 
    9597       43139 :         if (isNewOp) {
    9598        2930 :             if (pn->isKind(ParseNodeKind::SuperCall)) {
    9599          77 :                 if (!emit1(JSOP_NEWTARGET))
    9600             :                     return false;
    9601             :             } else {
    9602             :                 // Repush the callee as new.target
    9603        2853 :                 if (!emitDupAt(argc + 1))
    9604             :                     return false;
    9605             :             }
    9606             :         }
    9607             :     } else {
    9608         135 :         ParseNode* args = pn2->pn_next;
    9609         135 :         bool emitOptCode = (argc == 1) && isRestParameter(args->pn_kid);
    9610         270 :         InternalIfEmitter ifNotOptimizable(this);
    9611             : 
    9612         135 :         if (emitOptCode) {
    9613             :             // Emit a preparation code to optimize the spread call with a rest
    9614             :             // parameter:
    9615             :             //
    9616             :             //   function f(...args) {
    9617             :             //     g(...args);
    9618             :             //   }
    9619             :             //
    9620             :             // If the spread operand is a rest parameter and it's optimizable
    9621             :             // array, skip spread operation and pass it directly to spread call
    9622             :             // operation.  See the comment in OptimizeSpreadCall in
    9623             :             // Interpreter.cpp for the optimizable conditons.
    9624             : 
    9625          35 :             if (!emitTree(args->pn_kid))
    9626           0 :                 return false;
    9627             : 
    9628          35 :             if (!emit1(JSOP_OPTIMIZE_SPREADCALL))
    9629             :                 return false;
    9630             : 
    9631           0 :             if (!emit1(JSOP_NOT))
    9632             :                 return false;
    9633             : 
    9634           0 :             if (!ifNotOptimizable.emitThen())
    9635             :                 return false;
    9636             : 
    9637          35 :             if (!emit1(JSOP_POP))
    9638             :                 return false;
    9639             :         }
    9640             : 
    9641         135 :         if (!emitArray(args, argc))
    9642             :             return false;
    9643             : 
    9644         135 :         if (emitOptCode) {
    9645          35 :             if (!ifNotOptimizable.emitEnd())
    9646             :                 return false;
    9647             :         }
    9648             : 
    9649         135 :         if (isNewOp) {
    9650           0 :             if (pn->isKind(ParseNodeKind::SuperCall)) {
    9651           0 :                 if (!emit1(JSOP_NEWTARGET))
    9652             :                     return false;
    9653             :             } else {
    9654           2 :                 if (!emitDupAt(2))
    9655             :                     return false;
    9656             :             }
    9657             :         }
    9658             :     }
    9659             : 
    9660           0 :     if (!spread) {
    9661       86278 :         if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
    9662       18285 :             if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
    9663             :                 return false;
    9664             :             checkTypeSet(JSOP_CALL_IGNORES_RV);
    9665             :         } else {
    9666           0 :             if (!emitCall(pn->getOp(), argc, pn))
    9667             :                 return false;
    9668           0 :             checkTypeSet(pn->getOp());
    9669             :         }
    9670             :     } else {
    9671         270 :         if (!emit1(pn->getOp()))
    9672             :             return false;
    9673         135 :         checkTypeSet(pn->getOp());
    9674             :     }
    9675      129804 :     if (pn->isOp(JSOP_EVAL) ||
    9676       86512 :         pn->isOp(JSOP_STRICTEVAL) ||
    9677           0 :         pn->isOp(JSOP_SPREADEVAL) ||
    9678       43256 :         pn->isOp(JSOP_STRICTSPREADEVAL))
    9679             :     {
    9680           0 :         uint32_t lineNum = parser->errorReporter().lineAt(pn->pn_pos.begin);
    9681          18 :         if (!emitUint32Operand(JSOP_LINENO, lineNum))
    9682             :             return false;
    9683             :     }
    9684             : 
    9685             :     return true;
    9686             : }
    9687             : 
    9688             : static const JSOp ParseNodeKindToJSOp[] = {
    9689             :     // JSOP_NOP is for pipeline operator which does not emit its own JSOp
    9690             :     // but has highest precedence in binary operators
    9691             :     JSOP_NOP,
    9692             :     JSOP_OR,
    9693             :     JSOP_AND,
    9694             :     JSOP_BITOR,
    9695             :     JSOP_BITXOR,
    9696             :     JSOP_BITAND,
    9697             :     JSOP_STRICTEQ,
    9698             :     JSOP_EQ,
    9699             :     JSOP_STRICTNE,
    9700             :     JSOP_NE,
    9701             :     JSOP_LT,
    9702             :     JSOP_LE,
    9703             :     JSOP_GT,
    9704             :     JSOP_GE,
    9705             :     JSOP_INSTANCEOF,
    9706             :     JSOP_IN,
    9707             :     JSOP_LSH,
    9708             :     JSOP_RSH,
    9709             :     JSOP_URSH,
    9710             :     JSOP_ADD,
    9711             :     JSOP_SUB,
    9712             :     JSOP_MUL,
    9713             :     JSOP_DIV,
    9714             :     JSOP_MOD,
    9715             :     JSOP_POW
    9716             : };
    9717             : 
    9718             : static inline JSOp
    9719           0 : BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk)
    9720             : {
    9721       11850 :     MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst);
    9722       11850 :     MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast);
    9723           0 :     return ParseNodeKindToJSOp[size_t(pnk) - size_t(ParseNodeKind::BinOpFirst)];
    9724             : }
    9725             : 
    9726             : bool
    9727           0 : BytecodeEmitter::emitRightAssociative(ParseNode* pn)
    9728             : {
    9729             :     // ** is the only right-associative operator.
    9730           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Pow));
    9731           0 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9732             : 
    9733             :     // Right-associative operator chain.
    9734           0 :     for (ParseNode* subexpr = pn->pn_head; subexpr; subexpr = subexpr->pn_next) {
    9735           0 :         if (!emitTree(subexpr))
    9736             :             return false;
    9737             :     }
    9738           0 :     for (uint32_t i = 0; i < pn->pn_count - 1; i++) {
    9739           0 :         if (!emit1(JSOP_POW))
    9740             :             return false;
    9741             :     }
    9742             :     return true;
    9743             : }
    9744             : 
    9745             : bool
    9746           0 : BytecodeEmitter::emitLeftAssociative(ParseNode* pn)
    9747             : {
    9748           0 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9749             : 
    9750             :     // Left-associative operator chain.
    9751       11850 :     if (!emitTree(pn->pn_head))
    9752             :         return false;
    9753       11850 :     JSOp op = BinaryOpParseNodeKindToJSOp(pn->getKind());
    9754       11850 :     ParseNode* nextExpr = pn->pn_head->pn_next;
    9755       13180 :     do {
    9756       13180 :         if (!emitTree(nextExpr))
    9757             :             return false;
    9758       13180 :         if (!emit1(op))
    9759             :             return false;
    9760       13180 :     } while ((nextExpr = nextExpr->pn_next));
    9761             :     return true;
    9762             : }
    9763             : 
    9764             : bool
    9765        4454 : BytecodeEmitter::emitLogical(ParseNode* pn)
    9766             : {
    9767        4454 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9768        6962 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::Or) || pn->isKind(ParseNodeKind::And));
    9769             : 
    9770             :     /*
    9771             :      * JSOP_OR converts the operand on the stack to boolean, leaves the original
    9772             :      * value on the stack and jumps if true; otherwise it falls into the next
    9773             :      * bytecode, which pops the left operand and then evaluates the right operand.
    9774             :      * The jump goes around the right operand evaluation.
    9775             :      *
    9776             :      * JSOP_AND converts the operand on the stack to boolean and jumps if false;
    9777             :      * otherwise it falls into the right operand's bytecode.
    9778             :      */
    9779             : 
    9780           0 :     TDZCheckCache tdzCache(this);
    9781             : 
    9782             :     /* Left-associative operator chain: avoid too much recursion. */
    9783           0 :     ParseNode* pn2 = pn->pn_head;
    9784        4454 :     if (!emitTree(pn2))
    9785             :         return false;
    9786           0 :     JSOp op = pn->isKind(ParseNodeKind::Or) ? JSOP_OR : JSOP_AND;
    9787        4454 :     JumpList jump;
    9788        4454 :     if (!emitJump(op, &jump))
    9789             :         return false;
    9790           0 :     if (!emit1(JSOP_POP))
    9791             :         return false;
    9792             : 
    9793             :     /* Emit nodes between the head and the tail. */
    9794           0 :     while ((pn2 = pn2->pn_next)->pn_next) {
    9795         946 :         if (!emitTree(pn2))
    9796             :             return false;
    9797           0 :         if (!emitJump(op, &jump))
    9798             :             return false;
    9799         946 :         if (!emit1(JSOP_POP))
    9800             :             return false;
    9801             :     }
    9802        4454 :     if (!emitTree(pn2))
    9803             :         return false;
    9804             : 
    9805        4454 :     if (!emitJumpTargetAndPatch(jump))
    9806             :         return false;
    9807           0 :     return true;
    9808             : }
    9809             : 
    9810             : bool
    9811           8 : BytecodeEmitter::emitSequenceExpr(ParseNode* pn,
    9812             :                                   ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9813             : {
    9814          19 :     for (ParseNode* child = pn->pn_head; ; child = child->pn_next) {
    9815          30 :         if (!updateSourceCoordNotes(child->pn_pos.begin))
    9816             :             return false;
    9817          19 :         if (!emitTree(child, child->pn_next ? ValueUsage::IgnoreValue : valueUsage))
    9818             :             return false;
    9819          19 :         if (!child->pn_next)
    9820             :             break;
    9821           0 :         if (!emit1(JSOP_POP))
    9822             :             return false;
    9823             :     }
    9824             :     return true;
    9825             : }
    9826             : 
    9827             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    9828             : // the comment on emitSwitch.
    9829             : MOZ_NEVER_INLINE bool
    9830           0 : BytecodeEmitter::emitIncOrDec(ParseNode* pn)
    9831             : {
    9832         648 :     switch (pn->pn_kid->getKind()) {
    9833             :       case ParseNodeKind::Dot:
    9834         116 :         return emitPropIncDec(pn);
    9835             :       case ParseNodeKind::Elem:
    9836           0 :         return emitElemIncDec(pn);
    9837             :       case ParseNodeKind::Call:
    9838           0 :         return emitCallIncDec(pn);
    9839             :       default:
    9840         527 :         return emitNameIncDec(pn);
    9841             :     }
    9842             : }
    9843             : 
    9844             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    9845             : // the comment on emitSwitch.
    9846             : MOZ_NEVER_INLINE bool
    9847           0 : BytecodeEmitter::emitLabeledStatement(const LabeledStatement* pn)
    9848             : {
    9849             :     /*
    9850             :      * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
    9851             :      * following the labeled statement.
    9852             :      */
    9853             :     uint32_t index;
    9854           0 :     if (!makeAtomIndex(pn->label(), &index))
    9855             :         return false;
    9856             : 
    9857           0 :     JumpList top;
    9858           0 :     if (!emitJump(JSOP_LABEL, &top))
    9859             :         return false;
    9860             : 
    9861             :     /* Emit code for the labeled statement. */
    9862           0 :     LabelControl controlInfo(this, pn->label(), offset());
    9863             : 
    9864           0 :     if (!emitTree(pn->statement()))
    9865             :         return false;
    9866             : 
    9867             :     /* Patch the JSOP_LABEL offset. */
    9868           0 :     JumpTarget brk{ lastNonJumpTargetOffset() };
    9869           0 :     patchJumpsToTarget(top, brk);
    9870             : 
    9871           0 :     if (!controlInfo.patchBreaks(this))
    9872             :         return false;
    9873             : 
    9874           0 :     return true;
    9875             : }
    9876             : 
    9877             : bool
    9878           0 : BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional,
    9879             :                                            ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9880             : {
    9881             :     /* Emit the condition, then branch if false to the else part. */
    9882         971 :     if (!emitTree(&conditional.condition()))
    9883             :         return false;
    9884             : 
    9885         971 :     IfEmitter ifThenElse(this);
    9886         971 :     if (!ifThenElse.emitCond())
    9887             :         return false;
    9888             : 
    9889         971 :     if (!emitTree(&conditional.thenExpression(), valueUsage))
    9890             :         return false;
    9891             : 
    9892           0 :     if (!ifThenElse.emitElse())
    9893             :         return false;
    9894             : 
    9895         971 :     if (!emitTree(&conditional.elseExpression(), valueUsage))
    9896             :         return false;
    9897             : 
    9898         971 :     if (!ifThenElse.emitEnd())
    9899             :         return false;
    9900           0 :     MOZ_ASSERT(ifThenElse.pushed() == 1);
    9901             : 
    9902             :     return true;
    9903             : }
    9904             : 
    9905             : bool
    9906        4855 : BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type)
    9907             : {
    9908           0 :     for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
    9909       16285 :         if (!updateSourceCoordNotes(propdef->pn_pos.begin))
    9910             :             return false;
    9911             : 
    9912             :         // Handle __proto__: v specially because *only* this form, and no other
    9913             :         // involving "__proto__", performs [[Prototype]] mutation.
    9914       16285 :         if (propdef->isKind(ParseNodeKind::MutateProto)) {
    9915          16 :             MOZ_ASSERT(type == ObjectLiteral);
    9916          16 :             if (!emitTree(propdef->pn_kid))
    9917             :                 return false;
    9918           0 :             objp.set(nullptr);
    9919          16 :             if (!emit1(JSOP_MUTATEPROTO))
    9920             :                 return false;
    9921             :             continue;
    9922             :         }
    9923             : 
    9924       16269 :         if (propdef->isKind(ParseNodeKind::Spread)) {
    9925          13 :             MOZ_ASSERT(type == ObjectLiteral);
    9926             : 
    9927           0 :             if (!emit1(JSOP_DUP))
    9928             :                 return false;
    9929             : 
    9930           0 :             if (!emitTree(propdef->pn_kid))
    9931             :                 return false;
    9932             : 
    9933           0 :             if (!emitCopyDataProperties(CopyOption::Unfiltered))
    9934             :                 return false;
    9935             : 
    9936          13 :             objp.set(nullptr);
    9937           0 :             continue;
    9938             :         }
    9939             : 
    9940           0 :         bool extraPop = false;
    9941       16256 :         if (type == ClassBody && propdef->as<ClassMethod>().isStatic()) {
    9942          57 :             extraPop = true;
    9943           0 :             if (!emit1(JSOP_DUP2))
    9944             :                 return false;
    9945          57 :             if (!emit1(JSOP_POP))
    9946             :                 return false;
    9947             :         }
    9948             : 
    9949             :         /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
    9950           0 :         ParseNode* key = propdef->pn_left;
    9951           0 :         bool isIndex = false;
    9952       16256 :         if (key->isKind(ParseNodeKind::Number)) {
    9953           0 :             if (!emitNumberOp(key->pn_dval))
    9954             :                 return false;
    9955             :             isIndex = true;
    9956           0 :         } else if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
    9957           0 :                    key->isKind(ParseNodeKind::String))
    9958             :         {
    9959             :             // EmitClass took care of constructor already.
    9960       19452 :             if (type == ClassBody && key->pn_atom == cx->names().constructor &&
    9961           1 :                 !propdef->as<ClassMethod>().isStatic())
    9962             :             {
    9963             :                 continue;
    9964             :             }
    9965             :         } else {
    9966          58 :             if (!emitComputedPropertyName(key))
    9967             :                 return false;
    9968             :             isIndex = true;
    9969             :         }
    9970             : 
    9971             :         /* Emit code for the property initializer. */
    9972           1 :         if (!emitTree(propdef->pn_right))
    9973             :             return false;
    9974             : 
    9975       32184 :         JSOp op = propdef->getOp();
    9976       16092 :         MOZ_ASSERT(op == JSOP_INITPROP ||
    9977             :                    op == JSOP_INITPROP_GETTER ||
    9978             :                    op == JSOP_INITPROP_SETTER);
    9979             : 
    9980       16092 :         FunctionPrefixKind prefixKind = op == JSOP_INITPROP_GETTER ? FunctionPrefixKind::Get
    9981       15167 :                                         : op == JSOP_INITPROP_SETTER ? FunctionPrefixKind::Set
    9982       16092 :                                         : FunctionPrefixKind::None;
    9983             : 
    9984       16092 :         if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
    9985        1023 :             objp.set(nullptr);
    9986             : 
    9987       39373 :         if (propdef->pn_right->isKind(ParseNodeKind::Function) &&
    9988       14378 :             propdef->pn_right->pn_funbox->needsHomeObject())
    9989             :         {
    9990         162 :             MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty());
    9991           0 :             bool isAsync = propdef->pn_right->pn_funbox->isAsync();
    9992           0 :             if (isAsync) {
    9993           5 :                 if (!emit1(JSOP_SWAP))
    9994             :                     return false;
    9995             :             }
    9996          54 :             if (!emit2(JSOP_INITHOMEOBJECT, isIndex + isAsync))
    9997             :                 return false;
    9998          54 :             if (isAsync) {
    9999           0 :                 if (!emit1(JSOP_POP))
   10000             :                     return false;
   10001             :             }
   10002             :         }
   10003             : 
   10004             :         // Class methods are not enumerable.
   10005       16092 :         if (type == ClassBody) {
   10006        1387 :             switch (op) {
   10007             :               case JSOP_INITPROP:        op = JSOP_INITHIDDENPROP;          break;
   10008         249 :               case JSOP_INITPROP_GETTER: op = JSOP_INITHIDDENPROP_GETTER;   break;
   10009          22 :               case JSOP_INITPROP_SETTER: op = JSOP_INITHIDDENPROP_SETTER;   break;
   10010           0 :               default: MOZ_CRASH("Invalid op");
   10011             :             }
   10012             :         }
   10013             : 
   10014       16092 :         if (isIndex) {
   10015          68 :             objp.set(nullptr);
   10016           0 :             switch (op) {
   10017             :               case JSOP_INITPROP:               op = JSOP_INITELEM;              break;
   10018           1 :               case JSOP_INITHIDDENPROP:         op = JSOP_INITHIDDENELEM;        break;
   10019           0 :               case JSOP_INITPROP_GETTER:        op = JSOP_INITELEM_GETTER;       break;
   10020           0 :               case JSOP_INITHIDDENPROP_GETTER:  op = JSOP_INITHIDDENELEM_GETTER; break;
   10021           0 :               case JSOP_INITPROP_SETTER:        op = JSOP_INITELEM_SETTER;       break;
   10022           0 :               case JSOP_INITHIDDENPROP_SETTER:  op = JSOP_INITHIDDENELEM_SETTER; break;
   10023           0 :               default: MOZ_CRASH("Invalid op");
   10024             :             }
   10025         136 :             if (propdef->pn_right->isDirectRHSAnonFunction()) {
   10026          10 :                 if (!emitDupAt(1))
   10027             :                     return false;
   10028          10 :                 if (!emit2(JSOP_SETFUNNAME, uint8_t(prefixKind)))
   10029             :                     return false;
   10030             :             }
   10031          68 :             if (!emit1(op))
   10032             :                 return false;
   10033             :         } else {
   10034       16421 :             MOZ_ASSERT(key->isKind(ParseNodeKind::ObjectPropertyName) ||
   10035             :                        key->isKind(ParseNodeKind::String));
   10036             : 
   10037             :             uint32_t index;
   10038       16024 :             if (!makeAtomIndex(key->pn_atom, &index))
   10039           0 :                 return false;
   10040             : 
   10041       16023 :             if (objp) {
   10042           0 :                 MOZ_ASSERT(type == ObjectLiteral);
   10043           0 :                 MOZ_ASSERT(!IsHiddenInitOp(op));
   10044           0 :                 MOZ_ASSERT(!objp->inDictionaryMode());
   10045       22892 :                 Rooted<jsid> id(cx, AtomToId(key->pn_atom));
   10046           0 :                 if (!NativeDefineDataProperty(cx, objp, id, UndefinedHandleValue,
   10047             :                                               JSPROP_ENUMERATE))
   10048             :                 {
   10049           0 :                     return false;
   10050             :                 }
   10051       22892 :                 if (objp->inDictionaryMode())
   10052           0 :                     objp.set(nullptr);
   10053             :             }
   10054             : 
   10055           0 :             if (propdef->pn_right->isDirectRHSAnonFunction()) {
   10056         480 :                 MOZ_ASSERT(prefixKind == FunctionPrefixKind::None);
   10057             : 
   10058         960 :                 RootedAtom keyName(cx, key->pn_atom);
   10059         480 :                 if (!setOrEmitSetFunName(propdef->pn_right, keyName))
   10060           0 :                     return false;
   10061             :             }
   10062       16023 :             if (!emitIndex32(op, index))
   10063             :                 return false;
   10064             :         }
   10065             : 
   10066           0 :         if (extraPop) {
   10067           0 :             if (!emit1(JSOP_POP))
   10068             :                 return false;
   10069             :         }
   10070             :     }
   10071             :     return true;
   10072             : }
   10073             : 
   10074             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
   10075             : // the comment on emitSwitch.
   10076             : MOZ_NEVER_INLINE bool
   10077           0 : BytecodeEmitter::emitObject(ParseNode* pn)
   10078             : {
   10079        4660 :     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && checkSingletonContext())
   10080          17 :         return emitSingletonInitialiser(pn);
   10081             : 
   10082             :     /*
   10083             :      * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
   10084             :      * a new object and defining (in source order) each property on the object
   10085             :      * (or mutating the object's [[Prototype]], in the case of __proto__).
   10086             :      */
   10087        4643 :     ptrdiff_t offset = this->offset();
   10088        4643 :     if (!emitNewInit(JSProto_Object))
   10089             :         return false;
   10090             : 
   10091             :     // Try to construct the shape of the object as we go, so we can emit a
   10092             :     // JSOP_NEWOBJECT with the final shape instead.
   10093             :     // In the case of computed property names and indices, we cannot fix the
   10094             :     // shape at bytecode compile time. When the shape cannot be determined,
   10095             :     // |obj| is nulled out.
   10096             : 
   10097             :     // No need to do any guessing for the object kind, since we know the upper
   10098             :     // bound of how many properties we plan to have.
   10099        9286 :     gc::AllocKind kind = gc::GetGCObjectKind(pn->pn_count);
   10100        9286 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
   10101        4643 :     if (!obj)
   10102             :         return false;
   10103             : 
   10104        4643 :     if (!emitPropertyList(pn, &obj, ObjectLiteral))
   10105             :         return false;
   10106             : 
   10107           0 :     if (obj) {
   10108             :         // The object survived and has a predictable shape: update the original
   10109             :         // bytecode.
   10110        4380 :         if (!replaceNewInitWithNewObject(obj, offset))
   10111             :             return false;
   10112             :     }
   10113             : 
   10114             :     return true;
   10115             : }
   10116             : 
   10117             : bool
   10118           0 : BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
   10119             : {
   10120        4380 :     ObjectBox* objbox = parser->newObjectBox(obj);
   10121        4380 :     if (!objbox)
   10122             :         return false;
   10123             : 
   10124             :     static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
   10125             :                   "newinit and newobject must have equal length to edit in-place");
   10126             : 
   10127        4380 :     uint32_t index = objectList.add(objbox);
   10128        4380 :     jsbytecode* code = this->code(offset);
   10129             : 
   10130        4380 :     MOZ_ASSERT(code[0] == JSOP_NEWINIT);
   10131           0 :     code[0] = JSOP_NEWOBJECT;
   10132           0 :     SET_UINT32(code, index);
   10133             : 
   10134           0 :     return true;
   10135             : }
   10136             : 
   10137             : bool
   10138        2700 : BytecodeEmitter::emitArrayLiteral(ParseNode* pn)
   10139             : {
   10140           0 :     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head) {
   10141           0 :         if (checkSingletonContext()) {
   10142             :             // Bake in the object entirely if it will only be created once.
   10143          26 :             return emitSingletonInitialiser(pn);
   10144             :         }
   10145             : 
   10146             :         // If the array consists entirely of primitive values, make a
   10147             :         // template object with copy on write elements that can be reused
   10148             :         // every time the initializer executes. Don't do this if the array is
   10149             :         // small: copying the elements lazily is not worth it in that case.
   10150             :         static const size_t MinElementsForCopyOnWrite = 5;
   10151           0 :         if (emitterMode != BytecodeEmitter::SelfHosting &&
   10152        1030 :             pn->pn_count >= MinElementsForCopyOnWrite)
   10153             :         {
   10154         259 :             RootedValue value(cx);
   10155         125 :             if (!pn->getConstantValue(cx, ParseNode::ForCopyOnWriteArray, &value))
   10156         116 :                 return false;
   10157         125 :             if (!value.isMagic(JS_GENERIC_MAGIC)) {
   10158             :                 // Note: the group of the template object might not yet reflect
   10159             :                 // that the object has copy on write elements. When the
   10160             :                 // interpreter or JIT compiler fetches the template, it should
   10161             :                 // use ObjectGroup::getOrFixupCopyOnWriteObject to make sure the
   10162             :                 // group for the template is accurate. We don't do this here as we
   10163             :                 // want to use ObjectGroup::allocationSiteGroup, which requires a
   10164             :                 // finished script.
   10165         116 :                 JSObject* obj = &value.toObject();
   10166           0 :                 MOZ_ASSERT(obj->is<ArrayObject>() &&
   10167             :                            obj->as<ArrayObject>().denseElementsAreCopyOnWrite());
   10168             : 
   10169         116 :                 ObjectBox* objbox = parser->newObjectBox(obj);
   10170           0 :                 if (!objbox)
   10171             :                     return false;
   10172             : 
   10173         232 :                 return emitObjectOp(objbox, JSOP_NEWARRAY_COPYONWRITE);
   10174             :             }
   10175             :         }
   10176             :     }
   10177             : 
   10178           0 :     return emitArray(pn->pn_head, pn->pn_count);
   10179             : }
   10180             : 
   10181             : bool
   10182        2693 : BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count)
   10183             : {
   10184             : 
   10185             :     /*
   10186             :      * Emit code for [a, b, c] that is equivalent to constructing a new
   10187             :      * array and in source order evaluating each element value and adding
   10188             :      * it to the array, without invoking latent setters.  We use the
   10189             :      * JSOP_NEWINIT and JSOP_INITELEM_ARRAY bytecodes to ignore setters and
   10190             :      * to avoid dup'ing and popping the array as each element is added, as
   10191             :      * JSOP_SETELEM/JSOP_SETPROP would do.
   10192             :      */
   10193             : 
   10194           0 :     uint32_t nspread = 0;
   10195           0 :     for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
   10196           1 :         if (elt->isKind(ParseNodeKind::Spread))
   10197         242 :             nspread++;
   10198             :     }
   10199             : 
   10200             :     // Array literal's length is limited to NELEMENTS_LIMIT in parser.
   10201             :     static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
   10202             :                   "array literals' maximum length must not exceed limits "
   10203             :                   "required by BaselineCompiler::emit_JSOP_NEWARRAY, "
   10204             :                   "BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
   10205             :                   "and DoSetElemFallback's handling of JSOP_INITELEM_ARRAY");
   10206        2693 :     MOZ_ASSERT(count >= nspread);
   10207           0 :     MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,
   10208             :                "the parser must throw an error if the array exceeds maximum "
   10209             :                "length");
   10210             : 
   10211             :     // For arrays with spread, this is a very pessimistic allocation, the
   10212             :     // minimum possible final size.
   10213           0 :     if (!emitUint32Operand(JSOP_NEWARRAY, count - nspread))         // ARRAY
   10214             :         return false;
   10215             : 
   10216             :     ParseNode* pn2 = pn;
   10217             :     uint32_t index;
   10218             :     bool afterSpread = false;
   10219       12207 :     for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
   10220        9483 :         if (!afterSpread && pn2->isKind(ParseNodeKind::Spread)) {
   10221           0 :             afterSpread = true;
   10222         224 :             if (!emitNumberOp(index))                               // ARRAY INDEX
   10223             :                 return false;
   10224             :         }
   10225           0 :         if (!updateSourceCoordNotes(pn2->pn_pos.begin))
   10226             :             return false;
   10227             : 
   10228        4757 :         bool allowSelfHostedIter = false;
   10229           0 :         if (pn2->isKind(ParseNodeKind::Elision)) {
   10230           0 :             if (!emit1(JSOP_HOLE))
   10231             :                 return false;
   10232             :         } else {
   10233             :             ParseNode* expr;
   10234           0 :             if (pn2->isKind(ParseNodeKind::Spread)) {
   10235           0 :                 expr = pn2->pn_kid;
   10236             : 
   10237         485 :                 if (emitterMode == BytecodeEmitter::SelfHosting &&
   10238         244 :                     expr->isKind(ParseNodeKind::Call) &&
   10239           0 :                     expr->pn_head->name() == cx->names().allowContentIter)
   10240             :                 {
   10241           1 :                     allowSelfHostedIter = true;
   10242             :                 }
   10243             :             } else {
   10244             :                 expr = pn2;
   10245             :             }
   10246           0 :             if (!emitTree(expr))                                         // ARRAY INDEX? VALUE
   10247             :                 return false;
   10248             :         }
   10249           0 :         if (pn2->isKind(ParseNodeKind::Spread)) {
   10250           0 :             if (!emitIterator())                                         // ARRAY INDEX NEXT ITER
   10251             :                 return false;
   10252         242 :             if (!emit2(JSOP_PICK, 3))                                    // INDEX NEXT ITER ARRAY
   10253             :                 return false;
   10254         242 :             if (!emit2(JSOP_PICK, 3))                                    // NEXT ITER ARRAY INDEX
   10255             :                 return false;
   10256         242 :             if (!emitSpread(allowSelfHostedIter))                        // ARRAY INDEX
   10257             :                 return false;
   10258        4515 :         } else if (afterSpread) {
   10259           0 :             if (!emit1(JSOP_INITELEM_INC))
   10260             :                 return false;
   10261             :         } else {
   10262           0 :             if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index))
   10263             :                 return false;
   10264             :         }
   10265             :     }
   10266           0 :     MOZ_ASSERT(index == count);
   10267        2693 :     if (afterSpread) {
   10268         224 :         if (!emit1(JSOP_POP))                                            // ARRAY
   10269             :             return false;
   10270             :     }
   10271             :     return true;
   10272             : }
   10273             : 
   10274             : static inline JSOp
   10275        6481 : UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk)
   10276             : {
   10277           0 :     switch (pnk) {
   10278             :       case ParseNodeKind::Throw: return JSOP_THROW;
   10279           0 :       case ParseNodeKind::Void: return JSOP_VOID;
   10280        5055 :       case ParseNodeKind::Not: return JSOP_NOT;
   10281           0 :       case ParseNodeKind::BitNot: return JSOP_BITNOT;
   10282           1 :       case ParseNodeKind::Pos: return JSOP_POS;
   10283           0 :       case ParseNodeKind::Neg: return JSOP_NEG;
   10284           0 :       default: MOZ_CRASH("unexpected unary op");
   10285             :     }
   10286             : }
   10287             : 
   10288             : bool
   10289           0 : BytecodeEmitter::emitUnary(ParseNode* pn)
   10290             : {
   10291        6481 :     if (!updateSourceCoordNotes(pn->pn_pos.begin))
   10292             :         return false;
   10293        6481 :     if (!emitTree(pn->pn_kid))
   10294             :         return false;
   10295        6481 :     return emit1(UnaryOpParseNodeKindToJSOp(pn->getKind()));
   10296             : }
   10297             : 
   10298             : bool
   10299         713 : BytecodeEmitter::emitTypeof(ParseNode* node, JSOp op)
   10300             : {
   10301         713 :     MOZ_ASSERT(op == JSOP_TYPEOF || op == JSOP_TYPEOFEXPR);
   10302             : 
   10303         713 :     if (!updateSourceCoordNotes(node->pn_pos.begin))
   10304             :         return false;
   10305             : 
   10306         713 :     if (!emitTree(node->pn_kid))
   10307             :         return false;
   10308             : 
   10309           0 :     return emit1(op);
   10310             : }
   10311             : 
   10312             : bool
   10313           0 : BytecodeEmitter::emitFunctionFormalParametersAndBody(ParseNode *pn)
   10314             : {
   10315           0 :     MOZ_ASSERT(pn->isKind(ParseNodeKind::ParamsBody));
   10316             : 
   10317           0 :     ParseNode* funBody = pn->last();
   10318       13041 :     FunctionBox* funbox = sc->asFunctionBox();
   10319             : 
   10320           0 :     TDZCheckCache tdzCache(this);
   10321             : 
   10322       13041 :     if (funbox->hasParameterExprs) {
   10323           0 :         EmitterScope funEmitterScope(this);
   10324         471 :         if (!funEmitterScope.enterFunction(this, funbox))
   10325             :             return false;
   10326             : 
   10327           0 :         if (!emitInitializeFunctionSpecialNames())
   10328             :             return false;
   10329             : 
   10330           0 :         if (!emitFunctionFormalParameters(pn))
   10331             :             return false;
   10332             : 
   10333             :         {
   10334           0 :             Maybe<EmitterScope> extraVarEmitterScope;
   10335             : 
   10336           0 :             if (funbox->hasExtraBodyVarScope()) {
   10337           0 :                 extraVarEmitterScope.emplace(this);
   10338           0 :                 if (!extraVarEmitterScope->enterFunctionExtraBodyVar(this, funbox))
   10339           0 :                     return false;
   10340             : 
   10341             :                 // After emitting expressions for all parameters, copy over any
   10342             :                 // formal parameters which have been redeclared as vars. For
   10343             :                 // example, in the following, the var y in the body scope is 42:
   10344             :                 //
   10345             :                 //   function f(x, y = 42) { var y; }
   10346             :                 //
   10347         177 :                 RootedAtom name(cx);
   10348         144 :                 if (funbox->extraVarScopeBindings() && funbox->functionScopeBindings()) {
   10349         286 :                     for (BindingIter bi(*funbox->functionScopeBindings(), true); bi; bi++) {
   10350         182 :                         name = bi.name();
   10351             : 
   10352             :                         // There may not be a var binding of the same name.
   10353         455 :                         if (!locationOfNameBoundInScope(name, extraVarEmitterScope.ptr()))
   10354           0 :                             continue;
   10355             : 
   10356             :                         // The '.this' and '.generator' function special
   10357             :                         // bindings should never appear in the extra var
   10358             :                         // scope. 'arguments', however, may.
   10359           0 :                         MOZ_ASSERT(name != cx->names().dotThis &&
   10360             :                                    name != cx->names().dotGenerator);
   10361             : 
   10362           0 :                         NameLocation paramLoc = *locationOfNameBoundInScope(name, &funEmitterScope);
   10363             :                         auto emitRhs = [&name, &paramLoc](BytecodeEmitter* bce,
   10364             :                                                           const NameLocation&, bool)
   10365           0 :                         {
   10366           0 :                             return bce->emitGetNameAtLocation(name, paramLoc);
   10367           0 :                         };
   10368             : 
   10369           0 :                         if (!emitInitializeName(name, emitRhs))
   10370           0 :                             return false;
   10371           0 :                         if (!emit1(JSOP_POP))
   10372             :                             return false;
   10373             :                     }
   10374             :                 }
   10375             :             }
   10376             : 
   10377         471 :             if (!emitFunctionBody(funBody))
   10378             :                 return false;
   10379             : 
   10380           0 :             if (extraVarEmitterScope && !extraVarEmitterScope->leave(this))
   10381             :                 return false;
   10382             :         }
   10383             : 
   10384         471 :         return funEmitterScope.leave(this);
   10385             :     }
   10386             : 
   10387             :     // No parameter expressions. Enter the function body scope and emit
   10388             :     // everything.
   10389             :     //
   10390             :     // One caveat is that Debugger considers ops in the prologue to be
   10391             :     // unreachable (i.e. cannot set a breakpoint on it). If there are no
   10392             :     // parameter exprs, any unobservable environment ops (like pushing the
   10393             :     // call object, setting '.this', etc) need to go in the prologue, else it
   10394             :     // messes up breakpoint tests.
   10395           0 :     EmitterScope emitterScope(this);
   10396             : 
   10397       12570 :     switchToPrologue();
   10398       12570 :     if (!emitterScope.enterFunction(this, funbox))
   10399             :         return false;
   10400             : 
   10401       12570 :     if (!emitInitializeFunctionSpecialNames())
   10402             :         return false;
   10403       12570 :     switchToMain();
   10404             : 
   10405           0 :     if (!emitFunctionFormalParameters(pn))
   10406             :         return false;
   10407             : 
   10408       12570 :     if (!emitFunctionBody(funBody))
   10409             :         return false;
   10410             : 
   10411           0 :     return emitterScope.leave(this);
   10412             : }
   10413             : 
   10414             : bool
   10415       13041 : BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
   10416             : {
   10417       13041 :     ParseNode* funBody = pn->last();
   10418       13041 :     FunctionBox* funbox = sc->asFunctionBox();
   10419           0 :     EmitterScope* funScope = innermostEmitterScope();
   10420             : 
   10421       13041 :     bool hasParameterExprs = funbox->hasParameterExprs;
   10422           0 :     bool hasRest = funbox->hasRest();
   10423             : 
   10424       13041 :     uint16_t argSlot = 0;
   10425           0 :     for (ParseNode* arg = pn->pn_head; arg != funBody; arg = arg->pn_next, argSlot++) {
   10426       13507 :         ParseNode* bindingElement = arg;
   10427       13507 :         ParseNode* initializer = nullptr;
   10428           0 :         if (arg->isKind(ParseNodeKind::Assign)) {
   10429         543 :             bindingElement = arg->pn_left;
   10430         543 :             initializer = arg->pn_right;
   10431             :         }
   10432             : 
   10433             :         // Left-hand sides are either simple names or destructuring patterns.
   10434           0 :         MOZ_ASSERT(bindingElement->isKind(ParseNodeKind::Name) ||
   10435             :                    bindingElement->isKind(ParseNodeKind::Array) ||
   10436             :                    bindingElement->isKind(ParseNodeKind::Object));
   10437             : 
   10438             :         // The rest parameter doesn't have an initializer.
   10439       13507 :         bool isRest = hasRest && arg->pn_next == funBody;
   10440           0 :         MOZ_ASSERT_IF(isRest, !initializer);
   10441             : 
   10442       13507 :         bool isDestructuring = !bindingElement->isKind(ParseNodeKind::Name);
   10443             : 
   10444             :         // ES 14.1.19 says if BindingElement contains an expression in the
   10445             :         // production FormalParameter : BindingElement, it is evaluated in a
   10446             :         // new var environment. This is needed to prevent vars from escaping
   10447             :         // direct eval in parameter expressions.
   10448           0 :         Maybe<EmitterScope> paramExprVarScope;
   10449       13507 :         if (funbox->hasDirectEvalInParameterExpr && (isDestructuring || initializer)) {
   10450           0 :             paramExprVarScope.emplace(this);
   10451           0 :             if (!paramExprVarScope->enterParameterExpressionVar(this))
   10452           0 :                 return false;
   10453             :         }
   10454             : 
   10455             :         // First push the RHS if there is a default expression or if it is
   10456             :         // rest.
   10457             : 
   10458       13507 :         if (initializer) {
   10459             :             // If we have an initializer, emit the initializer and assign it
   10460             :             // to the argument slot. TDZ is taken care of afterwards.
   10461         543 :             MOZ_ASSERT(hasParameterExprs);
   10462         543 :             if (!emitArgOp(JSOP_GETARG, argSlot))
   10463           0 :                 return false;
   10464         543 :             if (!emit1(JSOP_DUP))
   10465             :                 return false;
   10466         543 :             if (!emit1(JSOP_UNDEFINED))
   10467             :                 return false;
   10468           0 :             if (!emit1(JSOP_STRICTEQ))
   10469             :                 return false;
   10470             :             // Emit source note to enable Ion compilation.
   10471         543 :             if (!newSrcNote(SRC_IF))
   10472             :                 return false;
   10473         543 :             JumpList jump;
   10474         543 :             if (!emitJump(JSOP_IFEQ, &jump))
   10475             :                 return false;
   10476           0 :             if (!emit1(JSOP_POP))
   10477             :                 return false;
   10478           0 :             if (!emitInitializerInBranch(initializer, bindingElement))
   10479             :                 return false;
   10480           0 :             if (!emitJumpTargetAndPatch(jump))
   10481             :                 return false;
   10482       12964 :         } else if (isRest) {
   10483         151 :             if (!emit1(JSOP_REST))
   10484             :                 return false;
   10485             :             checkTypeSet(JSOP_REST);
   10486             :         }
   10487             : 
   10488             :         // Initialize the parameter name.
   10489             : 
   10490       13507 :         if (isDestructuring) {
   10491             :             // If we had an initializer or the rest parameter, the value is
   10492             :             // already on the stack.
   10493         108 :             if (!initializer && !isRest && !emitArgOp(JSOP_GETARG, argSlot))
   10494             :                 return false;
   10495             : 
   10496             :             // If there's an parameter expression var scope, the destructuring
   10497             :             // declaration needs to initialize the name in the function scope,
   10498             :             // which is not the innermost scope.
   10499         108 :             if (!emitDestructuringOps(bindingElement,
   10500             :                                       paramExprVarScope
   10501             :                                       ? DestructuringFormalParameterInVarScope
   10502         108 :                                       : DestructuringDeclaration))
   10503             :             {
   10504             :                 return false;
   10505             :             }
   10506             : 
   10507         108 :             if (!emit1(JSOP_POP))
   10508             :                 return false;
   10509             :         } else {
   10510       26798 :             RootedAtom paramName(cx, bindingElement->name());
   10511           0 :             NameLocation paramLoc = *locationOfNameBoundInScope(paramName, funScope);
   10512             : 
   10513           0 :             if (hasParameterExprs) {
   10514             :                 auto emitRhs = [argSlot, initializer, isRest](BytecodeEmitter* bce,
   10515             :                                                               const NameLocation&, bool)
   10516        1112 :                 {
   10517             :                     // If we had an initializer or a rest parameter, the value is
   10518             :                     // already on the stack.
   10519           0 :                     if (!initializer && !isRest)
   10520         574 :                         return bce->emitArgOp(JSOP_GETARG, argSlot);
   10521             :                     return true;
   10522           0 :                 };
   10523             : 
   10524        1112 :                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, emitRhs, true))
   10525           0 :                     return false;
   10526        1112 :                 if (!emit1(JSOP_POP))
   10527             :                     return false;
   10528       12287 :             } else if (isRest) {
   10529             :                 // The rest value is already on top of the stack.
   10530             :                 auto nop = [](BytecodeEmitter*, const NameLocation&, bool) {
   10531             :                     return true;
   10532             :                 };
   10533             : 
   10534           0 :                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, nop, true))
   10535             :                     return false;
   10536         151 :                 if (!emit1(JSOP_POP))
   10537             :                     return false;
   10538             :             }
   10539             :         }
   10540             : 
   10541       13507 :         if (paramExprVarScope) {
   10542           0 :             if (!paramExprVarScope->leave(this))
   10543             :                 return false;
   10544             :         }
   10545             :     }
   10546             : 
   10547             :     return true;
   10548             : }
   10549             : 
   10550             : bool
   10551           0 : BytecodeEmitter::emitInitializeFunctionSpecialNames()
   10552             : {
   10553       13041 :     FunctionBox* funbox = sc->asFunctionBox();
   10554             : 
   10555             :     auto emitInitializeFunctionSpecialName = [](BytecodeEmitter* bce, HandlePropertyName name,
   10556        6527 :                                                 JSOp op)
   10557             :     {
   10558             :         // A special name must be slotful, either on the frame or on the
   10559             :         // call environment.
   10560       19581 :         MOZ_ASSERT(bce->lookupName(name).hasKnownSlot());
   10561             : 
   10562             :         auto emitInitial = [op](BytecodeEmitter* bce, const NameLocation&, bool) {
   10563             :             return bce->emit1(op);
   10564           0 :         };
   10565             : 
   10566           0 :         if (!bce->emitInitializeName(name, emitInitial))
   10567             :             return false;
   10568           0 :         if (!bce->emit1(JSOP_POP))
   10569             :             return false;
   10570             : 
   10571             :         return true;
   10572             :     };
   10573             : 
   10574             :     // Do nothing if the function doesn't have an arguments binding.
   10575       13041 :     if (funbox->argumentsHasLocalBinding()) {
   10576           0 :         if (!emitInitializeFunctionSpecialName(this, cx->names().arguments, JSOP_ARGUMENTS))
   10577             :             return false;
   10578             :     }
   10579             : 
   10580             :     // Do nothing if the function doesn't have a this-binding (this
   10581             :     // happens for instance if it doesn't use this/eval or if it's an
   10582             :     // arrow function).
   10583           0 :     if (funbox->hasThisBinding()) {
   10584           0 :         if (!emitInitializeFunctionSpecialName(this, cx->names().dotThis, JSOP_FUNCTIONTHIS))
   10585             :             return false;
   10586             :     }
   10587             : 
   10588             :     return true;
   10589             : }
   10590             : 
   10591             : bool
   10592           0 : BytecodeEmitter::emitFunctionBody(ParseNode* funBody)
   10593             : {
   10594       13041 :     FunctionBox* funbox = sc->asFunctionBox();
   10595             : 
   10596       13041 :     if (!emitTree(funBody))
   10597             :         return false;
   10598             : 
   10599           0 :     if (funbox->needsFinalYield()) {
   10600             :         // If we fall off the end of a generator, do a final yield.
   10601           0 :         bool needsIteratorResult = funbox->needsIteratorResult();
   10602           0 :         if (needsIteratorResult) {
   10603           0 :             if (!emitPrepareIteratorResult())
   10604             :                 return false;
   10605             :         }
   10606             : 
   10607         729 :         if (!emit1(JSOP_UNDEFINED))
   10608             :             return false;
   10609             : 
   10610         729 :         if (needsIteratorResult) {
   10611          40 :             if (!emitFinishIteratorResult(true))
   10612             :                 return false;
   10613             :         }
   10614             : 
   10615         729 :         if (!emit1(JSOP_SETRVAL))
   10616             :             return false;
   10617             : 
   10618         729 :         if (!emitGetDotGeneratorInInnermostScope())
   10619             :             return false;
   10620             : 
   10621             :         // No need to check for finally blocks, etc as in EmitReturn.
   10622         729 :         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
   10623             :             return false;
   10624             :     } else {
   10625             :         // Non-generator functions just return |undefined|. The
   10626             :         // JSOP_RETRVAL emitted below will do that, except if the
   10627             :         // script has a finally block: there can be a non-undefined
   10628             :         // value in the return value slot. Make sure the return value
   10629             :         // is |undefined|.
   10630       12312 :         if (hasTryFinally) {
   10631          54 :             if (!emit1(JSOP_UNDEFINED))
   10632             :                 return false;
   10633          54 :             if (!emit1(JSOP_SETRVAL))
   10634             :                 return false;
   10635             :         }
   10636             :     }
   10637             : 
   10638       13041 :     if (funbox->isDerivedClassConstructor()) {
   10639          79 :         if (!emitCheckDerivedClassConstructorReturn())
   10640             :             return false;
   10641             :     }
   10642             : 
   10643             :     return true;
   10644             : }
   10645             : 
   10646             : bool
   10647           0 : BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
   10648             : {
   10649             :     // The caller has pushed the RHS to the top of the stack. Assert that the
   10650             :     // name is lexical and no BIND[G]NAME ops were emitted.
   10651        1359 :     auto assertLexical = [](BytecodeEmitter*, const NameLocation& loc, bool emittedBindOp) {
   10652        1359 :         MOZ_ASSERT(loc.isLexical());
   10653        1359 :         MOZ_ASSERT(!emittedBindOp);
   10654        1359 :         return true;
   10655             :     };
   10656           0 :     return emitInitializeName(pn, assertLexical);
   10657             : }
   10658             : 
   10659             : // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
   10660             : // (BindingClassDeclarationEvaluation).
   10661             : bool
   10662           0 : BytecodeEmitter::emitClass(ParseNode* pn)
   10663             : {
   10664         212 :     ClassNode& classNode = pn->as<ClassNode>();
   10665             : 
   10666           0 :     ClassNames* names = classNode.names();
   10667             : 
   10668           0 :     ParseNode* heritageExpression = classNode.heritage();
   10669             : 
   10670           0 :     ParseNode* classMethods = classNode.methodList();
   10671         212 :     ParseNode* constructor = nullptr;
   10672         419 :     for (ParseNode* mn = classMethods->pn_head; mn; mn = mn->pn_next) {
   10673         371 :         ClassMethod& method = mn->as<ClassMethod>();
   10674           0 :         ParseNode& methodName = method.name();
   10675        1083 :         if (!method.isStatic() &&
   10676           0 :             (methodName.isKind(ParseNodeKind::ObjectPropertyName) ||
   10677         712 :              methodName.isKind(ParseNodeKind::String)) &&
   10678           0 :             methodName.pn_atom == cx->names().constructor)
   10679             :         {
   10680         164 :             constructor = &method.method();
   10681         164 :             break;
   10682             :         }
   10683             :     }
   10684             : 
   10685         424 :     bool savedStrictness = sc->setLocalStrictMode(true);
   10686             : 
   10687         424 :     Maybe<TDZCheckCache> tdzCache;
   10688           0 :     Maybe<EmitterScope> emitterScope;
   10689         212 :     if (names) {
   10690         192 :         tdzCache.emplace(this);
   10691         192 :         emitterScope.emplace(this);
   10692           0 :         if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode.scopeBindings()))
   10693             :             return false;
   10694             :     }
   10695             : 
   10696             :     // Pseudocode for class declarations:
   10697             :     //
   10698             :     //     class extends BaseExpression {
   10699             :     //       constructor() { ... }
   10700             :     //       ...
   10701             :     //       }
   10702             :     //
   10703             :     //
   10704             :     //   if defined <BaseExpression> {
   10705             :     //     let heritage = BaseExpression;
   10706             :     //
   10707             :     //     if (heritage !== null) {
   10708             :     //       funProto = heritage;
   10709             :     //       objProto = heritage.prototype;
   10710             :     //     } else {
   10711             :     //       funProto = %FunctionPrototype%;
   10712             :     //       objProto = null;
   10713             :     //     }
   10714             :     //   } else {
   10715             :     //     objProto = %ObjectPrototype%;
   10716             :     //   }
   10717             :     //
   10718             :     //   let homeObject = ObjectCreate(objProto);
   10719             :     //
   10720             :     //   if defined <constructor> {
   10721             :     //     if defined <BaseExpression> {
   10722             :     //       cons = DefineMethod(<constructor>, proto=homeObject, funProto=funProto);
   10723             :     //     } else {
   10724             :     //       cons = DefineMethod(<constructor>, proto=homeObject);
   10725             :     //     }
   10726             :     //   } else {
   10727             :     //     if defined <BaseExpression> {
   10728             :     //       cons = DefaultDerivedConstructor(proto=homeObject, funProto=funProto);
   10729             :     //     } else {
   10730             :     //       cons = DefaultConstructor(proto=homeObject);
   10731             :     //     }
   10732             :     //   }
   10733             :     //
   10734             :     //   cons.prototype = homeObject;
   10735             :     //   homeObject.constructor = cons;
   10736             :     //
   10737             :     //   EmitPropertyList(...)
   10738             : 
   10739             :     // This is kind of silly. In order to the get the home object defined on
   10740             :     // the constructor, we have to make it second, but we want the prototype
   10741             :     // on top for EmitPropertyList, because we expect static properties to be
   10742             :     // rarer. The result is a few more swaps than we would like. Such is life.
   10743         212 :     if (heritageExpression) {
   10744           0 :         InternalIfEmitter ifThenElse(this);
   10745             : 
   10746         116 :         if (!emitTree(heritageExpression))                      // ... HERITAGE
   10747           0 :             return false;
   10748             : 
   10749             :         // Heritage must be null or a non-generator constructor
   10750         116 :         if (!emit1(JSOP_CHECKCLASSHERITAGE))                    // ... HERITAGE
   10751             :             return false;
   10752             : 
   10753             :         // [IF] (heritage !== null)
   10754         116 :         if (!emit1(JSOP_DUP))                                   // ... HERITAGE HERITAGE
   10755             :             return false;
   10756         116 :         if (!emit1(JSOP_NULL))                                  // ... HERITAGE HERITAGE NULL
   10757             :             return false;
   10758         116 :         if (!emit1(JSOP_STRICTNE))                              // ... HERITAGE NE
   10759             :             return false;
   10760             : 
   10761             :         // [THEN] funProto = heritage, objProto = heritage.prototype
   10762           0 :         if (!ifThenElse.emitThenElse())
   10763             :             return false;
   10764         116 :         if (!emit1(JSOP_DUP))                                   // ... HERITAGE HERITAGE
   10765             :             return false;
   10766         348 :         if (!emitAtomOp(cx->names().prototype, JSOP_GETPROP))   // ... HERITAGE PROTO
   10767             :             return false;
   10768             : 
   10769             :         // [ELSE] funProto = %FunctionPrototype%, objProto = null
   10770         116 :         if (!ifThenElse.emitElse())
   10771             :             return false;
   10772         116 :         if (!emit1(JSOP_POP))                                   // ...
   10773             :             return false;
   10774           0 :         if (!emit2(JSOP_BUILTINPROTO, JSProto_Function))        // ... PROTO
   10775             :             return false;
   10776         116 :         if (!emit1(JSOP_NULL))                                  // ... PROTO NULL
   10777             :             return false;
   10778             : 
   10779             :         // [ENDIF]
   10780           0 :         if (!ifThenElse.emitEnd())
   10781             :             return false;
   10782             : 
   10783         116 :         if (!emit1(JSOP_OBJWITHPROTO))                          // ... HERITAGE HOMEOBJ
   10784             :             return false;
   10785           0 :         if (!emit1(JSOP_SWAP))                                  // ... HOMEOBJ HERITAGE
   10786             :             return false;
   10787             :     } else {
   10788          96 :         if (!emitNewInit(JSProto_Object))                       // ... HOMEOBJ
   10789             :             return false;
   10790             :     }
   10791             : 
   10792             :     // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
   10793             :     // is not used, an implicit value of %FunctionPrototype% is implied.
   10794             : 
   10795           0 :     if (constructor) {
   10796         164 :         if (!emitFunction(constructor, !!heritageExpression))   // ... HOMEOBJ CONSTRUCTOR
   10797             :             return false;
   10798         328 :         if (constructor->pn_funbox->needsHomeObject()) {
   10799           0 :             if (!emit2(JSOP_INITHOMEOBJECT, 0))                 // ... HOMEOBJ CONSTRUCTOR
   10800             :                 return false;
   10801             :         }
   10802             :     } else {
   10803             :         // In the case of default class constructors, emit the start and end
   10804             :         // offsets in the source buffer as source notes so that when we
   10805             :         // actually make the constructor during execution, we can give it the
   10806             :         // correct toString output.
   10807          48 :         ptrdiff_t classStart = ptrdiff_t(pn->pn_pos.begin);
   10808          48 :         ptrdiff_t classEnd = ptrdiff_t(pn->pn_pos.end);
   10809           0 :         if (!newSrcNote3(SRC_CLASS_SPAN, classStart, classEnd))
   10810             :             return false;
   10811             : 
   10812          64 :         JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;
   10813          48 :         if (heritageExpression) {
   10814           0 :             if (!emitAtomOp(name, JSOP_DERIVEDCONSTRUCTOR))     // ... HOMEOBJ CONSTRUCTOR
   10815             :                 return false;
   10816             :         } else {
   10817          11 :             if (!emitAtomOp(name, JSOP_CLASSCONSTRUCTOR))       // ... HOMEOBJ CONSTRUCTOR
   10818             :                 return false;
   10819             :         }
   10820             :     }
   10821             : 
   10822         212 :     if (!emit1(JSOP_SWAP))                                      // ... CONSTRUCTOR HOMEOBJ
   10823             :         return false;
   10824             : 
   10825         212 :     if (!emit1(JSOP_DUP2))                                          // ... CONSTRUCTOR HOMEOBJ CONSTRUCTOR HOMEOBJ
   10826             :         return false;
   10827         636 :     if (!emitAtomOp(cx->names().prototype, JSOP_INITLOCKEDPROP))    // ... CONSTRUCTOR HOMEOBJ CONSTRUCTOR
   10828             :         return false;
   10829         636 :     if (!emitAtomOp(cx->names().constructor, JSOP_INITHIDDENPROP))  // ... CONSTRUCTOR HOMEOBJ
   10830             :         return false;
   10831             : 
   10832         636 :     RootedPlainObject obj(cx);
   10833         212 :     if (!emitPropertyList(classMethods, &obj, ClassBody))       // ... CONSTRUCTOR HOMEOBJ
   10834             :         return false;
   10835             : 
   10836           0 :     if (!emit1(JSOP_POP))                                       // ... CONSTRUCTOR
   10837             :         return false;
   10838             : 
   10839         212 :     if (names) {
   10840         192 :         ParseNode* innerName = names->innerBinding();
   10841           0 :         if (!emitLexicalInitialization(innerName))              // ... CONSTRUCTOR
   10842             :             return false;
   10843             : 
   10844             :         // Pop the inner scope.
   10845         192 :         if (!emitterScope->leave(this))
   10846             :             return false;
   10847         192 :         emitterScope.reset();
   10848             : 
   10849         192 :         ParseNode* outerName = names->outerBinding();
   10850         192 :         if (outerName) {
   10851           0 :             if (!emitLexicalInitialization(outerName))          // ... CONSTRUCTOR
   10852             :                 return false;
   10853             :             // Only class statements make outer bindings, and they do not leave
   10854             :             // themselves on the stack.
   10855         165 :             if (!emit1(JSOP_POP))                               // ...
   10856             :                 return false;
   10857             :         }
   10858             :     }
   10859             : 
   10860             :     // The CONSTRUCTOR is left on stack if this is an expression.
   10861             : 
   10862         424 :     MOZ_ALWAYS_TRUE(sc->setLocalStrictMode(savedStrictness));
   10863             : 
   10864             :     return true;
   10865             : }
   10866             : 
   10867             : bool
   10868           0 : BytecodeEmitter::emitExportDefault(ParseNode* pn)
   10869             : {
   10870           0 :     if (!emitTree(pn->pn_left))
   10871             :         return false;
   10872             : 
   10873           0 :     if (pn->pn_right) {
   10874           0 :         if (!emitLexicalInitialization(pn->pn_right))
   10875             :             return false;
   10876             : 
   10877           0 :         if (pn->pn_left->isDirectRHSAnonFunction()) {
   10878           0 :             HandlePropertyName name = cx->names().default_;
   10879           0 :             if (!setOrEmitSetFunName(pn->pn_left, name))
   10880             :                 return false;
   10881             :         }
   10882             : 
   10883           0 :         if (!emit1(JSOP_POP))
   10884             :             return false;
   10885             :     }
   10886             : 
   10887             :     return true;
   10888             : }
   10889             : 
   10890             : bool
   10891           0 : BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
   10892             :                           EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */)
   10893             : {
   10894      475431 :     if (!CheckRecursionLimit(cx))
   10895             :         return false;
   10896             : 
   10897      475437 :     EmitLevelManager elm(this);
   10898             : 
   10899             :     /* Emit notes to tell the current bytecode's source line number.
   10900             :        However, a couple trees require special treatment; see the
   10901             :        relevant emitter functions for details. */
   10902      475437 :     if (emitLineNote == EMIT_LINENOTE && !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
   10903      454948 :         if (!updateLineNumberNotes(pn->pn_pos.begin))
   10904             :             return false;
   10905             :     }
   10906             : 
   10907      475411 :     switch (pn->getKind()) {
   10908             :       case ParseNodeKind::Function:
   10909       12272 :         if (!emitFunction(pn))
   10910             :             return false;
   10911             :         break;
   10912             : 
   10913             :       case ParseNodeKind::ParamsBody:
   10914       13041 :         if (!emitFunctionFormalParametersAndBody(pn))
   10915             :             return false;
   10916             :         break;
   10917             : 
   10918             :       case ParseNodeKind::If:
   10919       12834 :         if (!emitIf(pn))
   10920             :             return false;
   10921             :         break;
   10922             : 
   10923             :       case ParseNodeKind::Switch:
   10924           0 :         if (!emitSwitch(pn))
   10925             :             return false;
   10926             :         break;
   10927             : 
   10928             :       case ParseNodeKind::While:
   10929           0 :         if (!emitWhile(pn))
   10930             :             return false;
   10931             :         break;
   10932             : 
   10933             :       case ParseNodeKind::DoWhile:
   10934           0 :         if (!emitDo(pn))
   10935             :             return false;
   10936             :         break;
   10937             : 
   10938             :       case ParseNodeKind::For:
   10939         188 :         if (!emitFor(pn))
   10940             :             return false;
   10941             :         break;
   10942             : 
   10943             :       case ParseNodeKind::Break:
   10944        1260 :         if (!emitBreak(pn->as<BreakStatement>().label()))
   10945             :             return false;
   10946             :         break;
   10947             : 
   10948             :       case ParseNodeKind::Continue:
   10949         265 :         if (!emitContinue(pn->as<ContinueStatement>().label()))
   10950             :             return false;
   10951             :         break;
   10952             : 
   10953             :       case ParseNodeKind::With:
   10954           0 :         if (!emitWith(pn))
   10955             :             return false;
   10956             :         break;
   10957             : 
   10958             :       case ParseNodeKind::Try:
   10959        1074 :         if (!emitTry(pn))
   10960             :             return false;
   10961             :         break;
   10962             : 
   10963             :       case ParseNodeKind::Catch:
   10964        1003 :         if (!emitCatch(pn))
   10965             :             return false;
   10966             :         break;
   10967             : 
   10968             :       case ParseNodeKind::Var:
   10969        3527 :         if (!emitDeclarationList(pn))
   10970             :             return false;
   10971             :         break;
   10972             : 
   10973             :       case ParseNodeKind::Return:
   10974       11321 :         if (!emitReturn(pn))
   10975             :             return false;
   10976             :         break;
   10977             : 
   10978             :       case ParseNodeKind::YieldStar:
   10979           9 :         if (!emitYieldStar(pn->pn_kid))
   10980             :             return false;
   10981             :         break;
   10982             : 
   10983             :       case ParseNodeKind::Generator:
   10984         729 :         if (!emit1(JSOP_GENERATOR))
   10985             :             return false;
   10986             :         break;
   10987             : 
   10988             :       case ParseNodeKind::InitialYield:
   10989         729 :         if (!emitInitialYield(pn))
   10990             :             return false;
   10991             :         break;
   10992             : 
   10993             :       case ParseNodeKind::Yield:
   10994          44 :         if (!emitYield(pn))
   10995             :             return false;
   10996             :         break;
   10997             : 
   10998             :       case ParseNodeKind::Await:
   10999        1222 :         if (!emitAwaitInInnermostScope(pn))
   11000             :             return false;
   11001             :         break;
   11002             : 
   11003             :       case ParseNodeKind::StatementList:
   11004       30549 :         if (!emitStatementList(pn))
   11005             :             return false;
   11006             :         break;
   11007             : 
   11008             :       case ParseNodeKind::EmptyStatement:
   11009             :         break;
   11010             : 
   11011             :       case ParseNodeKind::ExpressionStatement:
   11012       32140 :         if (!emitExpressionStatement(pn))
   11013             :             return false;
   11014             :         break;
   11015             : 
   11016             :       case ParseNodeKind::Label:
   11017           0 :         if (!emitLabeledStatement(&pn->as<LabeledStatement>()))
   11018             :             return false;
   11019             :         break;
   11020             : 
   11021             :       case ParseNodeKind::Comma:
   11022           8 :         if (!emitSequenceExpr(pn, valueUsage))
   11023             :             return false;
   11024             :         break;
   11025             : 
   11026             :       case ParseNodeKind::Assign:
   11027             :       case ParseNodeKind::AddAssign:
   11028             :       case ParseNodeKind::SubAssign:
   11029             :       case ParseNodeKind::BitOrAssign:
   11030             :       case ParseNodeKind::BitXorAssign:
   11031             :       case ParseNodeKind::BitAndAssign:
   11032             :       case ParseNodeKind::LshAssign:
   11033             :       case ParseNodeKind::RshAssign:
   11034             :       case ParseNodeKind::UrshAssign:
   11035             :       case ParseNodeKind::MulAssign:
   11036             :       case ParseNodeKind::DivAssign:
   11037             :       case ParseNodeKind::ModAssign:
   11038             :       case ParseNodeKind::PowAssign:
   11039       12891 :         if (!emitAssignment(pn->pn_left, pn->getKind(), pn->pn_right))
   11040             :             return false;
   11041             :         break;
   11042             : 
   11043             :       case ParseNodeKind::Conditional:
   11044         971 :         if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
   11045             :             return false;
   11046             :         break;
   11047             : 
   11048             :       case ParseNodeKind::Or:
   11049             :       case ParseNodeKind::And:
   11050           0 :         if (!emitLogical(pn))
   11051             :             return false;
   11052             :         break;
   11053             : 
   11054             :       case ParseNodeKind::Add:
   11055             :       case ParseNodeKind::Sub:
   11056             :       case ParseNodeKind::BitOr:
   11057             :       case ParseNodeKind::BitXor:
   11058             :       case ParseNodeKind::BitAnd:
   11059             :       case ParseNodeKind::StrictEq:
   11060             :       case ParseNodeKind::Eq:
   11061             :       case ParseNodeKind::StrictNe:
   11062             :       case ParseNodeKind::Ne:
   11063             :       case ParseNodeKind::Lt:
   11064             :       case ParseNodeKind::Le:
   11065             :       case ParseNodeKind::Gt:
   11066             :       case ParseNodeKind::Ge:
   11067             :       case ParseNodeKind::In:
   11068             :       case ParseNodeKind::InstanceOf:
   11069             :       case ParseNodeKind::Lsh:
   11070             :       case ParseNodeKind::Rsh:
   11071             :       case ParseNodeKind::Ursh:
   11072             :       case ParseNodeKind::Star:
   11073             :       case ParseNodeKind::Div:
   11074             :       case ParseNodeKind::Mod:
   11075       11850 :         if (!emitLeftAssociative(pn))
   11076             :             return false;
   11077             :         break;
   11078             : 
   11079             :       case ParseNodeKind::Pow:
   11080           0 :         if (!emitRightAssociative(pn))
   11081             :             return false;
   11082             :         break;
   11083             : 
   11084             :       case ParseNodeKind::Pipeline:
   11085           0 :         if (!emitPipeline(pn))
   11086             :             return false;
   11087             :         break;
   11088             : 
   11089             :       case ParseNodeKind::TypeOfName:
   11090         553 :         if (!emitTypeof(pn, JSOP_TYPEOF))
   11091             :             return false;
   11092             :         break;
   11093             : 
   11094             :       case ParseNodeKind::TypeOfExpr:
   11095           0 :         if (!emitTypeof(pn, JSOP_TYPEOFEXPR))
   11096             :             return false;
   11097             :         break;
   11098             : 
   11099             :       case ParseNodeKind::Throw:
   11100             :       case ParseNodeKind::Void:
   11101             :       case ParseNodeKind::Not:
   11102             :       case ParseNodeKind::BitNot:
   11103             :       case ParseNodeKind::Pos:
   11104             :       case ParseNodeKind::Neg:
   11105        6481 :         if (!emitUnary(pn))
   11106             :             return false;
   11107             :         break;
   11108             : 
   11109             :       case ParseNodeKind::PreIncrement:
   11110             :       case ParseNodeKind::PreDecrement:
   11111             :       case ParseNodeKind::PostIncrement:
   11112             :       case ParseNodeKind::PostDecrement:
   11113         648 :         if (!emitIncOrDec(pn))
   11114             :             return false;
   11115             :         break;
   11116             : 
   11117             :       case ParseNodeKind::DeleteName:
   11118           0 :         if (!emitDeleteName(pn))
   11119             :             return false;
   11120             :         break;
   11121             : 
   11122             :       case ParseNodeKind::DeleteProp:
   11123         266 :         if (!emitDeleteProperty(pn))
   11124             :             return false;
   11125             :         break;
   11126             : 
   11127             :       case ParseNodeKind::DeleteElem:
   11128          94 :         if (!emitDeleteElement(pn))
   11129             :             return false;
   11130             :         break;
   11131             : 
   11132             :       case ParseNodeKind::DeleteExpr:
   11133           0 :         if (!emitDeleteExpression(pn))
   11134             :             return false;
   11135             :         break;
   11136             : 
   11137             :       case ParseNodeKind::Dot:
   11138       57344 :         if (pn->as<PropertyAccess>().isSuper()) {
   11139          12 :             if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
   11140             :                 return false;
   11141             :         } else {
   11142           0 :             if (!emitPropOp(pn, JSOP_GETPROP))
   11143             :                 return false;
   11144             :         }
   11145             :         break;
   11146             : 
   11147             :       case ParseNodeKind::Elem:
   11148        5094 :         if (pn->as<PropertyByValue>().isSuper()) {
   11149           0 :             if (!emitSuperElemOp(pn, JSOP_GETELEM_SUPER))
   11150             :                 return false;
   11151             :         } else {
   11152        2547 :             if (!emitElemOp(pn, JSOP_GETELEM))
   11153             :                 return false;
   11154             :         }
   11155             :         break;
   11156             : 
   11157             :       case ParseNodeKind::New:
   11158             :       case ParseNodeKind::TaggedTemplate:
   11159             :       case ParseNodeKind::Call:
   11160             :       case ParseNodeKind::SuperCall:
   11161       43830 :         if (!emitCallOrNew(pn, valueUsage))
   11162             :             return false;
   11163             :         break;
   11164             : 
   11165             :       case ParseNodeKind::LexicalScope:
   11166       31777 :         if (!emitLexicalScope(pn))
   11167             :             return false;
   11168             :         break;
   11169             : 
   11170             :       case ParseNodeKind::Const:
   11171             :       case ParseNodeKind::Let:
   11172           0 :         if (!emitDeclarationList(pn))
   11173             :             return false;
   11174             :         break;
   11175             : 
   11176             :       case ParseNodeKind::Import:
   11177           0 :         MOZ_ASSERT(sc->isModuleContext());
   11178             :         break;
   11179             : 
   11180             :       case ParseNodeKind::Export:
   11181           0 :         MOZ_ASSERT(sc->isModuleContext());
   11182           0 :         if (pn->pn_kid->getKind() != ParseNodeKind::ExportSpecList) {
   11183           0 :             if (!emitTree(pn->pn_kid))
   11184             :                 return false;
   11185             :         }
   11186             :         break;
   11187             : 
   11188             :       case ParseNodeKind::ExportDefault:
   11189           0 :         MOZ_ASSERT(sc->isModuleContext());
   11190           0 :         if (!emitExportDefault(pn))
   11191             :             return false;
   11192             :         break;
   11193             : 
   11194             :       case ParseNodeKind::ExportFrom:
   11195           0 :         MOZ_ASSERT(sc->isModuleContext());
   11196             :         break;
   11197             : 
   11198             :       case ParseNodeKind::CallSiteObj:
   11199           0 :         if (!emitCallSiteObject(pn))
   11200             :             return false;
   11201             :         break;
   11202             : 
   11203             :       case ParseNodeKind::Array:
   11204        2700 :         if (!emitArrayLiteral(pn))
   11205             :             return false;
   11206             :         break;
   11207             : 
   11208             :       case ParseNodeKind::Object:
   11209        4660 :         if (!emitObject(pn))
   11210             :             return false;
   11211             :         break;
   11212             : 
   11213             :       case ParseNodeKind::Name:
   11214      119239 :         if (!emitGetName(pn))
   11215             :             return false;
   11216             :         break;
   11217             : 
   11218             :       case ParseNodeKind::TemplateStringList:
   11219           0 :         if (!emitTemplateString(pn))
   11220             :             return false;
   11221             :         break;
   11222             : 
   11223             :       case ParseNodeKind::TemplateString:
   11224             :       case ParseNodeKind::String:
   11225           0 :         if (!emitAtomOp(pn, JSOP_STRING))
   11226             :             return false;
   11227             :         break;
   11228             : 
   11229             :       case ParseNodeKind::Number:
   11230        7716 :         if (!emitNumberOp(pn->pn_dval))
   11231             :             return false;
   11232             :         break;
   11233             : 
   11234             :       case ParseNodeKind::RegExp:
   11235         592 :         if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox())))
   11236             :             return false;
   11237             :         break;
   11238             : 
   11239             :       case ParseNodeKind::True:
   11240             :       case ParseNodeKind::False:
   11241             :       case ParseNodeKind::Null:
   11242             :       case ParseNodeKind::RawUndefined:
   11243           0 :         if (!emit1(pn->getOp()))
   11244             :             return false;
   11245             :         break;
   11246             : 
   11247             :       case ParseNodeKind::This:
   11248           0 :         if (!emitThisLiteral(pn))
   11249             :             return false;
   11250             :         break;
   11251             : 
   11252             :       case ParseNodeKind::Debugger:
   11253           0 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
   11254             :             return false;
   11255           0 :         if (!emit1(JSOP_DEBUGGER))
   11256             :             return false;
   11257             :         break;
   11258             : 
   11259             :       case ParseNodeKind::Class:
   11260           0 :         if (!emitClass(pn))
   11261             :             return false;
   11262             :         break;
   11263             : 
   11264             :       case ParseNodeKind::NewTarget:
   11265           0 :         if (!emit1(JSOP_NEWTARGET))
   11266             :             return false;
   11267             :         break;
   11268             : 
   11269             :       case ParseNodeKind::ImportMeta:
   11270           0 :         if (!emit1(JSOP_IMPORTMETA))
   11271             :             return false;
   11272             :         break;
   11273             : 
   11274             :       case ParseNodeKind::SetThis:
   11275           0 :         if (!emitSetThis(pn))
   11276             :             return false;
   11277             :         break;
   11278             : 
   11279             :       case ParseNodeKind::PosHolder:
   11280           0 :         MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PosHolder");
   11281             : 
   11282             :       default:
   11283           0 :         MOZ_ASSERT(0);
   11284             :     }
   11285             : 
   11286             :     /* bce->emitLevel == 1 means we're last on the stack, so finish up. */
   11287           0 :     if (emitLevel == 1) {
   11288       13449 :         if (!updateSourceCoordNotes(pn->pn_pos.end))
   11289             :             return false;
   11290             :     }
   11291             :     return true;
   11292             : }
   11293             : 
   11294             : bool
   11295        1874 : BytecodeEmitter::emitTreeInBranch(ParseNode* pn,
   11296             :                                   ValueUsage valueUsage /* = ValueUsage::WantValue */)
   11297             : {
   11298             :     // Code that may be conditionally executed always need their own TDZ
   11299             :     // cache.
   11300        3748 :     TDZCheckCache tdzCache(this);
   11301        3748 :     return emitTree(pn, valueUsage);
   11302             : }
   11303             : 
   11304             : static bool
   11305           0 : AllocSrcNote(JSContext* cx, SrcNotesVector& notes, unsigned* index)
   11306             : {
   11307      638368 :     if (!notes.growBy(1)) {
   11308           0 :         ReportOutOfMemory(cx);
   11309           0 :         return false;
   11310             :     }
   11311             : 
   11312           0 :     *index = notes.length() - 1;
   11313      638398 :     return true;
   11314             : }
   11315             : 
   11316             : bool
   11317           1 : BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp)
   11318             : {
   11319      514999 :     SrcNotesVector& notes = this->notes();
   11320             :     unsigned index;
   11321      515003 :     if (!AllocSrcNote(cx, notes, &index))
   11322             :         return false;
   11323             : 
   11324             :     /*
   11325             :      * Compute delta from the last annotated bytecode's offset.  If it's too
   11326             :      * big to fit in sn, allocate one or more xdelta notes and reset sn.
   11327             :      */
   11328      515023 :     ptrdiff_t offset = this->offset();
   11329     1030046 :     ptrdiff_t delta = offset - lastNoteOffset();
   11330           0 :     current->lastNoteOffset = offset;
   11331      515023 :     if (delta >= SN_DELTA_LIMIT) {
   11332             :         do {
   11333           0 :             ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
   11334           0 :             SN_MAKE_XDELTA(&notes[index], xdelta);
   11335           0 :             delta -= xdelta;
   11336           0 :             if (!AllocSrcNote(cx, notes, &index))
   11337             :                 return false;
   11338           0 :         } while (delta >= SN_DELTA_LIMIT);
   11339             :     }
   11340             : 
   11341             :     /*
   11342             :      * Initialize type and delta, then allocate the minimum number of notes
   11343             :      * needed for type's arity.  Usually, we won't need more, but if an offset
   11344             :      * does take two bytes, setSrcNoteOffset will grow notes.
   11345             :      */
   11346           0 :     SN_MAKE_NOTE(&notes[index], type, delta);
   11347      696424 :     for (int n = (int)js_SrcNoteSpec[type].arity; n > 0; n--) {
   11348           0 :         if (!newSrcNote(SRC_NULL))
   11349             :             return false;
   11350             :     }
   11351             : 
   11352           0 :     if (indexp)
   11353           0 :         *indexp = index;
   11354             :     return true;
   11355             : }
   11356             : 
   11357             : bool
   11358      173832 : BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp)
   11359             : {
   11360             :     unsigned index;
   11361           0 :     if (!newSrcNote(type, &index))
   11362             :         return false;
   11363           0 :     if (!setSrcNoteOffset(index, 0, offset))
   11364             :         return false;
   11365      173844 :     if (indexp)
   11366        1521 :         *indexp = index;
   11367             :     return true;
   11368             : }
   11369             : 
   11370             : bool
   11371         407 : BytecodeEmitter::newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
   11372             :                              unsigned* indexp)
   11373             : {
   11374             :     unsigned index;
   11375           1 :     if (!newSrcNote(type, &index))
   11376             :         return false;
   11377         407 :     if (!setSrcNoteOffset(index, 0, offset1))
   11378             :         return false;
   11379         407 :     if (!setSrcNoteOffset(index, 1, offset2))
   11380             :         return false;
   11381         407 :     if (indexp)
   11382         359 :         *indexp = index;
   11383             :     return true;
   11384             : }
   11385             : 
   11386             : bool
   11387           0 : BytecodeEmitter::addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta)
   11388             : {
   11389             :     /*
   11390             :      * Called only from finishTakingSrcNotes to add to main script note
   11391             :      * deltas, and only by a small positive amount.
   11392             :      */
   11393           0 :     MOZ_ASSERT(current == &main);
   11394           0 :     MOZ_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT);
   11395             : 
   11396        7111 :     ptrdiff_t base = SN_DELTA(sn);
   11397           0 :     ptrdiff_t limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
   11398        7111 :     ptrdiff_t newdelta = base + delta;
   11399           0 :     if (newdelta < limit) {
   11400           0 :         SN_SET_DELTA(sn, newdelta);
   11401             :     } else {
   11402             :         jssrcnote xdelta;
   11403           0 :         SN_MAKE_XDELTA(&xdelta, delta);
   11404         602 :         if (!main.notes.insert(sn, xdelta))
   11405           0 :             return false;
   11406             :     }
   11407             :     return true;
   11408             : }
   11409             : 
   11410             : bool
   11411           0 : BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset)
   11412             : {
   11413      183611 :     if (!SN_REPRESENTABLE_OFFSET(offset)) {
   11414           0 :         reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
   11415           0 :         return false;
   11416             :     }
   11417             : 
   11418           0 :     SrcNotesVector& notes = this->notes();
   11419             : 
   11420             :     /* Find the offset numbered which (i.e., skip exactly which offsets). */
   11421           0 :     jssrcnote* sn = &notes[index];
   11422           0 :     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
   11423           1 :     MOZ_ASSERT((int) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
   11424           0 :     for (sn++; which; sn++, which--) {
   11425           0 :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11426           0 :             sn += 3;
   11427             :     }
   11428             : 
   11429             :     /*
   11430             :      * See if the new offset requires four bytes either by being too big or if
   11431             :      * the offset has already been inflated (in which case, we need to stay big
   11432             :      * to not break the srcnote encoding if this isn't the last srcnote).
   11433             :      */
   11434           0 :     if (offset > (ptrdiff_t)SN_4BYTE_OFFSET_MASK || (*sn & SN_4BYTE_OFFSET_FLAG)) {
   11435             :         /* Maybe this offset was already set to a four-byte value. */
   11436       31650 :         if (!(*sn & SN_4BYTE_OFFSET_FLAG)) {
   11437             :             /* Insert three dummy bytes that will be overwritten shortly. */
   11438       31650 :             jssrcnote dummy = 0;
   11439       94950 :             if (!(sn = notes.insert(sn, dummy)) ||
   11440       63300 :                 !(sn = notes.insert(sn, dummy)) ||
   11441       31650 :                 !(sn = notes.insert(sn, dummy)))
   11442             :             {
   11443           0 :                 ReportOutOfMemory(cx);
   11444           0 :                 return false;
   11445             :             }
   11446             :         }
   11447       31650 :         *sn++ = (jssrcnote)(SN_4BYTE_OFFSET_FLAG | (offset >> 24));
   11448           0 :         *sn++ = (jssrcnote)(offset >> 16);
   11449           0 :         *sn++ = (jssrcnote)(offset >> 8);
   11450             :     }
   11451           0 :     *sn = (jssrcnote)offset;
   11452      183611 :     return true;
   11453             : }
   11454             : 
   11455             : bool
   11456       13449 : BytecodeEmitter::finishTakingSrcNotes(uint32_t* out)
   11457             : {
   11458           0 :     MOZ_ASSERT(current == &main);
   11459             : 
   11460           0 :     MOZ_ASSERT(prologue.notes.length() == 0);
   11461           0 :     MOZ_ASSERT(prologue.lastNoteOffset == 0);
   11462             : 
   11463             :     // We may need to adjust the offset of the first main note, by adding to
   11464             :     // its delta and possibly even prepending SRC_XDELTA notes to it to account
   11465             :     // for prologue bytecodes.
   11466           0 :     ptrdiff_t offset = prologueOffset();
   11467           0 :     MOZ_ASSERT(offset >= 0);
   11468           0 :     if (offset > 0 && main.notes.length() != 0) {
   11469             :         // NB: Use as much of the first main note's delta as we can.
   11470       13018 :         jssrcnote* sn = main.notes.begin();
   11471        6509 :         ptrdiff_t delta = SN_IS_XDELTA(sn)
   11472           0 :                           ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK)
   11473       12953 :                           : SN_DELTA_MASK - (*sn & SN_DELTA_MASK);
   11474           0 :         if (offset < delta)
   11475           0 :             delta = offset;
   11476             :         for (;;) {
   11477           0 :             if (!addToSrcNoteDelta(sn, delta))
   11478             :                 return false;
   11479        7111 :             offset -= delta;
   11480        7111 :             if (offset == 0)
   11481             :                 break;
   11482         602 :             delta = Min(offset, SN_XDELTA_MASK);
   11483           0 :             sn = main.notes.begin();
   11484             :         }
   11485             :     }
   11486             : 
   11487             :     // The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
   11488             :     // when the notes are copied to their final destination by copySrcNotes.
   11489           0 :     *out = main.notes.length() + 1;
   11490           0 :     return true;
   11491             : }
   11492             : 
   11493             : void
   11494       13449 : BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes)
   11495             : {
   11496       13449 :     MOZ_ASSERT(prologue.notes.length() == 0);
   11497           0 :     unsigned mainCount = main.notes.length();
   11498             :     // nsrcnotes includes SN_MAKE_TERMINATOR in addition to main.notes.
   11499           0 :     MOZ_ASSERT(mainCount == nsrcnotes - 1);
   11500       26898 :     PodCopy(destination, main.notes.begin(), mainCount);
   11501           0 :     SN_MAKE_TERMINATOR(&destination[mainCount]);
   11502           0 : }
   11503             : 
   11504             : void
   11505          42 : CGConstList::finish(ConstArray* array)
   11506             : {
   11507          42 :     MOZ_ASSERT(length() == array->length);
   11508             : 
   11509         321 :     for (unsigned i = 0; i < length(); i++)
   11510           0 :         array->vector[i] = list[i];
   11511          42 : }
   11512             : 
   11513             : /*
   11514             :  * Find the index of the given object for code generator.
   11515             :  *
   11516             :  * Since the emitter refers to each parsed object only once, for the index we
   11517             :  * use the number of already indexed objects. We also add the object to a list
   11518             :  * to convert the list to a fixed-size array when we complete code generation,
   11519             :  * see js::CGObjectList::finish below.
   11520             :  */
   11521             : unsigned
   11522       17178 : CGObjectList::add(ObjectBox* objbox)
   11523             : {
   11524           0 :     MOZ_ASSERT(!objbox->emitLink);
   11525           0 :     objbox->emitLink = lastbox;
   11526           0 :     lastbox = objbox;
   11527           0 :     return length++;
   11528             : }
   11529             : 
   11530             : void
   11531        3904 : CGObjectList::finish(ObjectArray* array)
   11532             : {
   11533        3904 :     MOZ_ASSERT(length <= INDEX_LIMIT);
   11534           0 :     MOZ_ASSERT(length == array->length);
   11535             : 
   11536           0 :     js::GCPtrObject* cursor = array->vector + array->length;
   11537           0 :     ObjectBox* objbox = lastbox;
   11538           0 :     do {
   11539           0 :         --cursor;
   11540           0 :         MOZ_ASSERT(!*cursor);
   11541           0 :         MOZ_ASSERT(objbox->object->isTenured());
   11542       34356 :         *cursor = objbox->object;
   11543           0 :     } while ((objbox = objbox->emitLink) != nullptr);
   11544        3905 :     MOZ_ASSERT(cursor == array->vector);
   11545        3905 : }
   11546             : 
   11547             : void
   11548           0 : CGScopeList::finish(ScopeArray* array)
   11549             : {
   11550           0 :     MOZ_ASSERT(length() <= INDEX_LIMIT);
   11551           0 :     MOZ_ASSERT(length() == array->length);
   11552           0 :     for (uint32_t i = 0; i < length(); i++)
   11553       92492 :         array->vector[i].init(vector[i]);
   11554       13449 : }
   11555             : 
   11556             : bool
   11557        7653 : CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end)
   11558             : {
   11559        7653 :     MOZ_ASSERT(start <= end);
   11560        7653 :     MOZ_ASSERT(size_t(uint32_t(start)) == start);
   11561        7653 :     MOZ_ASSERT(size_t(uint32_t(end)) == end);
   11562             : 
   11563             :     JSTryNote note;
   11564        7653 :     note.kind = kind;
   11565        7653 :     note.stackDepth = stackDepth;
   11566        7653 :     note.start = uint32_t(start);
   11567        7653 :     note.length = uint32_t(end - start);
   11568             : 
   11569        7653 :     return list.append(note);
   11570             : }
   11571             : 
   11572             : void
   11573        2320 : CGTryNoteList::finish(TryNoteArray* array)
   11574             : {
   11575        2320 :     MOZ_ASSERT(length() == array->length);
   11576             : 
   11577           0 :     for (unsigned i = 0; i < length(); i++)
   11578           0 :         array->vector[i] = list[i];
   11579           0 : }
   11580             : 
   11581             : bool
   11582           0 : CGScopeNoteList::append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
   11583             :                         uint32_t parent)
   11584             : {
   11585             :     CGScopeNote note;
   11586           0 :     mozilla::PodZero(&note);
   11587             : 
   11588       13762 :     note.index = scopeIndex;
   11589           0 :     note.start = offset;
   11590           0 :     note.parent = parent;
   11591           0 :     note.startInPrologue = inPrologue;
   11592             : 
   11593           0 :     return list.append(note);
   11594             : }
   11595             : 
   11596             : void
   11597           0 : CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset, bool inPrologue)
   11598             : {
   11599           0 :     MOZ_ASSERT(index < length());
   11600       13762 :     MOZ_ASSERT(list[index].length == 0);
   11601           0 :     list[index].end = offset;
   11602             :     list[index].endInPrologue = inPrologue;
   11603             : }
   11604             : 
   11605             : void
   11606             : CGScopeNoteList::finish(ScopeNoteArray* array, uint32_t prologueLength)
   11607             : {
   11608             :     MOZ_ASSERT(length() == array->length);
   11609             : 
   11610             :     for (unsigned i = 0; i < length(); i++) {
   11611             :         if (!list[i].startInPrologue)
   11612             :             list[i].start += prologueLength;
   11613             :         if (!list[i].endInPrologue && list[i].end != UINT32_MAX)
   11614             :             list[i].end += prologueLength;
   11615             :         MOZ_ASSERT(list[i].end >= list[i].start);
   11616             :         list[i].length = list[i].end - list[i].start;
   11617             :         array->vector[i] = list[i];
   11618             :     }
   11619             : }
   11620             : 
   11621             : void
   11622             : CGYieldAndAwaitOffsetList::finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength)
   11623             : {
   11624             :     MOZ_ASSERT(length() == array.length());
   11625             : 
   11626             :     for (unsigned i = 0; i < length(); i++)
   11627             :         array[i] = prologueLength + list[i];
   11628             : }
   11629             : 
   11630             : /*
   11631             :  * We should try to get rid of offsetBias (always 0 or 1, where 1 is
   11632             :  * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR.
   11633             :  */
   11634             : const JSSrcNoteSpec js_SrcNoteSpec[] = {
   11635             : #define DEFINE_SRC_NOTE_SPEC(sym, name, arity) { name, arity },
   11636             :     FOR_EACH_SRC_NOTE_TYPE(DEFINE_SRC_NOTE_SPEC)
   11637             : #undef DEFINE_SRC_NOTE_SPEC
   11638             : };
   11639             : 
   11640             : static int
   11641             : SrcNoteArity(jssrcnote* sn)
   11642             : {
   11643             :     MOZ_ASSERT(SN_TYPE(sn) < SRC_LAST);
   11644             :     return js_SrcNoteSpec[SN_TYPE(sn)].arity;
   11645             : }
   11646             : 
   11647             : JS_FRIEND_API(unsigned)
   11648             : js::SrcNoteLength(jssrcnote* sn)
   11649             : {
   11650             :     unsigned arity;
   11651             :     jssrcnote* base;
   11652             : 
   11653             :     arity = SrcNoteArity(sn);
   11654             :     for (base = sn++; arity; sn++, arity--) {
   11655             :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11656             :             sn += 3;
   11657             :     }
   11658             :     return sn - base;
   11659             : }
   11660             : 
   11661             : JS_FRIEND_API(ptrdiff_t)
   11662             : js::GetSrcNoteOffset(jssrcnote* sn, unsigned which)
   11663             : {
   11664             :     /* Find the offset numbered which (i.e., skip exactly which offsets). */
   11665             :     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
   11666             :     MOZ_ASSERT((int) which < SrcNoteArity(sn));
   11667             :     for (sn++; which; sn++, which--) {
   11668             :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11669             :             sn += 3;
   11670             :     }
   11671             :     if (*sn & SN_4BYTE_OFFSET_FLAG) {
   11672             :         return (ptrdiff_t)(((uint32_t)(sn[0] & SN_4BYTE_OFFSET_MASK) << 24)
   11673             :                            | (sn[1] << 16)
   11674             :                            | (sn[2] << 8)
   11675             :                            | sn[3]);
   11676             :     }
   11677             :     return (ptrdiff_t)*sn;
   11678             : }

Generated by: LCOV version 1.13-14-ga5dd952