LCOV - code coverage report
Current view: top level - js/src/frontend - BytecodeEmitter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3634 5853 62.1 %
Date: 2017-07-14 16:53:18 Functions: 343 395 86.8 %
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 "jsatom.h"
      23             : #include "jscntxt.h"
      24             : #include "jsfun.h"
      25             : #include "jsnum.h"
      26             : #include "jsopcode.h"
      27             : #include "jsscript.h"
      28             : #include "jstypes.h"
      29             : #include "jsutil.h"
      30             : 
      31             : #include "ds/Nestable.h"
      32             : #include "frontend/Parser.h"
      33             : #include "frontend/TokenStream.h"
      34             : #include "vm/Debugger.h"
      35             : #include "vm/GeneratorObject.h"
      36             : #include "vm/Stack.h"
      37             : #include "wasm/AsmJS.h"
      38             : 
      39             : #include "jsatominlines.h"
      40             : #include "jsobjinlines.h"
      41             : #include "jsscriptinlines.h"
      42             : 
      43             : #include "frontend/ParseNode-inl.h"
      44             : #include "vm/EnvironmentObject-inl.h"
      45             : #include "vm/NativeObject-inl.h"
      46             : 
      47             : using namespace js;
      48             : using namespace js::gc;
      49             : using namespace js::frontend;
      50             : 
      51             : using mozilla::AssertedCast;
      52             : using mozilla::DebugOnly;
      53             : using mozilla::Maybe;
      54             : using mozilla::Nothing;
      55             : using mozilla::NumberIsInt32;
      56             : using mozilla::PodCopy;
      57             : using mozilla::Some;
      58             : using mozilla::Unused;
      59             : 
      60             : class BreakableControl;
      61             : class LabelControl;
      62             : class LoopControl;
      63             : class ForOfLoopControl;
      64             : class TryFinallyControl;
      65             : 
      66             : static bool
      67      227412 : ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn)
      68             : {
      69      227412 :     return pn->getKind() == PNK_WHILE || pn->getKind() == PNK_FOR;
      70             : }
      71             : 
      72             : // A cache that tracks superfluous TDZ checks.
      73             : //
      74             : // Each basic block should have a TDZCheckCache in scope. Some NestableControl
      75             : // subclasses contain a TDZCheckCache.
      76       40420 : class BytecodeEmitter::TDZCheckCache : public Nestable<BytecodeEmitter::TDZCheckCache>
      77             : {
      78             :     PooledMapPtr<CheckTDZMap> cache_;
      79             : 
      80       23035 :     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
      81       23035 :         return cache_ || cache_.acquire(bce->cx);
      82             :     }
      83             : 
      84             :   public:
      85       40415 :     explicit TDZCheckCache(BytecodeEmitter* bce)
      86       40415 :       : Nestable<TDZCheckCache>(&bce->innermostTDZCheckCache),
      87       40415 :         cache_(bce->cx->frontendCollectionPool())
      88       40415 :     { }
      89             : 
      90             :     Maybe<MaybeCheckTDZ> needsTDZCheck(BytecodeEmitter* bce, JSAtom* name);
      91             :     MOZ_MUST_USE bool noteTDZCheck(BytecodeEmitter* bce, JSAtom* name, MaybeCheckTDZ check);
      92             : };
      93             : 
      94        1773 : class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::NestableControl>
      95             : {
      96             :     StatementKind kind_;
      97             : 
      98             :     // The innermost scope when this was pushed.
      99             :     EmitterScope* emitterScope_;
     100             : 
     101             :   protected:
     102        1773 :     NestableControl(BytecodeEmitter* bce, StatementKind kind)
     103        1773 :       : Nestable<NestableControl>(&bce->innermostNestableControl),
     104             :         kind_(kind),
     105        1773 :         emitterScope_(bce->innermostEmitterScope)
     106        1773 :     { }
     107             : 
     108             :   public:
     109             :     using Nestable<NestableControl>::enclosing;
     110             :     using Nestable<NestableControl>::findNearest;
     111             : 
     112        1564 :     StatementKind kind() const {
     113        1564 :         return kind_;
     114             :     }
     115             : 
     116        1912 :     EmitterScope* emitterScope() const {
     117        1912 :         return emitterScope_;
     118             :     }
     119             : 
     120             :     template <typename T>
     121             :     bool is() const;
     122             : 
     123             :     template <typename T>
     124        2806 :     T& as() {
     125        2806 :         MOZ_ASSERT(this->is<T>());
     126        2806 :         return static_cast<T&>(*this);
     127             :     }
     128             : };
     129             : 
     130             : // Template specializations are disallowed in different namespaces; specialize
     131             : // all the NestableControl subtypes up front.
     132             : namespace js {
     133             : namespace frontend {
     134             : 
     135             : template <>
     136             : bool
     137        2726 : BytecodeEmitter::NestableControl::is<BreakableControl>() const
     138             : {
     139        2726 :     return StatementKindIsUnlabeledBreakTarget(kind_) || kind_ == StatementKind::Label;
     140             : }
     141             : 
     142             : template <>
     143             : bool
     144        4177 : BytecodeEmitter::NestableControl::is<LabelControl>() const
     145             : {
     146        4177 :     return kind_ == StatementKind::Label;
     147             : }
     148             : 
     149             : template <>
     150             : bool
     151        2731 : BytecodeEmitter::NestableControl::is<LoopControl>() const
     152             : {
     153        2731 :     return StatementKindIsLoop(kind_);
     154             : }
     155             : 
     156             : template <>
     157             : bool
     158         536 : BytecodeEmitter::NestableControl::is<ForOfLoopControl>() const
     159             : {
     160         536 :     return kind_ == StatementKind::ForOfLoop;
     161             : }
     162             : 
     163             : template <>
     164             : bool
     165         972 : BytecodeEmitter::NestableControl::is<TryFinallyControl>() const
     166             : {
     167         972 :     return kind_ == StatementKind::Try || kind_ == StatementKind::Finally;
     168             : }
     169             : 
     170             : } // namespace frontend
     171             : } // namespace js
     172             : 
     173        1284 : class BreakableControl : public BytecodeEmitter::NestableControl
     174             : {
     175             :   public:
     176             :     // Offset of the last break.
     177             :     JumpList breaks;
     178             : 
     179        1284 :     BreakableControl(BytecodeEmitter* bce, StatementKind kind)
     180        1284 :       : NestableControl(bce, kind)
     181             :     {
     182        1284 :         MOZ_ASSERT(is<BreakableControl>());
     183        1284 :     }
     184             : 
     185        1226 :     MOZ_MUST_USE bool patchBreaks(BytecodeEmitter* bce) {
     186        1226 :         return bce->emitJumpTargetAndPatch(breaks);
     187             :     }
     188             : };
     189             : 
     190           0 : class LabelControl : public BreakableControl
     191             : {
     192             :     RootedAtom label_;
     193             : 
     194             :     // The code offset when this was pushed. Used for effectfulness checking.
     195             :     ptrdiff_t startOffset_;
     196             : 
     197             :   public:
     198           0 :     LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
     199           0 :       : BreakableControl(bce, StatementKind::Label),
     200             :         label_(bce->cx, label),
     201           0 :         startOffset_(startOffset)
     202           0 :     { }
     203             : 
     204           0 :     HandleAtom label() const {
     205           0 :         return label_;
     206             :     }
     207             : 
     208           0 :     ptrdiff_t startOffset() const {
     209           0 :         return startOffset_;
     210             :     }
     211             : };
     212             : 
     213        1074 : class LoopControl : public BreakableControl
     214             : {
     215             :     // Loops' children are emitted in dominance order, so they can always
     216             :     // have a TDZCheckCache.
     217             :     BytecodeEmitter::TDZCheckCache tdzCache_;
     218             : 
     219             :     // Stack depth when this loop was pushed on the control stack.
     220             :     int32_t stackDepth_;
     221             : 
     222             :     // The loop nesting depth. Used as a hint to Ion.
     223             :     uint32_t loopDepth_;
     224             : 
     225             :     // Can we OSR into Ion from here? True unless there is non-loop state on the stack.
     226             :     bool canIonOsr_;
     227             : 
     228             :   public:
     229             :     // The target of continue statement jumps, e.g., the update portion of a
     230             :     // for(;;) loop.
     231             :     JumpTarget continueTarget;
     232             : 
     233             :     // Offset of the last continue in the loop.
     234             :     JumpList continues;
     235             : 
     236        1074 :     LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
     237        1074 :       : BreakableControl(bce, loopKind),
     238             :         tdzCache_(bce),
     239        1074 :         continueTarget({ -1 })
     240             :     {
     241        1074 :         MOZ_ASSERT(is<LoopControl>());
     242             : 
     243        1074 :         LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
     244             : 
     245        1074 :         stackDepth_ = bce->stackDepth;
     246        1074 :         loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
     247             : 
     248             :         int loopSlots;
     249        1074 :         if (loopKind == StatementKind::Spread)
     250          58 :             loopSlots = 3;
     251        1016 :         else if (loopKind == StatementKind::ForInLoop || loopKind == StatementKind::ForOfLoop)
     252         372 :             loopSlots = 2;
     253             :         else
     254         644 :             loopSlots = 0;
     255             : 
     256        1074 :         MOZ_ASSERT(loopSlots <= stackDepth_);
     257             : 
     258        1074 :         if (enclosingLoop) {
     259         180 :             canIonOsr_ = (enclosingLoop->canIonOsr_ &&
     260          90 :                           stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
     261             :         } else {
     262         984 :             canIonOsr_ = stackDepth_ == loopSlots;
     263             :         }
     264        1074 :     }
     265             : 
     266        2148 :     uint32_t loopDepth() const {
     267        2148 :         return loopDepth_;
     268             :     }
     269             : 
     270        1074 :     bool canIonOsr() const {
     271        1074 :         return canIonOsr_;
     272             :     }
     273             : 
     274         336 :     MOZ_MUST_USE bool emitSpecialBreakForDone(BytecodeEmitter* bce) {
     275             :         // This doesn't pop stack values, nor handle any other controls.
     276             :         // Should be called on the toplevel of the loop.
     277         336 :         MOZ_ASSERT(bce->stackDepth == stackDepth_);
     278         336 :         MOZ_ASSERT(bce->innermostNestableControl == this);
     279             : 
     280         336 :         if (!bce->newSrcNote(SRC_BREAK))
     281           0 :             return false;
     282         336 :         if (!bce->emitJump(JSOP_GOTO, &breaks))
     283           0 :             return false;
     284             : 
     285         336 :         return true;
     286             :     }
     287             : 
     288        1016 :     MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce) {
     289        1016 :         MOZ_ASSERT(continueTarget.offset != -1);
     290        1016 :         if (!patchBreaks(bce))
     291           0 :             return false;
     292        1016 :         bce->patchJumpsToTarget(continues, continueTarget);
     293        1016 :         return true;
     294             :     }
     295             : };
     296             : 
     297         489 : class TryFinallyControl : public BytecodeEmitter::NestableControl
     298             : {
     299             :     bool emittingSubroutine_;
     300             : 
     301             :   public:
     302             :     // The subroutine when emitting a finally block.
     303             :     JumpList gosubs;
     304             : 
     305             :     // Offset of the last catch guard, if any.
     306             :     JumpList guardJump;
     307             : 
     308         489 :     TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
     309         489 :       : NestableControl(bce, kind),
     310         489 :         emittingSubroutine_(false)
     311             :     {
     312         489 :         MOZ_ASSERT(is<TryFinallyControl>());
     313         489 :     }
     314             : 
     315          41 :     void setEmittingSubroutine() {
     316          41 :         emittingSubroutine_ = true;
     317          41 :     }
     318             : 
     319          16 :     bool emittingSubroutine() const {
     320          16 :         return emittingSubroutine_;
     321             :     }
     322             : };
     323             : 
     324             : static inline void
     325         250 : MarkAllBindingsClosedOver(LexicalScope::Data& data)
     326             : {
     327         250 :     BindingName* names = data.names;
     328         638 :     for (uint32_t i = 0; i < data.length; i++)
     329         388 :         names[i] = BindingName(names[i].name(), true);
     330         250 : }
     331             : 
     332             : // A scope that introduces bindings.
     333        9111 : class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterScope>
     334             : {
     335             :     // The cache of bound names that may be looked up in the
     336             :     // scope. Initially populated as the set of names this scope binds. As
     337             :     // names are looked up in enclosing scopes, they are cached on the
     338             :     // current scope.
     339             :     PooledMapPtr<NameLocationMap> nameCache_;
     340             : 
     341             :     // If this scope's cache does not include free names, such as the
     342             :     // global scope, the NameLocation to return.
     343             :     Maybe<NameLocation> fallbackFreeNameLocation_;
     344             : 
     345             :     // True if there is a corresponding EnvironmentObject on the environment
     346             :     // chain, false if all bindings are stored in frame slots on the stack.
     347             :     bool hasEnvironment_;
     348             : 
     349             :     // The number of enclosing environments. Used for error checking.
     350             :     uint8_t environmentChainLength_;
     351             : 
     352             :     // The next usable slot on the frame for not-closed over bindings.
     353             :     //
     354             :     // The initial frame slot when assigning slots to bindings is the
     355             :     // enclosing scope's nextFrameSlot. For the first scope in a frame,
     356             :     // the initial frame slot is 0.
     357             :     uint32_t nextFrameSlot_;
     358             : 
     359             :     // The index in the BytecodeEmitter's interned scope vector, otherwise
     360             :     // ScopeNote::NoScopeIndex.
     361             :     uint32_t scopeIndex_;
     362             : 
     363             :     // If kind is Lexical, Catch, or With, the index in the BytecodeEmitter's
     364             :     // block scope note list. Otherwise ScopeNote::NoScopeNote.
     365             :     uint32_t noteIndex_;
     366             : 
     367        9108 :     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
     368        9108 :         return nameCache_.acquire(bce->cx);
     369             :     }
     370             : 
     371             :     template <typename BindingIter>
     372       18033 :     MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce, const BindingIter& bi) {
     373       36066 :         if (bi.nextFrameSlot() >= LOCALNO_LIMIT ||
     374       18033 :             bi.nextEnvironmentSlot() >= ENVCOORD_SLOT_LIMIT)
     375             :         {
     376           0 :             bce->reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
     377           0 :             return false;
     378             :         }
     379       18033 :         return true;
     380             :     }
     381             : 
     382        8840 :     MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce) {
     383             :         uint32_t hops;
     384        8840 :         if (EmitterScope* emitterScope = enclosing(&bce))
     385        7418 :             hops = emitterScope->environmentChainLength_;
     386             :         else
     387        1422 :             hops = bce->sc->compilationEnclosingScope()->environmentChainLength();
     388             : 
     389        8840 :         if (hops >= ENVCOORD_HOPS_LIMIT - 1) {
     390           0 :             bce->reportError(nullptr, JSMSG_TOO_DEEP, js_function_str);
     391           0 :             return false;
     392             :         }
     393             : 
     394        8840 :         environmentChainLength_ = mozilla::AssertedCast<uint8_t>(hops + 1);
     395        8840 :         return true;
     396             :     }
     397             : 
     398        7669 :     void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi) {
     399        7669 :         nextFrameSlot_ = bi.nextFrameSlot();
     400        7669 :         if (nextFrameSlot_ > bce->maxFixedSlots)
     401        4996 :             bce->maxFixedSlots = nextFrameSlot_;
     402        7669 :         MOZ_ASSERT_IF(bce->sc->isFunctionBox() &&
     403             :                       (bce->sc->asFunctionBox()->isStarGenerator() ||
     404             :                        bce->sc->asFunctionBox()->isLegacyGenerator() ||
     405             :                        bce->sc->asFunctionBox()->isAsync()),
     406             :                       bce->maxFixedSlots == 0);
     407        7669 :     }
     408             : 
     409       27447 :     MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc) {
     410       27447 :         NameLocationMap& cache = *nameCache_;
     411       27447 :         NameLocationMap::AddPtr p = cache.lookupForAdd(name);
     412       27447 :         MOZ_ASSERT(!p);
     413       27447 :         if (!cache.add(p, name, loc)) {
     414           0 :             ReportOutOfMemory(bce->cx);
     415           0 :             return false;
     416             :         }
     417       27447 :         return true;
     418             :     }
     419             : 
     420      117916 :     Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce, JSAtom* name) {
     421      117916 :         if (NameLocationMap::Ptr p = nameCache_->lookup(name))
     422       75959 :             return Some(p->value().wrapped);
     423       41957 :         if (fallbackFreeNameLocation_ && nameCanBeFree(bce, name))
     424       11523 :             return fallbackFreeNameLocation_;
     425       30434 :         return Nothing();
     426             :     }
     427             : 
     428             :     friend bool BytecodeEmitter::needsImplicitThis();
     429             : 
     430       48382 :     EmitterScope* enclosing(BytecodeEmitter** bce) const {
     431             :         // There is an enclosing scope with access to the same frame.
     432       48382 :         if (EmitterScope* inFrame = enclosingInFrame())
     433       22058 :             return inFrame;
     434             : 
     435             :         // We are currently compiling the enclosing script, look in the
     436             :         // enclosing BCE.
     437       26324 :         if ((*bce)->parent) {
     438       20737 :             *bce = (*bce)->parent;
     439       20737 :             return (*bce)->innermostEmitterScope;
     440             :         }
     441             : 
     442        5587 :         return nullptr;
     443             :     }
     444             : 
     445        9108 :     Scope* enclosingScope(BytecodeEmitter* bce) const {
     446        9108 :         if (EmitterScope* es = enclosing(&bce))
     447        7418 :             return es->scope(bce);
     448             : 
     449             :         // The enclosing script is already compiled or the current script is the
     450             :         // global script.
     451        1690 :         return bce->sc->compilationEnclosingScope();
     452             :     }
     453             : 
     454       11523 :     static bool nameCanBeFree(BytecodeEmitter* bce, JSAtom* name) {
     455             :         // '.generator' cannot be accessed by name.
     456       11523 :         return name != bce->cx->names().dotGenerator;
     457             :     }
     458             : 
     459             :     static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops);
     460             :     NameLocation searchAndCache(BytecodeEmitter* bce, JSAtom* name);
     461             : 
     462             :     template <typename ScopeCreator>
     463             :     MOZ_MUST_USE bool internScope(BytecodeEmitter* bce, ScopeCreator createScope);
     464             :     template <typename ScopeCreator>
     465             :     MOZ_MUST_USE bool internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope);
     466             :     MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
     467             : 
     468             :     MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
     469             :                                              uint32_t slotEnd);
     470             : 
     471             :   public:
     472        9108 :     explicit EmitterScope(BytecodeEmitter* bce)
     473        9108 :       : Nestable<EmitterScope>(&bce->innermostEmitterScope),
     474        9108 :         nameCache_(bce->cx->frontendCollectionPool()),
     475             :         hasEnvironment_(false),
     476             :         environmentChainLength_(0),
     477             :         nextFrameSlot_(0),
     478             :         scopeIndex_(ScopeNote::NoScopeIndex),
     479       18216 :         noteIndex_(ScopeNote::NoScopeNoteIndex)
     480        9108 :     { }
     481             : 
     482             :     void dump(BytecodeEmitter* bce);
     483             : 
     484             :     MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
     485             :                                    Handle<LexicalScope::Data*> bindings);
     486             :     MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
     487             :     MOZ_MUST_USE bool enterComprehensionFor(BytecodeEmitter* bce,
     488             :                                             Handle<LexicalScope::Data*> bindings);
     489             :     MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
     490             :     MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox);
     491             :     MOZ_MUST_USE bool enterParameterExpressionVar(BytecodeEmitter* bce);
     492             :     MOZ_MUST_USE bool enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc);
     493             :     MOZ_MUST_USE bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
     494             :     MOZ_MUST_USE bool enterModule(BytecodeEmitter* module, ModuleSharedContext* modulesc);
     495             :     MOZ_MUST_USE bool enterWith(BytecodeEmitter* bce);
     496             :     MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce);
     497             : 
     498             :     MOZ_MUST_USE bool leave(BytecodeEmitter* bce, bool nonLocal = false);
     499             : 
     500       31964 :     uint32_t index() const {
     501       31964 :         MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex, "Did you forget to intern a Scope?");
     502       31964 :         return scopeIndex_;
     503             :     }
     504             : 
     505        9809 :     uint32_t noteIndex() const {
     506        9809 :         return noteIndex_;
     507             :     }
     508             : 
     509       26399 :     Scope* scope(const BytecodeEmitter* bce) const {
     510       26399 :         return bce->scopeList.vector[index()];
     511             :     }
     512             : 
     513       39414 :     bool hasEnvironment() const {
     514       39414 :         return hasEnvironment_;
     515             :     }
     516             : 
     517             :     // The first frame slot used.
     518        3396 :     uint32_t frameSlotStart() const {
     519        3396 :         if (EmitterScope* inFrame = enclosingInFrame())
     520        3396 :             return inFrame->nextFrameSlot_;
     521           0 :         return 0;
     522             :     }
     523             : 
     524             :     // The last frame slot used + 1.
     525        3292 :     uint32_t frameSlotEnd() const {
     526        3292 :         return nextFrameSlot_;
     527             :     }
     528             : 
     529             :     uint32_t numFrameSlots() const {
     530             :         return frameSlotEnd() - frameSlotStart();
     531             :     }
     532             : 
     533       98496 :     EmitterScope* enclosingInFrame() const {
     534       98496 :         return Nestable<EmitterScope>::enclosing();
     535             :     }
     536             : 
     537       89957 :     NameLocation lookup(BytecodeEmitter* bce, JSAtom* name) {
     538      110002 :         if (Maybe<NameLocation> loc = lookupInCache(bce, name))
     539       69912 :             return *loc;
     540       20045 :         return searchAndCache(bce, name);
     541             :     }
     542             : 
     543             :     Maybe<NameLocation> locationBoundInScope(BytecodeEmitter* bce, JSAtom* name,
     544             :                                              EmitterScope* target);
     545             : };
     546             : 
     547             : void
     548           0 : BytecodeEmitter::EmitterScope::dump(BytecodeEmitter* bce)
     549             : {
     550           0 :     fprintf(stdout, "EmitterScope [%s] %p\n", ScopeKindString(scope(bce)->kind()), this);
     551             : 
     552           0 :     for (NameLocationMap::Range r = nameCache_->all(); !r.empty(); r.popFront()) {
     553           0 :         const NameLocation& l = r.front().value();
     554             : 
     555           0 :         JSAutoByteString bytes;
     556           0 :         if (!AtomToPrintableString(bce->cx, r.front().key(), &bytes))
     557           0 :             return;
     558           0 :         if (l.kind() != NameLocation::Kind::Dynamic)
     559           0 :             fprintf(stdout, "  %s %s ", BindingKindString(l.bindingKind()), bytes.ptr());
     560             :         else
     561           0 :             fprintf(stdout, "  %s ", bytes.ptr());
     562             : 
     563           0 :         switch (l.kind()) {
     564             :           case NameLocation::Kind::Dynamic:
     565           0 :             fprintf(stdout, "dynamic\n");
     566           0 :             break;
     567             :           case NameLocation::Kind::Global:
     568           0 :             fprintf(stdout, "global\n");
     569           0 :             break;
     570             :           case NameLocation::Kind::Intrinsic:
     571           0 :             fprintf(stdout, "intrinsic\n");
     572           0 :             break;
     573             :           case NameLocation::Kind::NamedLambdaCallee:
     574           0 :             fprintf(stdout, "named lambda callee\n");
     575           0 :             break;
     576             :           case NameLocation::Kind::Import:
     577           0 :             fprintf(stdout, "import\n");
     578           0 :             break;
     579             :           case NameLocation::Kind::ArgumentSlot:
     580           0 :             fprintf(stdout, "arg slot=%u\n", l.argumentSlot());
     581           0 :             break;
     582             :           case NameLocation::Kind::FrameSlot:
     583           0 :             fprintf(stdout, "frame slot=%u\n", l.frameSlot());
     584           0 :             break;
     585             :           case NameLocation::Kind::EnvironmentCoordinate:
     586           0 :             fprintf(stdout, "environment hops=%u slot=%u\n",
     587           0 :                     l.environmentCoordinate().hops(), l.environmentCoordinate().slot());
     588           0 :             break;
     589             :           case NameLocation::Kind::DynamicAnnexBVar:
     590           0 :             fprintf(stdout, "dynamic annex b var\n");
     591           0 :             break;
     592             :         }
     593             :     }
     594             : 
     595           0 :     fprintf(stdout, "\n");
     596             : }
     597             : 
     598             : template <typename ScopeCreator>
     599             : bool
     600        9108 : BytecodeEmitter::EmitterScope::internScope(BytecodeEmitter* bce, ScopeCreator createScope)
     601             : {
     602       18216 :     RootedScope enclosing(bce->cx, enclosingScope(bce));
     603        9108 :     Scope* scope = createScope(bce->cx, enclosing);
     604        9108 :     if (!scope)
     605           0 :         return false;
     606        9108 :     hasEnvironment_ = scope->hasEnvironment();
     607        9108 :     scopeIndex_ = bce->scopeList.length();
     608        9108 :     return bce->scopeList.append(scope);
     609             : }
     610             : 
     611             : template <typename ScopeCreator>
     612             : bool
     613        5672 : BytecodeEmitter::EmitterScope::internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope)
     614             : {
     615        5672 :     MOZ_ASSERT(bce->bodyScopeIndex == UINT32_MAX, "There can be only one body scope");
     616        5672 :     bce->bodyScopeIndex = bce->scopeList.length();
     617        5672 :     return internScope(bce, createScope);
     618             : }
     619             : 
     620             : bool
     621        3045 : BytecodeEmitter::EmitterScope::appendScopeNote(BytecodeEmitter* bce)
     622             : {
     623        3045 :     MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
     624             :                "Scope notes are not needed for body-level scopes.");
     625        3045 :     noteIndex_ = bce->scopeNoteList.length();
     626        6090 :     return bce->scopeNoteList.append(index(), bce->offset(), bce->inPrologue(),
     627        6090 :                                      enclosingInFrame() ? enclosingInFrame()->noteIndex()
     628        3045 :                                                         : ScopeNote::NoScopeNoteIndex);
     629             : }
     630             : 
     631             : #ifdef DEBUG
     632             : static bool
     633        3393 : NameIsOnEnvironment(Scope* scope, JSAtom* name)
     634             : {
     635       32001 :     for (BindingIter bi(scope); bi; bi++) {
     636             :         // If found, the name must already be on the environment or an import,
     637             :         // or else there is a bug in the closed-over name analysis in the
     638             :         // Parser.
     639       29998 :         if (bi.name() == name) {
     640        1390 :             BindingLocation::Kind kind = bi.location().kind();
     641             : 
     642        1390 :             if (bi.hasArgumentSlot()) {
     643         156 :                 JSScript* script = scope->as<FunctionScope>().script();
     644         156 :                 if (!script->strict() && !script->functionHasParameterExprs()) {
     645             :                     // Check for duplicate positional formal parameters.
     646         174 :                     for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
     647         115 :                         if (bi2.name() == name)
     648          59 :                             kind = bi2.location().kind();
     649             :                     }
     650             :                 }
     651             :             }
     652             : 
     653         482 :             return kind == BindingLocation::Kind::Global ||
     654        1390 :                    kind == BindingLocation::Kind::Environment ||
     655        1390 :                    kind == BindingLocation::Kind::Import;
     656             :         }
     657             :     }
     658             : 
     659             :     // If not found, assume it's on the global or dynamically accessed.
     660        2003 :     return true;
     661             : }
     662             : #endif
     663             : 
     664             : /* static */ NameLocation
     665        2475 : BytecodeEmitter::EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops)
     666             : {
     667        3393 :     for (ScopeIter si(scope); si; si++) {
     668        3393 :         MOZ_ASSERT(NameIsOnEnvironment(si.scope(), name));
     669             : 
     670        3393 :         bool hasEnv = si.hasSyntacticEnvironment();
     671             : 
     672        3393 :         switch (si.kind()) {
     673             :           case ScopeKind::Function:
     674         621 :             if (hasEnv) {
     675         485 :                 JSScript* script = si.scope()->as<FunctionScope>().script();
     676         485 :                 if (script->funHasExtensibleScope())
     677        2475 :                     return NameLocation::Dynamic();
     678             : 
     679        1413 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     680        1247 :                     if (bi.name() != name)
     681         928 :                         continue;
     682             : 
     683         319 :                     BindingLocation bindLoc = bi.location();
     684         794 :                     if (bi.hasArgumentSlot() &&
     685         378 :                         !script->strict() &&
     686          59 :                         !script->functionHasParameterExprs())
     687             :                     {
     688             :                         // Check for duplicate positional formal parameters.
     689         174 :                         for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
     690         115 :                             if (bi2.name() == name)
     691          59 :                                 bindLoc = bi2.location();
     692             :                         }
     693             :                     }
     694             : 
     695         319 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     696         319 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     697             :                 }
     698             :             }
     699         302 :             break;
     700             : 
     701             :           case ScopeKind::FunctionBodyVar:
     702             :           case ScopeKind::ParameterExpressionVar:
     703             :           case ScopeKind::Lexical:
     704             :           case ScopeKind::NamedLambda:
     705             :           case ScopeKind::StrictNamedLambda:
     706             :           case ScopeKind::SimpleCatch:
     707             :           case ScopeKind::Catch:
     708         763 :             if (hasEnv) {
     709        1208 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     710         940 :                     if (bi.name() != name)
     711         793 :                         continue;
     712             : 
     713             :                     // The name must already have been marked as closed
     714             :                     // over. If this assertion is hit, there is a bug in the
     715             :                     // name analysis.
     716         147 :                     BindingLocation bindLoc = bi.location();
     717         147 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     718         147 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     719             :                 }
     720             :             }
     721         616 :             break;
     722             : 
     723             :           case ScopeKind::Module:
     724           0 :             if (hasEnv) {
     725           0 :                 for (BindingIter bi(si.scope()); bi; bi++) {
     726           0 :                     if (bi.name() != name)
     727           0 :                         continue;
     728             : 
     729           0 :                     BindingLocation bindLoc = bi.location();
     730             : 
     731             :                     // Imports are on the environment but are indirect
     732             :                     // bindings and must be accessed dynamically instead of
     733             :                     // using an EnvironmentCoordinate.
     734           0 :                     if (bindLoc.kind() == BindingLocation::Kind::Import) {
     735           0 :                         MOZ_ASSERT(si.kind() == ScopeKind::Module);
     736           0 :                         return NameLocation::Import();
     737             :                     }
     738             : 
     739           0 :                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
     740           0 :                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
     741             :                 }
     742             :             }
     743           0 :             break;
     744             : 
     745             :           case ScopeKind::Eval:
     746             :           case ScopeKind::StrictEval:
     747             :             // As an optimization, if the eval doesn't have its own var
     748             :             // environment and its immediate enclosing scope is a global
     749             :             // scope, all accesses are global.
     750          30 :             if (!hasEnv && si.scope()->enclosing()->is<GlobalScope>())
     751           0 :                 return NameLocation::Global(BindingKind::Var);
     752          30 :             return NameLocation::Dynamic();
     753             : 
     754             :           case ScopeKind::Global:
     755        1349 :             return NameLocation::Global(BindingKind::Var);
     756             : 
     757             :           case ScopeKind::With:
     758             :           case ScopeKind::NonSyntactic:
     759         630 :             return NameLocation::Dynamic();
     760             : 
     761             :           case ScopeKind::WasmFunction:
     762           0 :             MOZ_CRASH("No direct eval inside wasm functions");
     763             :         }
     764             : 
     765         918 :         if (hasEnv) {
     766         434 :             MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT - 1);
     767         434 :             hops++;
     768             :         }
     769             :     }
     770             : 
     771           0 :     MOZ_CRASH("Malformed scope chain");
     772             : }
     773             : 
     774             : NameLocation
     775       20045 : BytecodeEmitter::EmitterScope::searchAndCache(BytecodeEmitter* bce, JSAtom* name)
     776             : {
     777       40090 :     Maybe<NameLocation> loc;
     778       20045 :     uint8_t hops = hasEnvironment() ? 1 : 0;
     779       40090 :     DebugOnly<bool> inCurrentScript = enclosingInFrame();
     780             : 
     781             :     // Start searching in the current compilation.
     782       30434 :     for (EmitterScope* es = enclosing(&bce); es; es = es->enclosing(&bce)) {
     783       27959 :         loc = es->lookupInCache(bce, name);
     784       27959 :         if (loc) {
     785       17570 :             if (loc->kind() == NameLocation::Kind::EnvironmentCoordinate)
     786        1735 :                 *loc = loc->addHops(hops);
     787       17570 :             break;
     788             :         }
     789             : 
     790       10389 :         if (es->hasEnvironment())
     791        2722 :             hops++;
     792             : 
     793             : #ifdef DEBUG
     794       10389 :         if (!es->enclosingInFrame())
     795        6338 :             inCurrentScript = false;
     796             : #endif
     797             :     }
     798             : 
     799             :     // If the name is not found in the current compilation, walk the Scope
     800             :     // chain encompassing the compilation.
     801       20045 :     if (!loc) {
     802        2475 :         inCurrentScript = false;
     803        2475 :         loc = Some(searchInEnclosingScope(name, bce->sc->compilationEnclosingScope(), hops));
     804             :     }
     805             : 
     806             :     // Each script has its own frame. A free name that is accessed
     807             :     // from an inner script must not be a frame slot access. If this
     808             :     // assertion is hit, it is a bug in the free name analysis in the
     809             :     // parser.
     810       20045 :     MOZ_ASSERT_IF(!inCurrentScript, loc->kind() != NameLocation::Kind::FrameSlot);
     811             : 
     812             :     // It is always correct to not cache the location. Ignore OOMs to make
     813             :     // lookups infallible.
     814       20045 :     if (!putNameInCache(bce, name, *loc))
     815           0 :         bce->cx->recoverFromOutOfMemory();
     816             : 
     817       40090 :     return *loc;
     818             : }
     819             : 
     820             : Maybe<NameLocation>
     821        7173 : BytecodeEmitter::EmitterScope::locationBoundInScope(BytecodeEmitter* bce, JSAtom* name,
     822             :                                                     EmitterScope* target)
     823             : {
     824             :     // The target scope must be an intra-frame enclosing scope of this
     825             :     // one. Count the number of extra hops to reach it.
     826        7173 :     uint8_t extraHops = 0;
     827        7478 :     for (EmitterScope* es = this; es != target; es = es->enclosingInFrame()) {
     828         305 :         if (es->hasEnvironment())
     829         303 :             extraHops++;
     830             :     }
     831             : 
     832             :     // Caches are prepopulated with bound names. So if the name is bound in a
     833             :     // particular scope, it must already be in the cache. Furthermore, don't
     834             :     // consult the fallback location as we only care about binding names.
     835        7173 :     Maybe<NameLocation> loc;
     836        7173 :     if (NameLocationMap::Ptr p = target->nameCache_->lookup(name)) {
     837        6832 :         NameLocation l = p->value().wrapped;
     838        6832 :         if (l.kind() == NameLocation::Kind::EnvironmentCoordinate)
     839         980 :             loc = Some(l.addHops(extraHops));
     840             :         else
     841        5852 :             loc = Some(l);
     842             :     }
     843        7173 :     return loc;
     844             : }
     845             : 
     846             : bool
     847        3465 : BytecodeEmitter::EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
     848             :                                                       uint32_t slotEnd)
     849             : {
     850             :     // Lexical bindings throw ReferenceErrors if they are used before
     851             :     // initialization. See ES6 8.1.1.1.6.
     852             :     //
     853             :     // For completeness, lexical bindings are initialized in ES6 by calling
     854             :     // InitializeBinding, after which touching the binding will no longer
     855             :     // throw reference errors. See 13.1.11, 9.2.13, 13.6.3.4, 13.6.4.6,
     856             :     // 13.6.4.8, 13.14.5, 15.1.8, and 15.2.0.15.
     857        3465 :     if (slotStart != slotEnd) {
     858        3056 :         if (!bce->emit1(JSOP_UNINITIALIZED))
     859           0 :             return false;
     860        7763 :         for (uint32_t slot = slotStart; slot < slotEnd; slot++) {
     861        4707 :             if (!bce->emitLocalOp(JSOP_INITLEXICAL, slot))
     862           0 :                 return false;
     863             :         }
     864        3056 :         if (!bce->emit1(JSOP_POP))
     865           0 :             return false;
     866             :     }
     867             : 
     868        3465 :     return true;
     869             : }
     870             : 
     871             : bool
     872         351 : BytecodeEmitter::EmitterScope::deadZoneFrameSlots(BytecodeEmitter* bce)
     873             : {
     874         351 :     return deadZoneFrameSlotRange(bce, frameSlotStart(), frameSlotEnd());
     875             : }
     876             : 
     877             : bool
     878        2941 : BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
     879             :                                             Handle<LexicalScope::Data*> bindings)
     880             : {
     881        2941 :     MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
     882        2941 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
     883             : 
     884        2941 :     if (!ensureCache(bce))
     885           0 :         return false;
     886             : 
     887             :     // Marks all names as closed over if the the context requires it. This
     888             :     // cannot be done in the Parser as we may not know if the context requires
     889             :     // all bindings to be closed over until after parsing is finished. For
     890             :     // example, legacy generators require all bindings to be closed over but
     891             :     // it is unknown if a function is a legacy generator until the first
     892             :     // 'yield' expression is parsed.
     893             :     //
     894             :     // This is not a problem with other scopes, as all other scopes with
     895             :     // bindings are body-level. At the time of their creation, whether or not
     896             :     // the context requires all bindings to be closed over is already known.
     897        2941 :     if (bce->sc->allBindingsClosedOver())
     898         245 :         MarkAllBindingsClosedOver(*bindings);
     899             : 
     900             :     // Resolve bindings.
     901        2941 :     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
     902        2941 :     uint32_t firstFrameSlot = frameSlotStart();
     903        2941 :     BindingIter bi(*bindings, firstFrameSlot, /* isNamedLambda = */ false);
     904       12227 :     for (; bi; bi++) {
     905        4643 :         if (!checkSlotLimits(bce, bi))
     906           0 :             return false;
     907             : 
     908        4643 :         NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
     909        4643 :         if (!putNameInCache(bce, bi.name(), loc))
     910           0 :             return false;
     911             : 
     912        4643 :         if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
     913           0 :             return false;
     914             :     }
     915             : 
     916        2941 :     updateFrameFixedSlots(bce, bi);
     917             : 
     918             :     // Create and intern the VM scope.
     919             :     auto createScope = [kind, bindings, firstFrameSlot](JSContext* cx,
     920        2941 :                                                         HandleScope enclosing)
     921        2941 :     {
     922             :         return LexicalScope::create(cx, kind, bindings, firstFrameSlot, enclosing);
     923        5882 :     };
     924        2941 :     if (!internScope(bce, createScope))
     925           0 :         return false;
     926             : 
     927        2941 :     if (ScopeKindIsInBody(kind) && hasEnvironment()) {
     928             :         // After interning the VM scope we can get the scope index.
     929         453 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHLEXICALENV))
     930           0 :             return false;
     931             :     }
     932             : 
     933             :     // Lexical scopes need notes to be mapped from a pc.
     934        2941 :     if (!appendScopeNote(bce))
     935           0 :         return false;
     936             : 
     937             :     // Put frame slots in TDZ. Environment slots are poisoned during
     938             :     // environment creation.
     939             :     //
     940             :     // This must be done after appendScopeNote to be considered in the extent
     941             :     // of the scope.
     942        2941 :     if (!deadZoneFrameSlotRange(bce, firstFrameSlot, frameSlotEnd()))
     943           0 :         return false;
     944             : 
     945        2941 :     return checkEnvironmentChainLength(bce);
     946             : }
     947             : 
     948             : bool
     949         391 : BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
     950             : {
     951         391 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
     952         391 :     MOZ_ASSERT(funbox->namedLambdaBindings());
     953             : 
     954         391 :     if (!ensureCache(bce))
     955           0 :         return false;
     956             : 
     957             :     // See comment in enterLexical about allBindingsClosedOver.
     958         391 :     if (funbox->allBindingsClosedOver())
     959           5 :         MarkAllBindingsClosedOver(*funbox->namedLambdaBindings());
     960             : 
     961         391 :     BindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT, /* isNamedLambda = */ true);
     962         391 :     MOZ_ASSERT(bi.kind() == BindingKind::NamedLambdaCallee);
     963             : 
     964             :     // The lambda name, if not closed over, is accessed via JSOP_CALLEE and
     965             :     // not a frame slot. Do not update frame slot information.
     966         391 :     NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
     967         391 :     if (!putNameInCache(bce, bi.name(), loc))
     968           0 :         return false;
     969             : 
     970         391 :     bi++;
     971         391 :     MOZ_ASSERT(!bi, "There should be exactly one binding in a NamedLambda scope");
     972             : 
     973         782 :     auto createScope = [funbox](JSContext* cx, HandleScope enclosing) {
     974             :         ScopeKind scopeKind =
     975         391 :             funbox->strict() ? ScopeKind::StrictNamedLambda : ScopeKind::NamedLambda;
     976         782 :         return LexicalScope::create(cx, scopeKind, funbox->namedLambdaBindings(),
     977         782 :                                     LOCALNO_LIMIT, enclosing);
     978         391 :     };
     979         391 :     if (!internScope(bce, createScope))
     980           0 :         return false;
     981             : 
     982         391 :     return checkEnvironmentChainLength(bce);
     983             : }
     984             : 
     985             : bool
     986           0 : BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce,
     987             :                                                      Handle<LexicalScope::Data*> bindings)
     988             : {
     989           0 :     if (!enterLexical(bce, ScopeKind::Lexical, bindings))
     990           0 :         return false;
     991             : 
     992             :     // For comprehensions, initialize all lexical names up front to undefined
     993             :     // because they're now a dead feature and don't interact properly with
     994             :     // TDZ.
     995           0 :     auto nop = [](BytecodeEmitter*, const NameLocation&, bool) {
     996             :         return true;
     997           0 :     };
     998             : 
     999           0 :     if (!bce->emit1(JSOP_UNDEFINED))
    1000           0 :         return false;
    1001             : 
    1002           0 :     RootedAtom name(bce->cx);
    1003           0 :     for (BindingIter bi(*bindings, frameSlotStart(), /* isNamedLambda = */ false); bi; bi++) {
    1004           0 :         name = bi.name();
    1005           0 :         if (!bce->emitInitializeName(name, nop))
    1006           0 :             return false;
    1007             :     }
    1008             : 
    1009           0 :     if (!bce->emit1(JSOP_POP))
    1010           0 :         return false;
    1011             : 
    1012           0 :     return true;
    1013             : }
    1014             : 
    1015             : bool
    1016           0 : BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
    1017             : {
    1018           0 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1019             : 
    1020           0 :     if (!ensureCache(bce))
    1021           0 :         return false;
    1022             : 
    1023             :     // Parameter expressions var scopes have no pre-set bindings and are
    1024             :     // always extensible, as they are needed for eval.
    1025           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1026             : 
    1027             :     // Create and intern the VM scope.
    1028           0 :     uint32_t firstFrameSlot = frameSlotStart();
    1029           0 :     auto createScope = [firstFrameSlot](JSContext* cx, HandleScope enclosing) {
    1030           0 :         return VarScope::create(cx, ScopeKind::ParameterExpressionVar,
    1031             :                                 /* data = */ nullptr, firstFrameSlot,
    1032             :                                 /* needsEnvironment = */ true, enclosing);
    1033           0 :     };
    1034           0 :     if (!internScope(bce, createScope))
    1035           0 :         return false;
    1036             : 
    1037           0 :     MOZ_ASSERT(hasEnvironment());
    1038           0 :     if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1039           0 :         return false;
    1040             : 
    1041             :     // The extra var scope needs a note to be mapped from a pc.
    1042           0 :     if (!appendScopeNote(bce))
    1043           0 :         return false;
    1044             : 
    1045           0 :     return checkEnvironmentChainLength(bce);
    1046             : }
    1047             : 
    1048             : bool
    1049        5404 : BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox)
    1050             : {
    1051        5404 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1052             : 
    1053             :     // If there are parameter expressions, there is an extra var scope.
    1054        5404 :     if (!funbox->hasExtraBodyVarScope())
    1055        5300 :         bce->setVarEmitterScope(this);
    1056             : 
    1057        5404 :     if (!ensureCache(bce))
    1058           0 :         return false;
    1059             : 
    1060             :     // Resolve body-level bindings, if there are any.
    1061        5404 :     auto bindings = funbox->functionScopeBindings();
    1062       10808 :     Maybe<uint32_t> lastLexicalSlot;
    1063        5404 :     if (bindings) {
    1064        4624 :         NameLocationMap& cache = *nameCache_;
    1065             : 
    1066        4624 :         BindingIter bi(*bindings, funbox->hasParameterExprs);
    1067       30516 :         for (; bi; bi++) {
    1068       12946 :             if (!checkSlotLimits(bce, bi))
    1069           0 :                 return false;
    1070             : 
    1071       12946 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1072       12946 :             NameLocationMap::AddPtr p = cache.lookupForAdd(bi.name());
    1073             : 
    1074             :             // The only duplicate bindings that occur are simple formal
    1075             :             // parameters, in which case the last position counts, so update the
    1076             :             // location.
    1077       12946 :             if (p) {
    1078           0 :                 MOZ_ASSERT(bi.kind() == BindingKind::FormalParameter);
    1079           0 :                 MOZ_ASSERT(!funbox->hasDestructuringArgs);
    1080           0 :                 MOZ_ASSERT(!funbox->hasRest());
    1081           0 :                 p->value() = loc;
    1082           0 :                 continue;
    1083             :             }
    1084             : 
    1085       12946 :             if (!cache.add(p, bi.name(), loc)) {
    1086           0 :                 ReportOutOfMemory(bce->cx);
    1087           0 :                 return false;
    1088             :             }
    1089             :         }
    1090             : 
    1091        4624 :         updateFrameFixedSlots(bce, bi);
    1092             :     } else {
    1093         780 :         nextFrameSlot_ = 0;
    1094             :     }
    1095             : 
    1096             :     // If the function's scope may be extended at runtime due to sloppy direct
    1097             :     // eval and there is no extra var scope, any names beyond the function
    1098             :     // scope must be accessed dynamically as we don't know if the name will
    1099             :     // become a 'var' binding due to direct eval.
    1100        5404 :     if (!funbox->hasParameterExprs && funbox->hasExtensibleScope())
    1101           2 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1102             : 
    1103             :     // In case of parameter expressions, the parameters are lexical
    1104             :     // bindings and have TDZ.
    1105        5404 :     if (funbox->hasParameterExprs && nextFrameSlot_) {
    1106         173 :         uint32_t paramFrameSlotEnd = 0;
    1107         592 :         for (BindingIter bi(*bindings, true); bi; bi++) {
    1108         532 :             if (!BindingKindIsLexical(bi.kind()))
    1109         113 :                 break;
    1110             : 
    1111         419 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1112         419 :             if (loc.kind() == NameLocation::Kind::FrameSlot) {
    1113         394 :                 MOZ_ASSERT(paramFrameSlotEnd <= loc.frameSlot());
    1114         394 :                 paramFrameSlotEnd = loc.frameSlot() + 1;
    1115             :             }
    1116             :         }
    1117             : 
    1118         173 :         if (!deadZoneFrameSlotRange(bce, 0, paramFrameSlotEnd))
    1119           0 :             return false;
    1120             :     }
    1121             : 
    1122             :     // Create and intern the VM scope.
    1123       21616 :     auto createScope = [funbox](JSContext* cx, HandleScope enclosing) {
    1124       10808 :         RootedFunction fun(cx, funbox->function());
    1125       27020 :         return FunctionScope::create(cx, funbox->functionScopeBindings(),
    1126        5404 :                                      funbox->hasParameterExprs,
    1127        5404 :                                      funbox->needsCallObjectRegardlessOfBindings(),
    1128       10808 :                                      fun, enclosing);
    1129        5404 :     };
    1130        5404 :     if (!internBodyScope(bce, createScope))
    1131           0 :         return false;
    1132             : 
    1133        5404 :     return checkEnvironmentChainLength(bce);
    1134             : }
    1135             : 
    1136             : bool
    1137         104 : BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox)
    1138             : {
    1139         104 :     MOZ_ASSERT(funbox->hasParameterExprs);
    1140         104 :     MOZ_ASSERT(funbox->extraVarScopeBindings() ||
    1141             :                funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings());
    1142         104 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1143             : 
    1144             :     // The extra var scope is never popped once it's entered. It replaces the
    1145             :     // function scope as the var emitter scope.
    1146         104 :     bce->setVarEmitterScope(this);
    1147             : 
    1148         104 :     if (!ensureCache(bce))
    1149           0 :         return false;
    1150             : 
    1151             :     // Resolve body-level bindings, if there are any.
    1152         104 :     uint32_t firstFrameSlot = frameSlotStart();
    1153         104 :     if (auto bindings = funbox->extraVarScopeBindings()) {
    1154         104 :         BindingIter bi(*bindings, firstFrameSlot);
    1155         992 :         for (; bi; bi++) {
    1156         444 :             if (!checkSlotLimits(bce, bi))
    1157           0 :                 return false;
    1158             : 
    1159         444 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1160         444 :             if (!putNameInCache(bce, bi.name(), loc))
    1161           0 :                 return false;
    1162             :         }
    1163             : 
    1164         104 :         updateFrameFixedSlots(bce, bi);
    1165             :     } else {
    1166           0 :         nextFrameSlot_ = firstFrameSlot;
    1167             :     }
    1168             : 
    1169             :     // If the extra var scope may be extended at runtime due to sloppy
    1170             :     // direct eval, any names beyond the var scope must be accessed
    1171             :     // dynamically as we don't know if the name will become a 'var' binding
    1172             :     // due to direct eval.
    1173         104 :     if (funbox->hasExtensibleScope())
    1174           0 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1175             : 
    1176             :     // Create and intern the VM scope.
    1177         208 :     auto createScope = [funbox, firstFrameSlot](JSContext* cx, HandleScope enclosing) {
    1178         312 :         return VarScope::create(cx, ScopeKind::FunctionBodyVar,
    1179             :                                 funbox->extraVarScopeBindings(), firstFrameSlot,
    1180         104 :                                 funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(),
    1181             :                                 enclosing);
    1182         312 :     };
    1183         104 :     if (!internScope(bce, createScope))
    1184           0 :         return false;
    1185             : 
    1186         104 :     if (hasEnvironment()) {
    1187          10 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1188           0 :             return false;
    1189             :     }
    1190             : 
    1191             :     // The extra var scope needs a note to be mapped from a pc.
    1192         104 :     if (!appendScopeNote(bce))
    1193           0 :         return false;
    1194             : 
    1195         104 :     return checkEnvironmentChainLength(bce);
    1196             : }
    1197             : 
    1198             : class DynamicBindingIter : public BindingIter
    1199             : {
    1200             :   public:
    1201         130 :     explicit DynamicBindingIter(GlobalSharedContext* sc)
    1202         130 :       : BindingIter(*sc->bindings)
    1203         130 :     { }
    1204             : 
    1205           0 :     explicit DynamicBindingIter(EvalSharedContext* sc)
    1206           0 :       : BindingIter(*sc->bindings, /* strict = */ false)
    1207             :     {
    1208           0 :         MOZ_ASSERT(!sc->strict());
    1209           0 :     }
    1210             : 
    1211        1474 :     JSOp bindingOp() const {
    1212        1474 :         switch (kind()) {
    1213             :           case BindingKind::Var:
    1214         304 :             return JSOP_DEFVAR;
    1215             :           case BindingKind::Let:
    1216          64 :             return JSOP_DEFLET;
    1217             :           case BindingKind::Const:
    1218        1106 :             return JSOP_DEFCONST;
    1219             :           default:
    1220           0 :             MOZ_CRASH("Bad BindingKind");
    1221             :         }
    1222             :     }
    1223             : };
    1224             : 
    1225             : bool
    1226         266 : BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
    1227             : {
    1228         266 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1229             : 
    1230         266 :     bce->setVarEmitterScope(this);
    1231             : 
    1232         266 :     if (!ensureCache(bce))
    1233           0 :         return false;
    1234             : 
    1235         266 :     if (bce->emitterMode == BytecodeEmitter::SelfHosting) {
    1236             :         // In self-hosting, it is incorrect to consult the global scope because
    1237             :         // self-hosted scripts are cloned into their target compartments before
    1238             :         // they are run. Instead of Global, Intrinsic is used for all names.
    1239             :         //
    1240             :         // Intrinsic lookups are redirected to the special intrinsics holder
    1241             :         // in the global object, into which any missing values are cloned
    1242             :         // lazily upon first access.
    1243           3 :         fallbackFreeNameLocation_ = Some(NameLocation::Intrinsic());
    1244             : 
    1245           3 :         auto createScope = [](JSContext* cx, HandleScope enclosing) {
    1246           3 :             MOZ_ASSERT(!enclosing);
    1247           3 :             return &cx->global()->emptyGlobalScope();
    1248             :         };
    1249           3 :         return internBodyScope(bce, createScope);
    1250             :     }
    1251             : 
    1252             :     // Resolve binding names and emit DEF{VAR,LET,CONST} prologue ops.
    1253         263 :     if (globalsc->bindings) {
    1254        2054 :         for (DynamicBindingIter bi(globalsc); bi; bi++) {
    1255        1924 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1256        1924 :             JSAtom* name = bi.name();
    1257        1924 :             if (!putNameInCache(bce, name, loc))
    1258           0 :                 return false;
    1259             : 
    1260             :             // Define the name in the prologue. Do not emit DEFVAR for
    1261             :             // functions that we'll emit DEFFUN for.
    1262        1924 :             if (bi.isTopLevelFunction())
    1263         450 :                 continue;
    1264             : 
    1265        1474 :             if (!bce->emitAtomOp(name, bi.bindingOp()))
    1266           0 :                 return false;
    1267             :         }
    1268             :     }
    1269             : 
    1270             :     // Note that to save space, we don't add free names to the cache for
    1271             :     // global scopes. They are assumed to be global vars in the syntactic
    1272             :     // global scope, dynamic accesses under non-syntactic global scope.
    1273         263 :     if (globalsc->scopeKind() == ScopeKind::Global)
    1274         124 :         fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1275             :     else
    1276         139 :         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1277             : 
    1278         789 :     auto createScope = [globalsc](JSContext* cx, HandleScope enclosing) {
    1279         263 :         MOZ_ASSERT(!enclosing);
    1280         526 :         return GlobalScope::create(cx, globalsc->scopeKind(), globalsc->bindings);
    1281         263 :     };
    1282         263 :     return internBodyScope(bce, createScope);
    1283             : }
    1284             : 
    1285             : bool
    1286           2 : BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
    1287             : {
    1288           2 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1289             : 
    1290           2 :     bce->setVarEmitterScope(this);
    1291             : 
    1292           2 :     if (!ensureCache(bce))
    1293           0 :         return false;
    1294             : 
    1295             :     // For simplicity, treat all free name lookups in eval scripts as dynamic.
    1296           2 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1297             : 
    1298             :     // Create the `var` scope. Note that there is also a lexical scope, created
    1299             :     // separately in emitScript().
    1300           4 :     auto createScope = [evalsc](JSContext* cx, HandleScope enclosing) {
    1301           2 :         ScopeKind scopeKind = evalsc->strict() ? ScopeKind::StrictEval : ScopeKind::Eval;
    1302           2 :         return EvalScope::create(cx, scopeKind, evalsc->bindings, enclosing);
    1303           2 :     };
    1304           2 :     if (!internBodyScope(bce, createScope))
    1305           0 :         return false;
    1306             : 
    1307           2 :     if (hasEnvironment()) {
    1308           2 :         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
    1309           0 :             return false;
    1310             :     } else {
    1311             :         // Resolve binding names and emit DEFVAR prologue ops if we don't have
    1312             :         // an environment (i.e., a sloppy eval not in a parameter expression).
    1313             :         // Eval scripts always have their own lexical scope, but non-strict
    1314             :         // scopes may introduce 'var' bindings to the nearest var scope.
    1315             :         //
    1316             :         // TODO: We may optimize strict eval bindings in the future to be on
    1317             :         // the frame. For now, handle everything dynamically.
    1318           0 :         if (!hasEnvironment() && evalsc->bindings) {
    1319           0 :             for (DynamicBindingIter bi(evalsc); bi; bi++) {
    1320           0 :                 MOZ_ASSERT(bi.bindingOp() == JSOP_DEFVAR);
    1321             : 
    1322           0 :                 if (bi.isTopLevelFunction())
    1323           0 :                     continue;
    1324             : 
    1325           0 :                 if (!bce->emitAtomOp(bi.name(), JSOP_DEFVAR))
    1326           0 :                     return false;
    1327             :             }
    1328             :         }
    1329             : 
    1330             :         // As an optimization, if the eval does not have its own var
    1331             :         // environment and is directly enclosed in a global scope, then all
    1332             :         // free name lookups are global.
    1333           0 :         if (scope(bce)->enclosing()->is<GlobalScope>())
    1334           0 :             fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1335             :     }
    1336             : 
    1337           2 :     return true;
    1338             : }
    1339             : 
    1340             : bool
    1341           0 : BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
    1342             : {
    1343           0 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1344             : 
    1345           0 :     bce->setVarEmitterScope(this);
    1346             : 
    1347           0 :     if (!ensureCache(bce))
    1348           0 :         return false;
    1349             : 
    1350             :     // Resolve body-level bindings, if there are any.
    1351           0 :     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
    1352           0 :     Maybe<uint32_t> firstLexicalFrameSlot;
    1353           0 :     if (ModuleScope::Data* bindings = modulesc->bindings) {
    1354           0 :         BindingIter bi(*bindings);
    1355           0 :         for (; bi; bi++) {
    1356           0 :             if (!checkSlotLimits(bce, bi))
    1357           0 :                 return false;
    1358             : 
    1359           0 :             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
    1360           0 :             if (!putNameInCache(bce, bi.name(), loc))
    1361           0 :                 return false;
    1362             : 
    1363           0 :             if (BindingKindIsLexical(bi.kind())) {
    1364           0 :                 if (loc.kind() == NameLocation::Kind::FrameSlot && !firstLexicalFrameSlot)
    1365           0 :                     firstLexicalFrameSlot = Some(loc.frameSlot());
    1366             : 
    1367           0 :                 if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
    1368           0 :                     return false;
    1369             :             }
    1370             :         }
    1371             : 
    1372           0 :         updateFrameFixedSlots(bce, bi);
    1373             :     } else {
    1374           0 :         nextFrameSlot_ = 0;
    1375             :     }
    1376             : 
    1377             :     // Modules are toplevel, so any free names are global.
    1378           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
    1379             : 
    1380             :     // Put lexical frame slots in TDZ. Environment slots are poisoned during
    1381             :     // environment creation.
    1382           0 :     if (firstLexicalFrameSlot) {
    1383           0 :         if (!deadZoneFrameSlotRange(bce, *firstLexicalFrameSlot, frameSlotEnd()))
    1384           0 :             return false;
    1385             :     }
    1386             : 
    1387             :     // Create and intern the VM scope.
    1388           0 :     auto createScope = [modulesc](JSContext* cx, HandleScope enclosing) {
    1389           0 :         return ModuleScope::create(cx, modulesc->bindings, modulesc->module(), enclosing);
    1390           0 :     };
    1391           0 :     if (!internBodyScope(bce, createScope))
    1392           0 :         return false;
    1393             : 
    1394           0 :     return checkEnvironmentChainLength(bce);
    1395             : }
    1396             : 
    1397             : bool
    1398           0 : BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
    1399             : {
    1400           0 :     MOZ_ASSERT(this == bce->innermostEmitterScope);
    1401             : 
    1402           0 :     if (!ensureCache(bce))
    1403           0 :         return false;
    1404             : 
    1405             :     // 'with' make all accesses dynamic and unanalyzable.
    1406           0 :     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
    1407             : 
    1408           0 :     auto createScope = [](JSContext* cx, HandleScope enclosing) {
    1409             :         return WithScope::create(cx, enclosing);
    1410           0 :     };
    1411           0 :     if (!internScope(bce, createScope))
    1412           0 :         return false;
    1413             : 
    1414           0 :     if (!bce->emitInternedScopeOp(index(), JSOP_ENTERWITH))
    1415           0 :         return false;
    1416             : 
    1417           0 :     if (!appendScopeNote(bce))
    1418           0 :         return false;
    1419             : 
    1420           0 :     return checkEnvironmentChainLength(bce);
    1421             : }
    1422             : 
    1423             : bool
    1424       11166 : BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
    1425             : {
    1426             :     // If we aren't leaving the scope due to a non-local jump (e.g., break),
    1427             :     // we must be the innermost scope.
    1428       11166 :     MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope);
    1429             : 
    1430       11166 :     ScopeKind kind = scope(bce)->kind();
    1431       11166 :     switch (kind) {
    1432             :       case ScopeKind::Lexical:
    1433             :       case ScopeKind::SimpleCatch:
    1434             :       case ScopeKind::Catch:
    1435        4997 :         if (!bce->emit1(hasEnvironment() ? JSOP_POPLEXICALENV : JSOP_DEBUGLEAVELEXICALENV))
    1436           0 :             return false;
    1437        4997 :         break;
    1438             : 
    1439             :       case ScopeKind::With:
    1440           0 :         if (!bce->emit1(JSOP_LEAVEWITH))
    1441           0 :             return false;
    1442           0 :         break;
    1443             : 
    1444             :       case ScopeKind::ParameterExpressionVar:
    1445           0 :         MOZ_ASSERT(hasEnvironment());
    1446           0 :         if (!bce->emit1(JSOP_POPVARENV))
    1447           0 :             return false;
    1448           0 :         break;
    1449             : 
    1450             :       case ScopeKind::Function:
    1451             :       case ScopeKind::FunctionBodyVar:
    1452             :       case ScopeKind::NamedLambda:
    1453             :       case ScopeKind::StrictNamedLambda:
    1454             :       case ScopeKind::Eval:
    1455             :       case ScopeKind::StrictEval:
    1456             :       case ScopeKind::Global:
    1457             :       case ScopeKind::NonSyntactic:
    1458             :       case ScopeKind::Module:
    1459        6169 :         break;
    1460             : 
    1461             :       case ScopeKind::WasmFunction:
    1462           0 :         MOZ_CRASH("No wasm function scopes in JS");
    1463             :     }
    1464             : 
    1465             :     // Finish up the scope if we are leaving it in LIFO fashion.
    1466       11166 :     if (!nonLocal) {
    1467             :         // Popping scopes due to non-local jumps generate additional scope
    1468             :         // notes. See NonLocalExitControl::prepareForNonLocalJump.
    1469        9111 :         if (ScopeKindIsInBody(kind)) {
    1470             :             // The extra function var scope is never popped once it's pushed,
    1471             :             // so its scope note extends until the end of any possible code.
    1472        3046 :             uint32_t offset = kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
    1473        3046 :             bce->scopeNoteList.recordEnd(noteIndex_, offset, bce->inPrologue());
    1474             :         }
    1475             :     }
    1476             : 
    1477       11166 :     return true;
    1478             : }
    1479             : 
    1480             : Maybe<MaybeCheckTDZ>
    1481       12738 : BytecodeEmitter::TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name)
    1482             : {
    1483       12738 :     if (!ensureCache(bce))
    1484           0 :         return Nothing();
    1485             : 
    1486       12738 :     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
    1487       12738 :     if (p)
    1488        5255 :         return Some(p->value().wrapped);
    1489             : 
    1490        7483 :     MaybeCheckTDZ rv = CheckTDZ;
    1491       16656 :     for (TDZCheckCache* it = enclosing(); it; it = it->enclosing()) {
    1492       16105 :         if (it->cache_) {
    1493        9567 :             if (CheckTDZMap::Ptr p2 = it->cache_->lookup(name)) {
    1494        6932 :                 rv = p2->value();
    1495        6932 :                 break;
    1496             :             }
    1497             :         }
    1498             :     }
    1499             : 
    1500        7483 :     if (!cache_->add(p, name, rv)) {
    1501           0 :         ReportOutOfMemory(bce->cx);
    1502           0 :         return Nothing();
    1503             :     }
    1504             : 
    1505        7483 :     return Some(rv);
    1506             : }
    1507             : 
    1508             : bool
    1509       10297 : BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
    1510             :                                              MaybeCheckTDZ check)
    1511             : {
    1512       10297 :     if (!ensureCache(bce))
    1513           0 :         return false;
    1514             : 
    1515       10297 :     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
    1516       10297 :     if (p) {
    1517        4622 :         MOZ_ASSERT(!check, "TDZ only needs to be checked once per binding per basic block.");
    1518        4622 :         p->value() = check;
    1519             :     } else {
    1520        5675 :         if (!cache_->add(p, name, check))
    1521           0 :             return false;
    1522             :     }
    1523             : 
    1524       10297 :     return true;
    1525             : }
    1526             : 
    1527        1164 : class MOZ_STACK_CLASS TryEmitter
    1528             : {
    1529             :   public:
    1530             :     enum Kind {
    1531             :         TryCatch,
    1532             :         TryCatchFinally,
    1533             :         TryFinally
    1534             :     };
    1535             :     enum ShouldUseRetVal {
    1536             :         UseRetVal,
    1537             :         DontUseRetVal
    1538             :     };
    1539             :     enum ShouldUseControl {
    1540             :         UseControl,
    1541             :         DontUseControl,
    1542             :     };
    1543             : 
    1544             :   private:
    1545             :     BytecodeEmitter* bce_;
    1546             :     Kind kind_;
    1547             :     ShouldUseRetVal retValKind_;
    1548             : 
    1549             :     // Track jumps-over-catches and gosubs-to-finally for later fixup.
    1550             :     //
    1551             :     // When a finally block is active, non-local jumps (including
    1552             :     // jumps-over-catches) result in a GOSUB being written into the bytecode
    1553             :     // stream and fixed-up later.
    1554             :     //
    1555             :     // If ShouldUseControl is DontUseControl, all that handling is skipped.
    1556             :     // DontUseControl is used by yield* and the internal try-catch around
    1557             :     // IteratorClose. These internal uses must:
    1558             :     //   * have only one catch block
    1559             :     //   * have no catch guard
    1560             :     //   * have JSOP_GOTO at the end of catch-block
    1561             :     //   * have no non-local-jump
    1562             :     //   * don't use finally block for normal completion of try-block and
    1563             :     //     catch-block
    1564             :     //
    1565             :     // Additionally, a finally block may be emitted when ShouldUseControl is
    1566             :     // DontUseControl, even if the kind is not TryCatchFinally or TryFinally,
    1567             :     // because GOSUBs are not emitted. This internal use shares the
    1568             :     // requirements as above.
    1569             :     Maybe<TryFinallyControl> controlInfo_;
    1570             : 
    1571             :     int depth_;
    1572             :     unsigned noteIndex_;
    1573             :     ptrdiff_t tryStart_;
    1574             :     JumpList catchAndFinallyJump_;
    1575             :     JumpTarget tryEnd_;
    1576             :     JumpTarget finallyStart_;
    1577             : 
    1578             :     enum State {
    1579             :         Start,
    1580             :         Try,
    1581             :         TryEnd,
    1582             :         Catch,
    1583             :         CatchEnd,
    1584             :         Finally,
    1585             :         FinallyEnd,
    1586             :         End
    1587             :     };
    1588             :     State state_;
    1589             : 
    1590        1164 :     bool hasCatch() const {
    1591        1164 :         return kind_ == TryCatch || kind_ == TryCatchFinally;
    1592             :     }
    1593        4489 :     bool hasFinally() const {
    1594        4489 :         return kind_ == TryCatchFinally || kind_ == TryFinally;
    1595             :     }
    1596             : 
    1597             :   public:
    1598        1164 :     TryEmitter(BytecodeEmitter* bce, Kind kind, ShouldUseRetVal retValKind = UseRetVal,
    1599             :                ShouldUseControl controlKind = UseControl)
    1600        1164 :       : bce_(bce),
    1601             :         kind_(kind),
    1602             :         retValKind_(retValKind),
    1603             :         depth_(0),
    1604             :         noteIndex_(0),
    1605             :         tryStart_(0),
    1606        1164 :         state_(Start)
    1607             :     {
    1608        1164 :         if (controlKind == UseControl)
    1609         489 :             controlInfo_.emplace(bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try);
    1610        1164 :         finallyStart_.offset = 0;
    1611        1164 :     }
    1612             : 
    1613           3 :     bool emitJumpOverCatchAndFinally() {
    1614           3 :         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1615           0 :             return false;
    1616           3 :         return true;
    1617             :     }
    1618             : 
    1619        1164 :     bool emitTry() {
    1620        1164 :         MOZ_ASSERT(state_ == Start);
    1621             : 
    1622             :         // Since an exception can be thrown at any place inside the try block,
    1623             :         // we need to restore the stack and the scope chain before we transfer
    1624             :         // the control to the exception handler.
    1625             :         //
    1626             :         // For that we store in a try note associated with the catch or
    1627             :         // finally block the stack depth upon the try entry. The interpreter
    1628             :         // uses this depth to properly unwind the stack and the scope chain.
    1629        1164 :         depth_ = bce_->stackDepth;
    1630             : 
    1631             :         // Record the try location, then emit the try block.
    1632        1164 :         if (!bce_->newSrcNote(SRC_TRY, &noteIndex_))
    1633           0 :             return false;
    1634        1164 :         if (!bce_->emit1(JSOP_TRY))
    1635           0 :             return false;
    1636        1164 :         tryStart_ = bce_->offset();
    1637             : 
    1638        1164 :         state_ = Try;
    1639        1164 :         return true;
    1640             :     }
    1641             : 
    1642             :   private:
    1643        1164 :     bool emitTryEnd() {
    1644        1164 :         MOZ_ASSERT(state_ == Try);
    1645        1164 :         MOZ_ASSERT(depth_ == bce_->stackDepth);
    1646             : 
    1647             :         // GOSUB to finally, if present.
    1648        1164 :         if (hasFinally() && controlInfo_) {
    1649          41 :             if (!bce_->emitJump(JSOP_GOSUB, &controlInfo_->gosubs))
    1650           0 :                 return false;
    1651             :         }
    1652             : 
    1653             :         // Source note points to the jump at the end of the try block.
    1654        1164 :         if (!bce_->setSrcNoteOffset(noteIndex_, 0, bce_->offset() - tryStart_ + JSOP_TRY_LENGTH))
    1655           0 :             return false;
    1656             : 
    1657             :         // Emit jump over catch and/or finally.
    1658        1164 :         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1659           0 :             return false;
    1660             : 
    1661        1164 :         if (!bce_->emitJumpTarget(&tryEnd_))
    1662           0 :             return false;
    1663             : 
    1664        1164 :         return true;
    1665             :     }
    1666             : 
    1667             :   public:
    1668        1142 :     bool emitCatch() {
    1669        1142 :         if (state_ == Try) {
    1670        1142 :             if (!emitTryEnd())
    1671           0 :                 return false;
    1672             :         } else {
    1673           0 :             MOZ_ASSERT(state_ == Catch);
    1674           0 :             if (!emitCatchEnd(true))
    1675           0 :                 return false;
    1676             :         }
    1677             : 
    1678        1142 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1679             : 
    1680        1142 :         if (retValKind_ == UseRetVal) {
    1681             :             // Clear the frame's return value that might have been set by the
    1682             :             // try block:
    1683             :             //
    1684             :             //   eval("try { 1; throw 2 } catch(e) {}"); // undefined, not 1
    1685         467 :             if (!bce_->emit1(JSOP_UNDEFINED))
    1686           0 :                 return false;
    1687         467 :             if (!bce_->emit1(JSOP_SETRVAL))
    1688           0 :                 return false;
    1689             :         }
    1690             : 
    1691        1142 :         state_ = Catch;
    1692        1142 :         return true;
    1693             :     }
    1694             : 
    1695             :   private:
    1696        1142 :     bool emitCatchEnd(bool hasNext) {
    1697        1142 :         MOZ_ASSERT(state_ == Catch);
    1698             : 
    1699        1142 :         if (!controlInfo_)
    1700         675 :             return true;
    1701             : 
    1702             :         // gosub <finally>, if required.
    1703         467 :         if (hasFinally()) {
    1704          19 :             if (!bce_->emitJump(JSOP_GOSUB, &controlInfo_->gosubs))
    1705           0 :                 return false;
    1706          19 :             MOZ_ASSERT(bce_->stackDepth == depth_);
    1707             :         }
    1708             : 
    1709             :         // Jump over the remaining catch blocks.  This will get fixed
    1710             :         // up to jump to after catch/finally.
    1711         467 :         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
    1712           0 :             return false;
    1713             : 
    1714             :         // If this catch block had a guard clause, patch the guard jump to
    1715             :         // come here.
    1716         467 :         if (controlInfo_->guardJump.offset != -1) {
    1717           0 :             if (!bce_->emitJumpTargetAndPatch(controlInfo_->guardJump))
    1718           0 :                 return false;
    1719           0 :             controlInfo_->guardJump.offset = -1;
    1720             : 
    1721             :             // If this catch block is the last one, rethrow, delegating
    1722             :             // execution of any finally block to the exception handler.
    1723           0 :             if (!hasNext) {
    1724           0 :                 if (!bce_->emit1(JSOP_EXCEPTION))
    1725           0 :                     return false;
    1726           0 :                 if (!bce_->emit1(JSOP_THROW))
    1727           0 :                     return false;
    1728             :             }
    1729             :         }
    1730             : 
    1731         467 :         return true;
    1732             :     }
    1733             : 
    1734             :   public:
    1735          64 :     bool emitFinally(const Maybe<uint32_t>& finallyPos = Nothing()) {
    1736             :         // If we are using controlInfo_ (i.e., emitting a syntactic try
    1737             :         // blocks), we must have specified up front if there will be a finally
    1738             :         // close. For internal try blocks, like those emitted for yield* and
    1739             :         // IteratorClose inside for-of loops, we can emitFinally even without
    1740             :         // specifying up front, since the internal try blocks emit no GOSUBs.
    1741          64 :         if (!controlInfo_) {
    1742          23 :             if (kind_ == TryCatch)
    1743          20 :                 kind_ = TryCatchFinally;
    1744             :         } else {
    1745          41 :             MOZ_ASSERT(hasFinally());
    1746             :         }
    1747             : 
    1748          64 :         if (state_ == Try) {
    1749          22 :             if (!emitTryEnd())
    1750           0 :                 return false;
    1751             :         } else {
    1752          42 :             MOZ_ASSERT(state_ == Catch);
    1753          42 :             if (!emitCatchEnd(false))
    1754           0 :                 return false;
    1755             :         }
    1756             : 
    1757          64 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1758             : 
    1759          64 :         if (!bce_->emitJumpTarget(&finallyStart_))
    1760           0 :             return false;
    1761             : 
    1762          64 :         if (controlInfo_) {
    1763             :             // Fix up the gosubs that might have been emitted before non-local
    1764             :             // jumps to the finally code.
    1765          41 :             bce_->patchJumpsToTarget(controlInfo_->gosubs, finallyStart_);
    1766             : 
    1767             :             // Indicate that we're emitting a subroutine body.
    1768          41 :             controlInfo_->setEmittingSubroutine();
    1769             :         }
    1770          64 :         if (finallyPos) {
    1771          41 :             if (!bce_->updateSourceCoordNotes(finallyPos.value()))
    1772           0 :                 return false;
    1773             :         }
    1774          64 :         if (!bce_->emit1(JSOP_FINALLY))
    1775           0 :             return false;
    1776             : 
    1777          64 :         if (retValKind_ == UseRetVal) {
    1778          41 :             if (!bce_->emit1(JSOP_GETRVAL))
    1779           0 :                 return false;
    1780             : 
    1781             :             // Clear the frame's return value to make break/continue return
    1782             :             // correct value even if there's no other statement before them:
    1783             :             //
    1784             :             //   eval("x: try { 1 } finally { break x; }"); // undefined, not 1
    1785          41 :             if (!bce_->emit1(JSOP_UNDEFINED))
    1786           0 :                 return false;
    1787          41 :             if (!bce_->emit1(JSOP_SETRVAL))
    1788           0 :                 return false;
    1789             :         }
    1790             : 
    1791          64 :         state_ = Finally;
    1792          64 :         return true;
    1793             :     }
    1794             : 
    1795             :   private:
    1796          64 :     bool emitFinallyEnd() {
    1797          64 :         MOZ_ASSERT(state_ == Finally);
    1798             : 
    1799          64 :         if (retValKind_ == UseRetVal) {
    1800          41 :             if (!bce_->emit1(JSOP_SETRVAL))
    1801           0 :                 return false;
    1802             :         }
    1803             : 
    1804          64 :         if (!bce_->emit1(JSOP_RETSUB))
    1805           0 :             return false;
    1806             : 
    1807          64 :         bce_->hasTryFinally = true;
    1808          64 :         return true;
    1809             :     }
    1810             : 
    1811             :   public:
    1812        1164 :     bool emitEnd() {
    1813        1164 :         if (state_ == Catch) {
    1814        1100 :             MOZ_ASSERT(!hasFinally());
    1815        1100 :             if (!emitCatchEnd(false))
    1816           0 :                 return false;
    1817             :         } else {
    1818          64 :             MOZ_ASSERT(state_ == Finally);
    1819          64 :             MOZ_ASSERT(hasFinally());
    1820          64 :             if (!emitFinallyEnd())
    1821           0 :                 return false;
    1822             :         }
    1823             : 
    1824        1164 :         MOZ_ASSERT(bce_->stackDepth == depth_);
    1825             : 
    1826             :         // ReconstructPCStack needs a NOP here to mark the end of the last
    1827             :         // catch block.
    1828        1164 :         if (!bce_->emit1(JSOP_NOP))
    1829           0 :             return false;
    1830             : 
    1831             :         // Fix up the end-of-try/catch jumps to come here.
    1832        1164 :         if (!bce_->emitJumpTargetAndPatch(catchAndFinallyJump_))
    1833           0 :             return false;
    1834             : 
    1835             :         // Add the try note last, to let post-order give us the right ordering
    1836             :         // (first to last for a given nesting level, inner to outer by level).
    1837        1164 :         if (hasCatch()) {
    1838        1142 :             if (!bce_->tryNoteList.append(JSTRY_CATCH, depth_, tryStart_, tryEnd_.offset))
    1839           0 :                 return false;
    1840             :         }
    1841             : 
    1842             :         // If we've got a finally, mark try+catch region with additional
    1843             :         // trynote to catch exceptions (re)thrown from a catch block or
    1844             :         // for the try{}finally{} case.
    1845        1164 :         if (hasFinally()) {
    1846          64 :             if (!bce_->tryNoteList.append(JSTRY_FINALLY, depth_, tryStart_, finallyStart_.offset))
    1847           0 :                 return false;
    1848             :         }
    1849             : 
    1850        1164 :         state_ = End;
    1851        1164 :         return true;
    1852             :     }
    1853             : };
    1854             : 
    1855             : class MOZ_STACK_CLASS IfThenElseEmitter
    1856             : {
    1857             :     BytecodeEmitter* bce_;
    1858             :     JumpList jumpAroundThen_;
    1859             :     JumpList jumpsAroundElse_;
    1860             :     unsigned noteIndex_;
    1861             :     int32_t thenDepth_;
    1862             : #ifdef DEBUG
    1863             :     int32_t pushed_;
    1864             :     bool calculatedPushed_;
    1865             : #endif
    1866             :     enum State {
    1867             :         Start,
    1868             :         If,
    1869             :         Cond,
    1870             :         IfElse,
    1871             :         Else,
    1872             :         End
    1873             :     };
    1874             :     State state_;
    1875             : 
    1876             :   public:
    1877        9045 :     explicit IfThenElseEmitter(BytecodeEmitter* bce)
    1878        9045 :       : bce_(bce),
    1879             :         noteIndex_(-1),
    1880             :         thenDepth_(0),
    1881             : #ifdef DEBUG
    1882             :         pushed_(0),
    1883             :         calculatedPushed_(false),
    1884             : #endif
    1885        9045 :         state_(Start)
    1886        9045 :     {}
    1887             : 
    1888        9046 :     ~IfThenElseEmitter()
    1889        9046 :     {}
    1890             : 
    1891             :   private:
    1892        9215 :     bool emitIf(State nextState) {
    1893        9215 :         MOZ_ASSERT(state_ == Start || state_ == Else);
    1894        9215 :         MOZ_ASSERT(nextState == If || nextState == IfElse || nextState == Cond);
    1895             : 
    1896             :         // Clear jumpAroundThen_ offset that points previous JSOP_IFEQ.
    1897        9215 :         if (state_ == Else)
    1898         276 :             jumpAroundThen_ = JumpList();
    1899             : 
    1900             :         // Emit an annotated branch-if-false around the then part.
    1901        9215 :         SrcNoteType type = nextState == If ? SRC_IF : nextState == IfElse ? SRC_IF_ELSE : SRC_COND;
    1902        9215 :         if (!bce_->newSrcNote(type, &noteIndex_))
    1903           0 :             return false;
    1904        9215 :         if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_))
    1905           0 :             return false;
    1906             : 
    1907             :         // To restore stack depth in else part, save depth of the then part.
    1908             : #ifdef DEBUG
    1909             :         // If DEBUG, this is also necessary to calculate |pushed_|.
    1910        9215 :         thenDepth_ = bce_->stackDepth;
    1911             : #else
    1912             :         if (nextState == IfElse || nextState == Cond)
    1913             :             thenDepth_ = bce_->stackDepth;
    1914             : #endif
    1915        9215 :         state_ = nextState;
    1916        9215 :         return true;
    1917             :     }
    1918             : 
    1919             :   public:
    1920        6826 :     bool emitIf() {
    1921        6826 :         return emitIf(If);
    1922             :     }
    1923             : 
    1924         657 :     bool emitCond() {
    1925         657 :         return emitIf(Cond);
    1926             :     }
    1927             : 
    1928        1732 :     bool emitIfElse() {
    1929        1732 :         return emitIf(IfElse);
    1930             :     }
    1931             : 
    1932        2389 :     bool emitElse() {
    1933        2389 :         MOZ_ASSERT(state_ == IfElse || state_ == Cond);
    1934             : 
    1935        2389 :         calculateOrCheckPushed();
    1936             : 
    1937             :         // Emit a jump from the end of our then part around the else part. The
    1938             :         // patchJumpsToTarget call at the bottom of this function will fix up
    1939             :         // the offset with jumpsAroundElse value.
    1940        2389 :         if (!bce_->emitJump(JSOP_GOTO, &jumpsAroundElse_))
    1941           0 :             return false;
    1942             : 
    1943             :         // Ensure the branch-if-false comes here, then emit the else.
    1944        2389 :         if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
    1945           0 :             return false;
    1946             : 
    1947             :         // Annotate SRC_IF_ELSE or SRC_COND with the offset from branch to
    1948             :         // jump, for IonMonkey's benefit.  We can't just "back up" from the pc
    1949             :         // of the else clause, because we don't know whether an extended
    1950             :         // jump was required to leap from the end of the then clause over
    1951             :         // the else clause.
    1952        2389 :         if (!bce_->setSrcNoteOffset(noteIndex_, 0,
    1953        2389 :                                     jumpsAroundElse_.offset - jumpAroundThen_.offset))
    1954             :         {
    1955           0 :             return false;
    1956             :         }
    1957             : 
    1958             :         // Restore stack depth of the then part.
    1959        2389 :         bce_->stackDepth = thenDepth_;
    1960        2389 :         state_ = Else;
    1961        2389 :         return true;
    1962             :     }
    1963             : 
    1964        8939 :     bool emitEnd() {
    1965        8939 :         MOZ_ASSERT(state_ == If || state_ == Else);
    1966             : 
    1967        8939 :         calculateOrCheckPushed();
    1968             : 
    1969        8939 :         if (state_ == If) {
    1970             :             // No else part, fixup the branch-if-false to come here.
    1971        6826 :             if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
    1972           0 :                 return false;
    1973             :         }
    1974             : 
    1975             :         // Patch all the jumps around else parts.
    1976        8939 :         if (!bce_->emitJumpTargetAndPatch(jumpsAroundElse_))
    1977           0 :             return false;
    1978             : 
    1979        8939 :         state_ = End;
    1980        8939 :         return true;
    1981             :     }
    1982             : 
    1983       11328 :     void calculateOrCheckPushed() {
    1984             : #ifdef DEBUG
    1985       11328 :         if (!calculatedPushed_) {
    1986        8939 :             pushed_ = bce_->stackDepth - thenDepth_;
    1987        8939 :             calculatedPushed_ = true;
    1988             :         } else {
    1989        2389 :             MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
    1990             :         }
    1991             : #endif
    1992       11328 :     }
    1993             : 
    1994             : #ifdef DEBUG
    1995         876 :     int32_t pushed() const {
    1996         876 :         return pushed_;
    1997             :     }
    1998             : 
    1999             :     int32_t popped() const {
    2000             :         return -pushed_;
    2001             :     }
    2002             : #endif
    2003             : };
    2004             : 
    2005         336 : class ForOfLoopControl : public LoopControl
    2006             : {
    2007             :     // The stack depth of the iterator.
    2008             :     int32_t iterDepth_;
    2009             : 
    2010             :     // for-of loops, when throwing from non-iterator code (i.e. from the body
    2011             :     // or from evaluating the LHS of the loop condition), need to call
    2012             :     // IteratorClose.  This is done by enclosing non-iterator code with
    2013             :     // try-catch and call IteratorClose in `catch` block.
    2014             :     // If IteratorClose itself throws, we must not re-call IteratorClose. Since
    2015             :     // non-local jumps like break and return call IteratorClose, whenever a
    2016             :     // non-local jump is emitted, we must tell catch block not to perform
    2017             :     // IteratorClose.
    2018             :     //
    2019             :     //   for (x of y) {
    2020             :     //     // Operations for iterator (IteratorNext etc) are outside of
    2021             :     //     // try-block.
    2022             :     //     try {
    2023             :     //       ...
    2024             :     //       if (...) {
    2025             :     //         // Before non-local jump, clear iterator on the stack to tell
    2026             :     //         // catch block not to perform IteratorClose.
    2027             :     //         tmpIterator = iterator;
    2028             :     //         iterator = undefined;
    2029             :     //         IteratorClose(tmpIterator, { break });
    2030             :     //         break;
    2031             :     //       }
    2032             :     //       ...
    2033             :     //     } catch (e) {
    2034             :     //       // Just throw again when iterator is cleared by non-local jump.
    2035             :     //       if (iterator === undefined)
    2036             :     //         throw e;
    2037             :     //       IteratorClose(iterator, { throw, e });
    2038             :     //     }
    2039             :     //   }
    2040             :     Maybe<TryEmitter> tryCatch_;
    2041             : 
    2042             :     // Used to track if any yields were emitted between calls to to
    2043             :     // emitBeginCodeNeedingIteratorClose and emitEndCodeNeedingIteratorClose.
    2044             :     uint32_t numYieldsAtBeginCodeNeedingIterClose_;
    2045             : 
    2046             :     bool allowSelfHosted_;
    2047             : 
    2048             :     IteratorKind iterKind_;
    2049             : 
    2050             :   public:
    2051         336 :     ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted,
    2052             :                      IteratorKind iterKind)
    2053         336 :       : LoopControl(bce, StatementKind::ForOfLoop),
    2054             :         iterDepth_(iterDepth),
    2055             :         numYieldsAtBeginCodeNeedingIterClose_(UINT32_MAX),
    2056             :         allowSelfHosted_(allowSelfHosted),
    2057         336 :         iterKind_(iterKind)
    2058             :     {
    2059         336 :     }
    2060             : 
    2061         336 :     bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
    2062         672 :         tryCatch_.emplace(bce, TryEmitter::TryCatch, TryEmitter::DontUseRetVal,
    2063         336 :                           TryEmitter::DontUseControl);
    2064             : 
    2065         336 :         if (!tryCatch_->emitTry())
    2066           0 :             return false;
    2067             : 
    2068         336 :         MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
    2069         336 :         numYieldsAtBeginCodeNeedingIterClose_ = bce->yieldAndAwaitOffsetList.numYields;
    2070             : 
    2071         336 :         return true;
    2072             :     }
    2073             : 
    2074         336 :     bool emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
    2075         336 :         if (!tryCatch_->emitCatch())              // ITER ...
    2076           0 :             return false;
    2077             : 
    2078         336 :         if (!bce->emit1(JSOP_EXCEPTION))          // ITER ... EXCEPTION
    2079           0 :             return false;
    2080         336 :         unsigned slotFromTop = bce->stackDepth - iterDepth_;
    2081         336 :         if (!bce->emitDupAt(slotFromTop))         // ITER ... EXCEPTION ITER
    2082           0 :             return false;
    2083             : 
    2084             :         // If ITER is undefined, it means the exception is thrown by
    2085             :         // IteratorClose for non-local jump, and we should't perform
    2086             :         // IteratorClose again here.
    2087         336 :         if (!bce->emit1(JSOP_UNDEFINED))          // ITER ... EXCEPTION ITER UNDEF
    2088           0 :             return false;
    2089         336 :         if (!bce->emit1(JSOP_STRICTNE))           // ITER ... EXCEPTION NE
    2090           0 :             return false;
    2091             : 
    2092         672 :         IfThenElseEmitter ifIteratorIsNotClosed(bce);
    2093         336 :         if (!ifIteratorIsNotClosed.emitIf())      // ITER ... EXCEPTION
    2094           0 :             return false;
    2095             : 
    2096         336 :         MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
    2097         336 :         if (!bce->emitDupAt(slotFromTop))         // ITER ... EXCEPTION ITER
    2098           0 :             return false;
    2099         336 :         if (!emitIteratorClose(bce, CompletionKind::Throw)) // ITER ... EXCEPTION
    2100           0 :             return false;
    2101             : 
    2102         336 :         if (!ifIteratorIsNotClosed.emitEnd())     // ITER ... EXCEPTION
    2103           0 :             return false;
    2104             : 
    2105         336 :         if (!bce->emit1(JSOP_THROW))              // ITER ...
    2106           0 :             return false;
    2107             : 
    2108             :         // If any yields were emitted, then this for-of loop is inside a star
    2109             :         // generator and must handle the case of Generator.return. Like in
    2110             :         // yield*, it is handled with a finally block.
    2111         336 :         uint32_t numYieldsEmitted = bce->yieldAndAwaitOffsetList.numYields;
    2112         336 :         if (numYieldsEmitted > numYieldsAtBeginCodeNeedingIterClose_) {
    2113          20 :             if (!tryCatch_->emitFinally())
    2114           0 :                 return false;
    2115             : 
    2116          40 :             IfThenElseEmitter ifGeneratorClosing(bce);
    2117          20 :             if (!bce->emit1(JSOP_ISGENCLOSING))   // ITER ... FTYPE FVALUE CLOSING
    2118           0 :                 return false;
    2119          20 :             if (!ifGeneratorClosing.emitIf())     // ITER ... FTYPE FVALUE
    2120           0 :                 return false;
    2121          20 :             if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER
    2122           0 :                 return false;
    2123          20 :             if (!emitIteratorClose(bce, CompletionKind::Normal)) // ITER ... FTYPE FVALUE
    2124           0 :                 return false;
    2125          20 :             if (!ifGeneratorClosing.emitEnd())    // ITER ... FTYPE FVALUE
    2126           0 :                 return false;
    2127             :         }
    2128             : 
    2129         336 :         if (!tryCatch_->emitEnd())
    2130           0 :             return false;
    2131             : 
    2132         336 :         tryCatch_.reset();
    2133         336 :         numYieldsAtBeginCodeNeedingIterClose_ = UINT32_MAX;
    2134             : 
    2135         336 :         return true;
    2136             :     }
    2137             : 
    2138         413 :     bool emitIteratorClose(BytecodeEmitter* bce,
    2139             :                            CompletionKind completionKind = CompletionKind::Normal) {
    2140         413 :         ptrdiff_t start = bce->offset();
    2141         413 :         if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_))
    2142           0 :             return false;
    2143         413 :         ptrdiff_t end = bce->offset();
    2144         413 :         return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
    2145             :     }
    2146             : 
    2147          57 :     bool emitPrepareForNonLocalJump(BytecodeEmitter* bce, bool isTarget) {
    2148             :         // Pop unnecessary value from the stack.  Effectively this means
    2149             :         // leaving try-catch block.  However, the performing IteratorClose can
    2150             :         // reach the depth for try-catch, and effectively re-enter the
    2151             :         // try-catch block.
    2152          57 :         if (!bce->emit1(JSOP_POP))                        // ITER
    2153           0 :             return false;
    2154             : 
    2155             :         // Clear ITER slot on the stack to tell catch block to avoid performing
    2156             :         // IteratorClose again.
    2157          57 :         if (!bce->emit1(JSOP_UNDEFINED))                  // ITER UNDEF
    2158           0 :             return false;
    2159          57 :         if (!bce->emit1(JSOP_SWAP))                       // UNDEF ITER
    2160           0 :             return false;
    2161             : 
    2162          57 :         if (!emitIteratorClose(bce))                      // UNDEF
    2163           0 :             return false;
    2164             : 
    2165          57 :         if (isTarget) {
    2166             :             // At the level of the target block, there's bytecode after the
    2167             :             // loop that will pop the iterator and the value, so push
    2168             :             // an undefined to balance the stack.
    2169          11 :             if (!bce->emit1(JSOP_UNDEFINED))              // UNDEF UNDEF
    2170           0 :                 return false;
    2171             :         } else {
    2172          46 :             if (!bce->emit1(JSOP_POP))                    //
    2173           0 :                 return false;
    2174             :         }
    2175             : 
    2176          57 :         return true;
    2177             :     }
    2178             : };
    2179             : 
    2180        5673 : BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
    2181             :                                  const EitherParser<FullParseHandler>& parser, SharedContext* sc,
    2182             :                                  HandleScript script, Handle<LazyScript*> lazyScript,
    2183        5673 :                                  uint32_t lineNum, EmitterMode emitterMode)
    2184             :   : sc(sc),
    2185        5673 :     cx(sc->context),
    2186             :     parent(parent),
    2187             :     script(cx, script),
    2188             :     lazyScript(cx, lazyScript),
    2189        5673 :     prologue(cx, lineNum),
    2190        5673 :     main(cx, lineNum),
    2191        5673 :     current(&main),
    2192             :     parser(parser),
    2193        5673 :     atomIndices(cx->frontendCollectionPool()),
    2194             :     firstLine(lineNum),
    2195             :     maxFixedSlots(0),
    2196             :     maxStackDepth(0),
    2197             :     stackDepth(0),
    2198             :     arrayCompDepth(0),
    2199             :     emitLevel(0),
    2200             :     bodyScopeIndex(UINT32_MAX),
    2201             :     varEmitterScope(nullptr),
    2202             :     innermostNestableControl(nullptr),
    2203             :     innermostEmitterScope(nullptr),
    2204             :     innermostTDZCheckCache(nullptr),
    2205        5673 :     constList(cx),
    2206        5673 :     scopeList(cx),
    2207        5673 :     tryNoteList(cx),
    2208        5673 :     scopeNoteList(cx),
    2209        5673 :     yieldAndAwaitOffsetList(cx),
    2210             :     typesetCount(0),
    2211             :     hasSingletons(false),
    2212             :     hasTryFinally(false),
    2213             :     emittingRunOnceLambda(false),
    2214             :     emitterMode(emitterMode),
    2215       62403 :     functionBodyEndPosSet(false)
    2216             : {
    2217        5673 :     MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
    2218        5673 : }
    2219             : 
    2220        5389 : BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
    2221             :                                  const EitherParser<FullParseHandler>& parser, SharedContext* sc,
    2222             :                                  HandleScript script, Handle<LazyScript*> lazyScript,
    2223        5389 :                                  TokenPos bodyPosition, EmitterMode emitterMode)
    2224             :     : BytecodeEmitter(parent, parser, sc, script, lazyScript,
    2225        5389 :                       parser.tokenStream().srcCoords.lineNum(bodyPosition.begin),
    2226       10778 :                       emitterMode)
    2227             : {
    2228        5389 :     setFunctionBodyEndPos(bodyPosition);
    2229        5389 : }
    2230             : 
    2231             : bool
    2232        5673 : BytecodeEmitter::init()
    2233             : {
    2234        5673 :     return atomIndices.acquire(cx);
    2235             : }
    2236             : 
    2237             : template <typename Predicate /* (NestableControl*) -> bool */>
    2238             : BytecodeEmitter::NestableControl*
    2239             : BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
    2240             : {
    2241             :     return NestableControl::findNearest(innermostNestableControl, predicate);
    2242             : }
    2243             : 
    2244             : template <typename T>
    2245             : T*
    2246        6004 : BytecodeEmitter::findInnermostNestableControl() const
    2247             : {
    2248        6004 :     return NestableControl::findNearest<T>(innermostNestableControl);
    2249             : }
    2250             : 
    2251             : template <typename T, typename Predicate /* (T*) -> bool */>
    2252             : T*
    2253         479 : BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
    2254             : {
    2255         479 :     return NestableControl::findNearest<T>(innermostNestableControl, predicate);
    2256             : }
    2257             : 
    2258             : NameLocation
    2259       89957 : BytecodeEmitter::lookupName(JSAtom* name)
    2260             : {
    2261       89957 :     return innermostEmitterScope->lookup(this, name);
    2262             : }
    2263             : 
    2264             : Maybe<NameLocation>
    2265        6694 : BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
    2266             : {
    2267        6694 :     return innermostEmitterScope->locationBoundInScope(this, name, target);
    2268             : }
    2269             : 
    2270             : Maybe<NameLocation>
    2271         479 : BytecodeEmitter::locationOfNameBoundInFunctionScope(JSAtom* name, EmitterScope* source)
    2272             : {
    2273         479 :     EmitterScope* funScope = source;
    2274        1089 :     while (!funScope->scope(this)->is<FunctionScope>())
    2275         305 :         funScope = funScope->enclosingInFrame();
    2276         479 :     return source->locationBoundInScope(this, name, funScope);
    2277             : }
    2278             : 
    2279             : bool
    2280      388624 : BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
    2281             : {
    2282      388624 :     *offset = code().length();
    2283             : 
    2284             :     // Start it off moderately large to avoid repeated resizings early on.
    2285             :     // ~98% of cases fit within 1024 bytes.
    2286      388624 :     if (code().capacity() == 0 && !code().reserve(1024))
    2287           0 :         return false;
    2288             : 
    2289      388624 :     if (!code().growBy(delta)) {
    2290           0 :         ReportOutOfMemory(cx);
    2291           0 :         return false;
    2292             :     }
    2293      388624 :     return true;
    2294             : }
    2295             : 
    2296             : void
    2297      388624 : BytecodeEmitter::updateDepth(ptrdiff_t target)
    2298             : {
    2299      388624 :     jsbytecode* pc = code(target);
    2300             : 
    2301      388624 :     int nuses = StackUses(nullptr, pc);
    2302      388624 :     int ndefs = StackDefs(nullptr, pc);
    2303             : 
    2304      388624 :     stackDepth -= nuses;
    2305      388624 :     MOZ_ASSERT(stackDepth >= 0);
    2306      388624 :     stackDepth += ndefs;
    2307             : 
    2308      388624 :     if ((uint32_t)stackDepth > maxStackDepth)
    2309       24354 :         maxStackDepth = stackDepth;
    2310      388624 : }
    2311             : 
    2312             : #ifdef DEBUG
    2313             : bool
    2314      367346 : BytecodeEmitter::checkStrictOrSloppy(JSOp op)
    2315             : {
    2316      367346 :     if (IsCheckStrictOp(op) && !sc->strict())
    2317           0 :         return false;
    2318      367346 :     if (IsCheckSloppyOp(op) && sc->strict())
    2319           0 :         return false;
    2320      367346 :     return true;
    2321             : }
    2322             : #endif
    2323             : 
    2324             : bool
    2325      178487 : BytecodeEmitter::emit1(JSOp op)
    2326             : {
    2327      178487 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2328             : 
    2329             :     ptrdiff_t offset;
    2330      178487 :     if (!emitCheck(1, &offset))
    2331           0 :         return false;
    2332             : 
    2333      178487 :     jsbytecode* code = this->code(offset);
    2334      178487 :     code[0] = jsbytecode(op);
    2335      178487 :     updateDepth(offset);
    2336      178487 :     return true;
    2337             : }
    2338             : 
    2339             : bool
    2340        7109 : BytecodeEmitter::emit2(JSOp op, uint8_t op1)
    2341             : {
    2342        7109 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2343             : 
    2344             :     ptrdiff_t offset;
    2345        7109 :     if (!emitCheck(2, &offset))
    2346           0 :         return false;
    2347             : 
    2348        7109 :     jsbytecode* code = this->code(offset);
    2349        7109 :     code[0] = jsbytecode(op);
    2350        7109 :     code[1] = jsbytecode(op1);
    2351        7109 :     updateDepth(offset);
    2352        7109 :     return true;
    2353             : }
    2354             : 
    2355             : bool
    2356       23937 : BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
    2357             : {
    2358       23937 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2359             : 
    2360             :     /* These should filter through emitVarOp. */
    2361       23937 :     MOZ_ASSERT(!IsArgOp(op));
    2362       23937 :     MOZ_ASSERT(!IsLocalOp(op));
    2363             : 
    2364             :     ptrdiff_t offset;
    2365       23937 :     if (!emitCheck(3, &offset))
    2366           0 :         return false;
    2367             : 
    2368       23937 :     jsbytecode* code = this->code(offset);
    2369       23937 :     code[0] = jsbytecode(op);
    2370       23937 :     code[1] = op1;
    2371       23937 :     code[2] = op2;
    2372       23937 :     updateDepth(offset);
    2373       23937 :     return true;
    2374             : }
    2375             : 
    2376             : bool
    2377       75110 : BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset)
    2378             : {
    2379       75110 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2380       75110 :     ptrdiff_t length = 1 + ptrdiff_t(extra);
    2381             : 
    2382             :     ptrdiff_t off;
    2383       75110 :     if (!emitCheck(length, &off))
    2384           0 :         return false;
    2385             : 
    2386       75110 :     jsbytecode* code = this->code(off);
    2387       75110 :     code[0] = jsbytecode(op);
    2388             :     /* The remaining |extra| bytes are set by the caller */
    2389             : 
    2390             :     /*
    2391             :      * Don't updateDepth if op's use-count comes from the immediate
    2392             :      * operand yet to be stored in the extra bytes after op.
    2393             :      */
    2394       75110 :     if (CodeSpec[op].nuses >= 0)
    2395       75110 :         updateDepth(off);
    2396             : 
    2397       75110 :     if (offset)
    2398       74900 :         *offset = off;
    2399       75110 :     return true;
    2400             : }
    2401             : 
    2402             : bool
    2403       32532 : BytecodeEmitter::emitJumpTarget(JumpTarget* target)
    2404             : {
    2405       32532 :     ptrdiff_t off = offset();
    2406             : 
    2407             :     // Alias consecutive jump targets.
    2408       32532 :     if (off == current->lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
    2409        2050 :         target->offset = current->lastTarget.offset;
    2410        2050 :         return true;
    2411             :     }
    2412             : 
    2413       30482 :     target->offset = off;
    2414       30482 :     current->lastTarget.offset = off;
    2415       30482 :     if (!emit1(JSOP_JUMPTARGET))
    2416           0 :         return false;
    2417       30482 :     return true;
    2418             : }
    2419             : 
    2420             : void
    2421       19622 : JumpList::push(jsbytecode* code, ptrdiff_t jumpOffset)
    2422             : {
    2423       19622 :     SET_JUMP_OFFSET(&code[jumpOffset], offset - jumpOffset);
    2424       19622 :     offset = jumpOffset;
    2425       19622 : }
    2426             : 
    2427             : void
    2428       19251 : JumpList::patchAll(jsbytecode* code, JumpTarget target)
    2429             : {
    2430             :     ptrdiff_t delta;
    2431       38873 :     for (ptrdiff_t jumpOffset = offset; jumpOffset != -1; jumpOffset += delta) {
    2432       19622 :         jsbytecode* pc = &code[jumpOffset];
    2433       19622 :         MOZ_ASSERT(IsJumpOpcode(JSOp(*pc)) || JSOp(*pc) == JSOP_LABEL);
    2434       19622 :         delta = GET_JUMP_OFFSET(pc);
    2435       19622 :         MOZ_ASSERT(delta < 0);
    2436       19622 :         ptrdiff_t span = target.offset - jumpOffset;
    2437       19622 :         SET_JUMP_OFFSET(pc, span);
    2438             :     }
    2439       19251 : }
    2440             : 
    2441             : bool
    2442       19622 : BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump)
    2443             : {
    2444             :     ptrdiff_t offset;
    2445       19622 :     if (!emitCheck(5, &offset))
    2446           0 :         return false;
    2447             : 
    2448       19622 :     jsbytecode* code = this->code(offset);
    2449       19622 :     code[0] = jsbytecode(op);
    2450       19622 :     MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
    2451       19622 :     jump->push(this->code(0), offset);
    2452       19622 :     updateDepth(offset);
    2453       19622 :     return true;
    2454             : }
    2455             : 
    2456             : bool
    2457       18542 : BytecodeEmitter::emitJump(JSOp op, JumpList* jump)
    2458             : {
    2459       18542 :     if (!emitJumpNoFallthrough(op, jump))
    2460           0 :         return false;
    2461       18542 :     if (BytecodeFallsThrough(op)) {
    2462             :         JumpTarget fallthrough;
    2463       12403 :         if (!emitJumpTarget(&fallthrough))
    2464           0 :             return false;
    2465             :     }
    2466       18542 :     return true;
    2467             : }
    2468             : 
    2469             : bool
    2470        1080 : BytecodeEmitter::emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump, JumpTarget* fallthrough)
    2471             : {
    2472        1080 :     if (!emitJumpNoFallthrough(op, jump))
    2473           0 :         return false;
    2474        1080 :     patchJumpsToTarget(*jump, target);
    2475             : 
    2476             :     // Unconditionally create a fallthrough for closing iterators, and as a
    2477             :     // target for break statements.
    2478        1080 :     if (!emitJumpTarget(fallthrough))
    2479           0 :         return false;
    2480        1080 :     return true;
    2481             : }
    2482             : 
    2483             : void
    2484       19251 : BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target)
    2485             : {
    2486       19251 :     MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
    2487       19251 :     MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
    2488       19251 :     MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
    2489             :                   BytecodeIsJumpTarget(JSOp(*code(target.offset))));
    2490       19251 :     jump.patchAll(code(0), target);
    2491       19251 : }
    2492             : 
    2493             : bool
    2494       23298 : BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump)
    2495             : {
    2496       23298 :     if (jump.offset == -1)
    2497        7390 :         return true;
    2498             :     JumpTarget target;
    2499       15908 :     if (!emitJumpTarget(&target))
    2500           0 :         return false;
    2501       15908 :     patchJumpsToTarget(jump, target);
    2502       15908 :     return true;
    2503             : }
    2504             : 
    2505             : bool
    2506       23429 : BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
    2507             : {
    2508       23429 :     if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
    2509           0 :         return false;
    2510       23429 :     return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
    2511             : }
    2512             : 
    2513             : bool
    2514        2959 : BytecodeEmitter::emitDupAt(unsigned slotFromTop)
    2515             : {
    2516        2959 :     MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
    2517             : 
    2518        2959 :     if (slotFromTop == 0)
    2519         541 :         return emit1(JSOP_DUP);
    2520             : 
    2521        2418 :     if (slotFromTop >= JS_BIT(24)) {
    2522           0 :         reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
    2523           0 :         return false;
    2524             :     }
    2525             : 
    2526             :     ptrdiff_t off;
    2527        2418 :     if (!emitN(JSOP_DUPAT, 3, &off))
    2528           0 :         return false;
    2529             : 
    2530        2418 :     jsbytecode* pc = code(off);
    2531        2418 :     SET_UINT24(pc, slotFromTop);
    2532        2418 :     return true;
    2533             : }
    2534             : 
    2535             : bool
    2536         736 : BytecodeEmitter::emitPopN(unsigned n)
    2537             : {
    2538         736 :     MOZ_ASSERT(n != 0);
    2539             : 
    2540         736 :     if (n == 1)
    2541           0 :         return emit1(JSOP_POP);
    2542             : 
    2543             :     // 2 JSOP_POPs (2 bytes) are shorter than JSOP_POPN (3 bytes).
    2544         736 :     if (n == 2)
    2545         733 :         return emit1(JSOP_POP) && emit1(JSOP_POP);
    2546             : 
    2547           3 :     return emitUint16Operand(JSOP_POPN, n);
    2548             : }
    2549             : 
    2550             : bool
    2551        1177 : BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind)
    2552             : {
    2553        1177 :     return emit2(JSOP_CHECKISOBJ, uint8_t(kind));
    2554             : }
    2555             : 
    2556             : bool
    2557         336 : BytecodeEmitter::emitCheckIsCallable(CheckIsCallableKind kind)
    2558             : {
    2559         336 :     return emit2(JSOP_CHECKISCALLABLE, uint8_t(kind));
    2560             : }
    2561             : 
    2562             : static inline unsigned
    2563       66838 : LengthOfSetLine(unsigned line)
    2564             : {
    2565       66838 :     return 1 /* SN_SETLINE */ + (line > SN_4BYTE_OFFSET_MASK ? 4 : 1);
    2566             : }
    2567             : 
    2568             : /* Updates line number notes, not column notes. */
    2569             : bool
    2570      312313 : BytecodeEmitter::updateLineNumberNotes(uint32_t offset)
    2571             : {
    2572      312313 :     TokenStreamAnyChars* ts = &parser.tokenStream();
    2573             :     bool onThisLine;
    2574      312313 :     if (!ts->srcCoords.isOnThisLine(offset, currentLine(), &onThisLine)) {
    2575           0 :         ts->reportErrorNoOffset(JSMSG_OUT_OF_MEMORY);
    2576           0 :         return false;
    2577             :     }
    2578             : 
    2579      312313 :     if (!onThisLine) {
    2580       66838 :         unsigned line = ts->srcCoords.lineNum(offset);
    2581       66838 :         unsigned delta = line - currentLine();
    2582             : 
    2583             :         /*
    2584             :          * Encode any change in the current source line number by using
    2585             :          * either several SRC_NEWLINE notes or just one SRC_SETLINE note,
    2586             :          * whichever consumes less space.
    2587             :          *
    2588             :          * NB: We handle backward line number deltas (possible with for
    2589             :          * loops where the update part is emitted after the body, but its
    2590             :          * line number is <= any line number in the body) here by letting
    2591             :          * unsigned delta_ wrap to a very large number, which triggers a
    2592             :          * SRC_SETLINE.
    2593             :          */
    2594       66838 :         current->currentLine = line;
    2595       66838 :         current->lastColumn  = 0;
    2596       66838 :         if (delta >= LengthOfSetLine(line)) {
    2597       19611 :             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line)))
    2598           0 :                 return false;
    2599             :         } else {
    2600       60545 :             do {
    2601       60545 :                 if (!newSrcNote(SRC_NEWLINE))
    2602           0 :                     return false;
    2603             :             } while (--delta != 0);
    2604             :         }
    2605             :     }
    2606      312313 :     return true;
    2607             : }
    2608             : 
    2609             : /* Updates the line number and column number information in the source notes. */
    2610             : bool
    2611       85525 : BytecodeEmitter::updateSourceCoordNotes(uint32_t offset)
    2612             : {
    2613       85525 :     if (!updateLineNumberNotes(offset))
    2614           0 :         return false;
    2615             : 
    2616       85525 :     uint32_t columnIndex = parser.tokenStream().srcCoords.columnIndex(offset);
    2617       85525 :     ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(current->lastColumn);
    2618       85525 :     if (colspan != 0) {
    2619             :         // If the column span is so large that we can't store it, then just
    2620             :         // discard this information. This can happen with minimized or otherwise
    2621             :         // machine-generated code. Even gigantic column numbers are still
    2622             :         // valuable if you have a source map to relate them to something real;
    2623             :         // but it's better to fail soft here.
    2624       63975 :         if (!SN_REPRESENTABLE_COLSPAN(colspan))
    2625           0 :             return true;
    2626       63975 :         if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)))
    2627           0 :             return false;
    2628       63975 :         current->lastColumn = columnIndex;
    2629             :     }
    2630       85525 :     return true;
    2631             : }
    2632             : 
    2633             : bool
    2634        1074 : BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
    2635             : {
    2636        1074 :     if (nextpn) {
    2637             :         /*
    2638             :          * Try to give the JSOP_LOOPHEAD the same line number as the next
    2639             :          * instruction. nextpn is often a block, in which case the next
    2640             :          * instruction typically comes from the first statement inside.
    2641             :          */
    2642         644 :         if (nextpn->isKind(PNK_LEXICALSCOPE))
    2643         576 :             nextpn = nextpn->scopeBody();
    2644         644 :         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
    2645         644 :         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
    2646         575 :             nextpn = nextpn->pn_head;
    2647         644 :         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
    2648           0 :             return false;
    2649             :     }
    2650             : 
    2651        1074 :     *top = { offset() };
    2652        1074 :     return emit1(JSOP_LOOPHEAD);
    2653             : }
    2654             : 
    2655             : bool
    2656        1074 : BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
    2657             : {
    2658        1074 :     if (nextpn) {
    2659             :         /* Update the line number, as for LOOPHEAD. */
    2660         960 :         if (nextpn->isKind(PNK_LEXICALSCOPE))
    2661           9 :             nextpn = nextpn->scopeBody();
    2662         960 :         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
    2663         960 :         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
    2664           9 :             nextpn = nextpn->pn_head;
    2665         960 :         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
    2666           0 :             return false;
    2667             :     }
    2668             : 
    2669        1074 :     JumpTarget entry{ offset() };
    2670        1074 :     patchJumpsToTarget(entryJump, entry);
    2671             : 
    2672        1074 :     LoopControl& loopInfo = innermostNestableControl->as<LoopControl>();
    2673        1074 :     MOZ_ASSERT(loopInfo.loopDepth() > 0);
    2674             : 
    2675        1074 :     uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loopInfo.loopDepth(),
    2676        2148 :                                                                loopInfo.canIonOsr());
    2677        1074 :     return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
    2678             : }
    2679             : 
    2680             : void
    2681      121549 : BytecodeEmitter::checkTypeSet(JSOp op)
    2682             : {
    2683      121549 :     if (CodeSpec[op].format & JOF_TYPESET) {
    2684       82592 :         if (typesetCount < UINT16_MAX)
    2685       82592 :             typesetCount++;
    2686             :     }
    2687      121549 : }
    2688             : 
    2689             : bool
    2690         508 : BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
    2691             : {
    2692         508 :     MOZ_ASSERT(operand <= UINT16_MAX);
    2693         508 :     if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand)))
    2694           0 :         return false;
    2695         508 :     checkTypeSet(op);
    2696         508 :     return true;
    2697             : }
    2698             : 
    2699             : bool
    2700        2124 : BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand)
    2701             : {
    2702             :     ptrdiff_t off;
    2703        2124 :     if (!emitN(op, 4, &off))
    2704           0 :         return false;
    2705        2124 :     SET_UINT32(code(off), operand);
    2706        2124 :     checkTypeSet(op);
    2707        2124 :     return true;
    2708             : }
    2709             : 
    2710             : namespace {
    2711             : 
    2712             : class NonLocalExitControl
    2713             : {
    2714             :   public:
    2715             :     enum Kind
    2716             :     {
    2717             :         // IteratorClose is handled especially inside the exception unwinder.
    2718             :         Throw,
    2719             : 
    2720             :         // A 'continue' statement does not call IteratorClose for the loop it
    2721             :         // is continuing, i.e. excluding the target loop.
    2722             :         Continue,
    2723             : 
    2724             :         // A 'break' or 'return' statement does call IteratorClose for the
    2725             :         // loop it is breaking out of or returning from, i.e. including the
    2726             :         // target loop.
    2727             :         Break,
    2728             :         Return
    2729             :     };
    2730             : 
    2731             :   private:
    2732             :     BytecodeEmitter* bce_;
    2733             :     const uint32_t savedScopeNoteIndex_;
    2734             :     const int savedDepth_;
    2735             :     uint32_t openScopeNoteIndex_;
    2736             :     Kind kind_;
    2737             : 
    2738             :     NonLocalExitControl(const NonLocalExitControl&) = delete;
    2739             : 
    2740             :     MOZ_MUST_USE bool leaveScope(BytecodeEmitter::EmitterScope* scope);
    2741             : 
    2742             :   public:
    2743        6764 :     NonLocalExitControl(BytecodeEmitter* bce, Kind kind)
    2744        6764 :       : bce_(bce),
    2745        6764 :         savedScopeNoteIndex_(bce->scopeNoteList.length()),
    2746        6764 :         savedDepth_(bce->stackDepth),
    2747        6764 :         openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex()),
    2748       27056 :         kind_(kind)
    2749        6764 :     { }
    2750             : 
    2751       13528 :     ~NonLocalExitControl() {
    2752        8819 :         for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length(); n++)
    2753        2055 :             bce_->scopeNoteList.recordEnd(n, bce_->offset(), bce_->inPrologue());
    2754        6764 :         bce_->stackDepth = savedDepth_;
    2755        6764 :     }
    2756             : 
    2757             :     MOZ_MUST_USE bool prepareForNonLocalJump(BytecodeEmitter::NestableControl* target);
    2758             : 
    2759        6164 :     MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
    2760        6164 :         return prepareForNonLocalJump(nullptr);
    2761             :     }
    2762             : };
    2763             : 
    2764             : bool
    2765        2055 : NonLocalExitControl::leaveScope(BytecodeEmitter::EmitterScope* es)
    2766             : {
    2767        2055 :     if (!es->leave(bce_, /* nonLocal = */ true))
    2768           0 :         return false;
    2769             : 
    2770             :     // As we pop each scope due to the non-local jump, emit notes that
    2771             :     // record the extent of the enclosing scope. These notes will have
    2772             :     // their ends recorded in ~NonLocalExitControl().
    2773        2055 :     uint32_t enclosingScopeIndex = ScopeNote::NoScopeIndex;
    2774        2055 :     if (es->enclosingInFrame())
    2775        2055 :         enclosingScopeIndex = es->enclosingInFrame()->index();
    2776        2055 :     if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(), bce_->inPrologue(),
    2777             :                                     openScopeNoteIndex_))
    2778           0 :         return false;
    2779        2055 :     openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
    2780             : 
    2781        2055 :     return true;
    2782             : }
    2783             : 
    2784             : /*
    2785             :  * Emit additional bytecode(s) for non-local jumps.
    2786             :  */
    2787             : bool
    2788        6764 : NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* target)
    2789             : {
    2790             :     using NestableControl = BytecodeEmitter::NestableControl;
    2791             :     using EmitterScope = BytecodeEmitter::EmitterScope;
    2792             : 
    2793        6764 :     EmitterScope* es = bce_->innermostEmitterScope;
    2794        6764 :     int npops = 0;
    2795             : 
    2796             :     // For 'continue', 'break', and 'return' statements, emit IteratorClose
    2797             :     // bytecode inline. 'continue' statements do not call IteratorClose for
    2798             :     // the loop they are continuing.
    2799        6764 :     bool emitIteratorClose = kind_ == Continue || kind_ == Break || kind_ == Return;
    2800        6764 :     bool emitIteratorCloseAtTarget = emitIteratorClose && kind_ != Continue;
    2801             : 
    2802       13652 :     auto flushPops = [&npops](BytecodeEmitter* bce) {
    2803        6826 :         if (npops && !bce->emitPopN(npops))
    2804           0 :             return false;
    2805        6826 :         npops = 0;
    2806        6826 :         return true;
    2807        6764 :     };
    2808             : 
    2809             :     // Walk the nestable control stack and patch jumps.
    2810        7849 :     for (NestableControl* control = bce_->innermostNestableControl;
    2811        7849 :          control != target;
    2812        1085 :          control = control->enclosing())
    2813             :     {
    2814             :         // Walk the scope stack and leave the scopes we entered. Leaving a scope
    2815             :         // may emit administrative ops like JSOP_POPLEXICALENV but never anything
    2816             :         // that manipulates the stack.
    2817        1539 :         for (; es != control->emitterScope(); es = es->enclosingInFrame()) {
    2818         227 :             if (!leaveScope(es))
    2819           0 :                 return false;
    2820             :         }
    2821             : 
    2822        1085 :         switch (control->kind()) {
    2823             :           case StatementKind::Finally: {
    2824          16 :             TryFinallyControl& finallyControl = control->as<TryFinallyControl>();
    2825          16 :             if (finallyControl.emittingSubroutine()) {
    2826             :                 /*
    2827             :                  * There's a [exception or hole, retsub pc-index] pair and the
    2828             :                  * possible return value on the stack that we need to pop.
    2829             :                  */
    2830           0 :                 npops += 3;
    2831             :             } else {
    2832          16 :                 if (!flushPops(bce_))
    2833           0 :                     return false;
    2834          16 :                 if (!bce_->emitJump(JSOP_GOSUB, &finallyControl.gosubs)) // ...
    2835           0 :                     return false;
    2836             :             }
    2837          16 :             break;
    2838             :           }
    2839             : 
    2840             :           case StatementKind::ForOfLoop:
    2841          46 :             if (emitIteratorClose) {
    2842          46 :                 if (!flushPops(bce_))
    2843           0 :                     return false;
    2844             : 
    2845          46 :                 ForOfLoopControl& loopinfo = control->as<ForOfLoopControl>();
    2846          46 :                 if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ false)) // ...
    2847           0 :                     return false;
    2848             :             } else {
    2849           0 :                 npops += 2;
    2850             :             }
    2851          46 :             break;
    2852             : 
    2853             :           case StatementKind::ForInLoop:
    2854           0 :             if (!flushPops(bce_))
    2855           0 :                 return false;
    2856             : 
    2857             :             // The iterator and the current value are on the stack.
    2858           0 :             if (!bce_->emit1(JSOP_POP))                   // ... ITER
    2859           0 :                 return false;
    2860           0 :             if (!bce_->emit1(JSOP_ENDITER))               // ...
    2861           0 :                 return false;
    2862           0 :             break;
    2863             : 
    2864             :           default:
    2865        1023 :             break;
    2866             :         }
    2867             :     }
    2868             : 
    2869        6764 :     if (!flushPops(bce_))
    2870           0 :         return false;
    2871             : 
    2872        6764 :     if (target && emitIteratorCloseAtTarget && target->is<ForOfLoopControl>()) {
    2873          11 :         ForOfLoopControl& loopinfo = target->as<ForOfLoopControl>();
    2874          11 :         if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ true)) // ... UNDEF UNDEF
    2875           0 :             return false;
    2876             :     }
    2877             : 
    2878        6764 :     EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope;
    2879       10420 :     for (; es != targetEmitterScope; es = es->enclosingInFrame()) {
    2880        1828 :         if (!leaveScope(es))
    2881           0 :             return false;
    2882             :     }
    2883             : 
    2884        6764 :     return true;
    2885             : }
    2886             : 
    2887             : }  // anonymous namespace
    2888             : 
    2889             : bool
    2890         600 : BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteType noteType)
    2891             : {
    2892             :     NonLocalExitControl nle(this, noteType == SRC_CONTINUE
    2893             :                                   ? NonLocalExitControl::Continue
    2894        1200 :                                   : NonLocalExitControl::Break);
    2895             : 
    2896         600 :     if (!nle.prepareForNonLocalJump(target))
    2897           0 :         return false;
    2898             : 
    2899         600 :     if (noteType != SRC_NULL) {
    2900         600 :         if (!newSrcNote(noteType))
    2901           0 :             return false;
    2902             :     }
    2903             : 
    2904         600 :     return emitJump(JSOP_GOTO, jumplist);
    2905             : }
    2906             : 
    2907             : Scope*
    2908        2981 : BytecodeEmitter::innermostScope() const
    2909             : {
    2910        2981 :     return innermostEmitterScope->scope(this);
    2911             : }
    2912             : 
    2913             : bool
    2914       13156 : BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
    2915             : {
    2916       13156 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2917             : 
    2918       13156 :     const size_t len = 1 + UINT32_INDEX_LEN;
    2919       13156 :     MOZ_ASSERT(len == size_t(CodeSpec[op].length));
    2920             : 
    2921             :     ptrdiff_t offset;
    2922       13156 :     if (!emitCheck(len, &offset))
    2923           0 :         return false;
    2924             : 
    2925       13156 :     jsbytecode* code = this->code(offset);
    2926       13156 :     code[0] = jsbytecode(op);
    2927       13156 :     SET_UINT32_INDEX(code, index);
    2928       13156 :     checkTypeSet(op);
    2929       13156 :     updateDepth(offset);
    2930       13156 :     return true;
    2931             : }
    2932             : 
    2933             : bool
    2934       69547 : BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
    2935             : {
    2936       69547 :     MOZ_ASSERT(checkStrictOrSloppy(op));
    2937             : 
    2938       69547 :     const size_t len = CodeSpec[op].length;
    2939       69547 :     MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
    2940             : 
    2941             :     ptrdiff_t offset;
    2942       69547 :     if (!emitCheck(len, &offset))
    2943           0 :         return false;
    2944             : 
    2945       69547 :     jsbytecode* code = this->code(offset);
    2946       69547 :     code[0] = jsbytecode(op);
    2947       69547 :     SET_UINT32_INDEX(code, index);
    2948       69547 :     checkTypeSet(op);
    2949       69547 :     updateDepth(offset);
    2950       69547 :     return true;
    2951             : }
    2952             : 
    2953             : bool
    2954       64667 : BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op)
    2955             : {
    2956       64667 :     MOZ_ASSERT(atom);
    2957       64667 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
    2958             : 
    2959             :     // .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of
    2960             :     // JSOP_GETNAME etc, to bypass |with| objects on the scope chain.
    2961             :     // It's safe to emit .this lookups though because |with| objects skip
    2962             :     // those.
    2963       64667 :     MOZ_ASSERT_IF(op == JSOP_GETNAME || op == JSOP_GETGNAME,
    2964             :                   atom != cx->names().dotGenerator);
    2965             : 
    2966       64667 :     if (op == JSOP_GETPROP && atom == cx->names().length) {
    2967             :         /* Specialize length accesses for the interpreter. */
    2968        1232 :         op = JSOP_LENGTH;
    2969             :     }
    2970             : 
    2971             :     uint32_t index;
    2972       64667 :     if (!makeAtomIndex(atom, &index))
    2973           0 :         return false;
    2974             : 
    2975       64667 :     return emitIndexOp(op, index);
    2976             : }
    2977             : 
    2978             : bool
    2979       37557 : BytecodeEmitter::emitAtomOp(ParseNode* pn, JSOp op)
    2980             : {
    2981       37557 :     MOZ_ASSERT(pn->pn_atom != nullptr);
    2982       37557 :     return emitAtomOp(pn->pn_atom, op);
    2983             : }
    2984             : 
    2985             : bool
    2986         465 : BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op)
    2987             : {
    2988         465 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE);
    2989         465 :     MOZ_ASSERT(index < scopeList.length());
    2990         465 :     return emitIndex32(op, index);
    2991             : }
    2992             : 
    2993             : bool
    2994         488 : BytecodeEmitter::emitInternedObjectOp(uint32_t index, JSOp op)
    2995             : {
    2996         488 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
    2997         488 :     MOZ_ASSERT(index < objectList.length);
    2998         488 :     return emitIndex32(op, index);
    2999             : }
    3000             : 
    3001             : bool
    3002         487 : BytecodeEmitter::emitObjectOp(ObjectBox* objbox, JSOp op)
    3003             : {
    3004         487 :     return emitInternedObjectOp(objectList.add(objbox), op);
    3005             : }
    3006             : 
    3007             : bool
    3008           1 : BytecodeEmitter::emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op)
    3009             : {
    3010           1 :     uint32_t index = objectList.add(objbox1);
    3011           1 :     objectList.add(objbox2);
    3012           1 :     return emitInternedObjectOp(index, op);
    3013             : }
    3014             : 
    3015             : bool
    3016         172 : BytecodeEmitter::emitRegExp(uint32_t index)
    3017             : {
    3018         172 :     return emitIndex32(JSOP_REGEXP, index);
    3019             : }
    3020             : 
    3021             : bool
    3022       47040 : BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot)
    3023             : {
    3024       47040 :     MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD);
    3025       47040 :     MOZ_ASSERT(IsLocalOp(op));
    3026             : 
    3027             :     ptrdiff_t off;
    3028       47040 :     if (!emitN(op, LOCALNO_LEN, &off))
    3029           0 :         return false;
    3030             : 
    3031       47040 :     SET_LOCALNO(code(off), slot);
    3032       47040 :     return true;
    3033             : }
    3034             : 
    3035             : bool
    3036       14802 : BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot)
    3037             : {
    3038       14802 :     MOZ_ASSERT(IsArgOp(op));
    3039             :     ptrdiff_t off;
    3040       14802 :     if (!emitN(op, ARGNO_LEN, &off))
    3041           0 :         return false;
    3042             : 
    3043       14802 :     SET_ARGNO(code(off), slot);
    3044       14802 :     return true;
    3045             : }
    3046             : 
    3047             : bool
    3048        8054 : BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec)
    3049             : {
    3050        8054 :     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD);
    3051             : 
    3052        8054 :     unsigned n = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
    3053        8054 :     MOZ_ASSERT(int(n) + 1 /* op */ == CodeSpec[op].length);
    3054             : 
    3055             :     ptrdiff_t off;
    3056        8054 :     if (!emitN(op, n, &off))
    3057           0 :         return false;
    3058             : 
    3059        8054 :     jsbytecode* pc = code(off);
    3060        8054 :     SET_ENVCOORD_HOPS(pc, ec.hops());
    3061        8054 :     pc += ENVCOORD_HOPS_LEN;
    3062        8054 :     SET_ENVCOORD_SLOT(pc, ec.slot());
    3063        8054 :     pc += ENVCOORD_SLOT_LEN;
    3064        8054 :     checkTypeSet(op);
    3065        8054 :     return true;
    3066             : }
    3067             : 
    3068             : static JSOp
    3069         705 : GetIncDecInfo(ParseNodeKind kind, bool* post)
    3070             : {
    3071         705 :     MOZ_ASSERT(kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT ||
    3072             :                kind == PNK_POSTDECREMENT || kind == PNK_PREDECREMENT);
    3073         705 :     *post = kind == PNK_POSTINCREMENT || kind == PNK_POSTDECREMENT;
    3074         705 :     return (kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT) ? JSOP_ADD : JSOP_SUB;
    3075             : }
    3076             : 
    3077             : JSOp
    3078         452 : BytecodeEmitter::strictifySetNameOp(JSOp op)
    3079             : {
    3080         452 :     switch (op) {
    3081             :       case JSOP_SETNAME:
    3082          35 :         if (sc->strict())
    3083          35 :             op = JSOP_STRICTSETNAME;
    3084          35 :         break;
    3085             :       case JSOP_SETGNAME:
    3086         417 :         if (sc->strict())
    3087         333 :             op = JSOP_STRICTSETGNAME;
    3088         417 :         break;
    3089             :         default:;
    3090             :     }
    3091         452 :     return op;
    3092             : }
    3093             : 
    3094             : bool
    3095       14039 : BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
    3096             : {
    3097       14039 :     if (!CheckRecursionLimit(cx))
    3098           0 :         return false;
    3099             : 
    3100             :  restart:
    3101             : 
    3102       14039 :     switch (pn->getKind()) {
    3103             :       // Trivial cases with no side effects.
    3104             :       case PNK_NOP:
    3105             :       case PNK_STRING:
    3106             :       case PNK_TEMPLATE_STRING:
    3107             :       case PNK_REGEXP:
    3108             :       case PNK_TRUE:
    3109             :       case PNK_FALSE:
    3110             :       case PNK_NULL:
    3111             :       case PNK_RAW_UNDEFINED:
    3112             :       case PNK_ELISION:
    3113             :       case PNK_GENERATOR:
    3114             :       case PNK_NUMBER:
    3115             :       case PNK_OBJECT_PROPERTY_NAME:
    3116         107 :         MOZ_ASSERT(pn->isArity(PN_NULLARY));
    3117         107 :         *answer = false;
    3118         107 :         return true;
    3119             : 
    3120             :       // |this| can throw in derived class constructors, including nested arrow
    3121             :       // functions or eval.
    3122             :       case PNK_THIS:
    3123           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3124           0 :         *answer = sc->needsThisTDZChecks();
    3125           0 :         return true;
    3126             : 
    3127             :       // Trivial binary nodes with more token pos holders.
    3128             :       case PNK_NEWTARGET:
    3129           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3130           0 :         MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
    3131           0 :         MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
    3132           0 :         *answer = false;
    3133           0 :         return true;
    3134             : 
    3135             :       case PNK_BREAK:
    3136             :       case PNK_CONTINUE:
    3137             :       case PNK_DEBUGGER:
    3138           0 :         MOZ_ASSERT(pn->isArity(PN_NULLARY));
    3139           0 :         *answer = true;
    3140           0 :         return true;
    3141             : 
    3142             :       // Watch out for getters!
    3143             :       case PNK_DOT:
    3144           3 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3145           3 :         *answer = true;
    3146           3 :         return true;
    3147             : 
    3148             :       // Unary cases with side effects only if the child has them.
    3149             :       case PNK_TYPEOFEXPR:
    3150             :       case PNK_VOID:
    3151             :       case PNK_NOT:
    3152           6 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3153           6 :         return checkSideEffects(pn->pn_kid, answer);
    3154             : 
    3155             :       // Even if the name expression is effect-free, performing ToPropertyKey on
    3156             :       // it might not be effect-free:
    3157             :       //
    3158             :       //   RegExp.prototype.toString = () => { throw 42; };
    3159             :       //   ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
    3160             :       //
    3161             :       //   function Q() {
    3162             :       //     ({ [new.target]: 0 });
    3163             :       //   }
    3164             :       //   Q.toString = () => { throw 17; };
    3165             :       //   new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
    3166             :       case PNK_COMPUTED_NAME:
    3167           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3168           0 :         *answer = true;
    3169           0 :         return true;
    3170             : 
    3171             :       // Looking up or evaluating the associated name could throw.
    3172             :       case PNK_TYPEOFNAME:
    3173           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3174           0 :         *answer = true;
    3175           0 :         return true;
    3176             : 
    3177             :       // These unary cases have side effects on the enclosing object/array,
    3178             :       // sure.  But that's not the question this function answers: it's
    3179             :       // whether the operation may have a side effect on something *other* than
    3180             :       // the result of the overall operation in which it's embedded.  The
    3181             :       // answer to that is no, for an object literal having a mutated prototype
    3182             :       // and an array comprehension containing no other effectful operations
    3183             :       // only produce a value, without affecting anything else.
    3184             :       case PNK_MUTATEPROTO:
    3185             :       case PNK_ARRAYPUSH:
    3186           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3187           0 :         return checkSideEffects(pn->pn_kid, answer);
    3188             : 
    3189             :       // Unary cases with obvious side effects.
    3190             :       case PNK_PREINCREMENT:
    3191             :       case PNK_POSTINCREMENT:
    3192             :       case PNK_PREDECREMENT:
    3193             :       case PNK_POSTDECREMENT:
    3194             :       case PNK_THROW:
    3195         182 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3196         182 :         *answer = true;
    3197         182 :         return true;
    3198             : 
    3199             :       // These might invoke valueOf/toString, even with a subexpression without
    3200             :       // side effects!  Consider |+{ valueOf: null, toString: null }|.
    3201             :       case PNK_BITNOT:
    3202             :       case PNK_POS:
    3203             :       case PNK_NEG:
    3204           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3205           0 :         *answer = true;
    3206           0 :         return true;
    3207             : 
    3208             :       // This invokes the (user-controllable) iterator protocol.
    3209             :       case PNK_SPREAD:
    3210           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3211           0 :         *answer = true;
    3212           0 :         return true;
    3213             : 
    3214             :       case PNK_INITIALYIELD:
    3215             :       case PNK_YIELD_STAR:
    3216             :       case PNK_YIELD:
    3217             :       case PNK_AWAIT:
    3218         157 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3219         157 :         *answer = true;
    3220         157 :         return true;
    3221             : 
    3222             :       // Deletion generally has side effects, even if isolated cases have none.
    3223             :       case PNK_DELETENAME:
    3224             :       case PNK_DELETEPROP:
    3225             :       case PNK_DELETEELEM:
    3226          82 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3227          82 :         *answer = true;
    3228          82 :         return true;
    3229             : 
    3230             :       // Deletion of a non-Reference expression has side effects only through
    3231             :       // evaluating the expression.
    3232             :       case PNK_DELETEEXPR: {
    3233           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3234           0 :         ParseNode* expr = pn->pn_kid;
    3235           0 :         return checkSideEffects(expr, answer);
    3236             :       }
    3237             : 
    3238             :       case PNK_SEMI:
    3239           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3240           0 :         if (ParseNode* expr = pn->pn_kid)
    3241           0 :             return checkSideEffects(expr, answer);
    3242           0 :         *answer = false;
    3243           0 :         return true;
    3244             : 
    3245             :       // Binary cases with obvious side effects.
    3246             :       case PNK_ASSIGN:
    3247             :       case PNK_ADDASSIGN:
    3248             :       case PNK_SUBASSIGN:
    3249             :       case PNK_BITORASSIGN:
    3250             :       case PNK_BITXORASSIGN:
    3251             :       case PNK_BITANDASSIGN:
    3252             :       case PNK_LSHASSIGN:
    3253             :       case PNK_RSHASSIGN:
    3254             :       case PNK_URSHASSIGN:
    3255             :       case PNK_MULASSIGN:
    3256             :       case PNK_DIVASSIGN:
    3257             :       case PNK_MODASSIGN:
    3258             :       case PNK_POWASSIGN:
    3259             :       case PNK_SETTHIS:
    3260        5394 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3261        5394 :         *answer = true;
    3262        5394 :         return true;
    3263             : 
    3264             :       case PNK_STATEMENTLIST:
    3265             :       case PNK_CATCHLIST:
    3266             :       // Strict equality operations and logical operators are well-behaved and
    3267             :       // perform no conversions.
    3268             :       case PNK_OR:
    3269             :       case PNK_AND:
    3270             :       case PNK_STRICTEQ:
    3271             :       case PNK_STRICTNE:
    3272             :       // Any subexpression of a comma expression could be effectful.
    3273             :       case PNK_COMMA:
    3274           9 :         MOZ_ASSERT(pn->pn_count > 0);
    3275             :         MOZ_FALLTHROUGH;
    3276             :       // Subcomponents of a literal may be effectful.
    3277             :       case PNK_ARRAY:
    3278             :       case PNK_OBJECT:
    3279           9 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3280           9 :         for (ParseNode* item = pn->pn_head; item; item = item->pn_next) {
    3281           9 :             if (!checkSideEffects(item, answer))
    3282           0 :                 return false;
    3283           9 :             if (*answer)
    3284           9 :                 return true;
    3285             :         }
    3286           0 :         return true;
    3287             : 
    3288             :       // Most other binary operations (parsed as lists in SpiderMonkey) may
    3289             :       // perform conversions triggering side effects.  Math operations perform
    3290             :       // ToNumber and may fail invoking invalid user-defined toString/valueOf:
    3291             :       // |5 < { toString: null }|.  |instanceof| throws if provided a
    3292             :       // non-object constructor: |null instanceof null|.  |in| throws if given
    3293             :       // a non-object RHS: |5 in null|.
    3294             :       case PNK_BITOR:
    3295             :       case PNK_BITXOR:
    3296             :       case PNK_BITAND:
    3297             :       case PNK_EQ:
    3298             :       case PNK_NE:
    3299             :       case PNK_LT:
    3300             :       case PNK_LE:
    3301             :       case PNK_GT:
    3302             :       case PNK_GE:
    3303             :       case PNK_INSTANCEOF:
    3304             :       case PNK_IN:
    3305             :       case PNK_LSH:
    3306             :       case PNK_RSH:
    3307             :       case PNK_URSH:
    3308             :       case PNK_ADD:
    3309             :       case PNK_SUB:
    3310             :       case PNK_STAR:
    3311             :       case PNK_DIV:
    3312             :       case PNK_MOD:
    3313             :       case PNK_POW:
    3314           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3315           0 :         MOZ_ASSERT(pn->pn_count >= 2);
    3316           0 :         *answer = true;
    3317           0 :         return true;
    3318             : 
    3319             :       case PNK_COLON:
    3320             :       case PNK_CASE:
    3321           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3322           0 :         if (!checkSideEffects(pn->pn_left, answer))
    3323           0 :             return false;
    3324           0 :         if (*answer)
    3325           0 :             return true;
    3326           0 :         return checkSideEffects(pn->pn_right, answer);
    3327             : 
    3328             :       // More getters.
    3329             :       case PNK_ELEM:
    3330           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3331           0 :         *answer = true;
    3332           0 :         return true;
    3333             : 
    3334             :       // These affect visible names in this code, or in other code.
    3335             :       case PNK_IMPORT:
    3336             :       case PNK_EXPORT_FROM:
    3337             :       case PNK_EXPORT_DEFAULT:
    3338           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3339           0 :         *answer = true;
    3340           0 :         return true;
    3341             : 
    3342             :       // Likewise.
    3343             :       case PNK_EXPORT:
    3344           0 :         MOZ_ASSERT(pn->isArity(PN_UNARY));
    3345           0 :         *answer = true;
    3346           0 :         return true;
    3347             : 
    3348             :       // Every part of a loop might be effect-free, but looping infinitely *is*
    3349             :       // an effect.  (Language lawyer trivia: C++ says threads can be assumed
    3350             :       // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
    3351             :       // implementation's equivalent of the below could set |*answer = false;|
    3352             :       // if all loop sub-nodes set |*answer = false|!)
    3353             :       case PNK_DOWHILE:
    3354             :       case PNK_WHILE:
    3355             :       case PNK_FOR:
    3356             :       case PNK_COMPREHENSIONFOR:
    3357           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3358           0 :         *answer = true;
    3359           0 :         return true;
    3360             : 
    3361             :       // Declarations affect the name set of the relevant scope.
    3362             :       case PNK_VAR:
    3363             :       case PNK_CONST:
    3364             :       case PNK_LET:
    3365           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3366           0 :         *answer = true;
    3367           0 :         return true;
    3368             : 
    3369             :       case PNK_IF:
    3370             :       case PNK_CONDITIONAL:
    3371           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3372           0 :         if (!checkSideEffects(pn->pn_kid1, answer))
    3373           0 :             return false;
    3374           0 :         if (*answer)
    3375           0 :             return true;
    3376           0 :         if (!checkSideEffects(pn->pn_kid2, answer))
    3377           0 :             return false;
    3378           0 :         if (*answer)
    3379           0 :             return true;
    3380           0 :         if ((pn = pn->pn_kid3))
    3381           0 :             goto restart;
    3382           0 :         return true;
    3383             : 
    3384             :       // Function calls can invoke non-local code.
    3385             :       case PNK_NEW:
    3386             :       case PNK_CALL:
    3387             :       case PNK_TAGGED_TEMPLATE:
    3388             :       case PNK_SUPERCALL:
    3389        8092 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3390        8092 :         *answer = true;
    3391        8092 :         return true;
    3392             : 
    3393             :       // Classes typically introduce names.  Even if no name is introduced,
    3394             :       // the heritage and/or class body (through computed property names)
    3395             :       // usually have effects.
    3396             :       case PNK_CLASS:
    3397           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3398           0 :         *answer = true;
    3399           0 :         return true;
    3400             : 
    3401             :       // |with| calls |ToObject| on its expression and so throws if that value
    3402             :       // is null/undefined.
    3403             :       case PNK_WITH:
    3404           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3405           0 :         *answer = true;
    3406           0 :         return true;
    3407             : 
    3408             :       case PNK_RETURN:
    3409           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3410           0 :         *answer = true;
    3411           0 :         return true;
    3412             : 
    3413             :       case PNK_NAME:
    3414           7 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3415           7 :         *answer = true;
    3416           7 :         return true;
    3417             : 
    3418             :       // Shorthands could trigger getters: the |x| in the object literal in
    3419             :       // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
    3420             :       // one.  (Of course, it isn't necessary to use |with| for a shorthand to
    3421             :       // trigger a getter.)
    3422             :       case PNK_SHORTHAND:
    3423           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3424           0 :         *answer = true;
    3425           0 :         return true;
    3426             : 
    3427             :       case PNK_FUNCTION:
    3428           0 :         MOZ_ASSERT(pn->isArity(PN_CODE));
    3429             :         /*
    3430             :          * A named function, contrary to ES3, is no longer effectful, because
    3431             :          * we bind its name lexically (using JSOP_CALLEE) instead of creating
    3432             :          * an Object instance and binding a readonly, permanent property in it
    3433             :          * (the object and binding can be detected and hijacked or captured).
    3434             :          * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
    3435             :          */
    3436           0 :         *answer = false;
    3437           0 :         return true;
    3438             : 
    3439             :       case PNK_MODULE:
    3440           0 :         *answer = false;
    3441           0 :         return true;
    3442             : 
    3443             :       // Generator expressions have no side effects on their own.
    3444             :       case PNK_GENEXP:
    3445           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3446           0 :         *answer = false;
    3447           0 :         return true;
    3448             : 
    3449             :       case PNK_TRY:
    3450           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3451           0 :         if (!checkSideEffects(pn->pn_kid1, answer))
    3452           0 :             return false;
    3453           0 :         if (*answer)
    3454           0 :             return true;
    3455           0 :         if (ParseNode* catchList = pn->pn_kid2) {
    3456           0 :             MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
    3457           0 :             if (!checkSideEffects(catchList, answer))
    3458           0 :                 return false;
    3459           0 :             if (*answer)
    3460           0 :                 return true;
    3461             :         }
    3462           0 :         if (ParseNode* finallyBlock = pn->pn_kid3) {
    3463           0 :             if (!checkSideEffects(finallyBlock, answer))
    3464           0 :                 return false;
    3465             :         }
    3466           0 :         return true;
    3467             : 
    3468             :       case PNK_CATCH:
    3469           0 :         MOZ_ASSERT(pn->isArity(PN_TERNARY));
    3470           0 :         if (!checkSideEffects(pn->pn_kid1, answer))
    3471           0 :             return false;
    3472           0 :         if (*answer)
    3473           0 :             return true;
    3474           0 :         if (ParseNode* cond = pn->pn_kid2) {
    3475           0 :             if (!checkSideEffects(cond, answer))
    3476           0 :                 return false;
    3477           0 :             if (*answer)
    3478           0 :                 return true;
    3479             :         }
    3480           0 :         return checkSideEffects(pn->pn_kid3, answer);
    3481             : 
    3482             :       case PNK_SWITCH:
    3483           0 :         MOZ_ASSERT(pn->isArity(PN_BINARY));
    3484           0 :         if (!checkSideEffects(pn->pn_left, answer))
    3485           0 :             return false;
    3486           0 :         return *answer || checkSideEffects(pn->pn_right, answer);
    3487             : 
    3488             :       case PNK_LABEL:
    3489           0 :         MOZ_ASSERT(pn->isArity(PN_NAME));
    3490           0 :         return checkSideEffects(pn->expr(), answer);
    3491             : 
    3492             :       case PNK_LEXICALSCOPE:
    3493           0 :         MOZ_ASSERT(pn->isArity(PN_SCOPE));
    3494           0 :         return checkSideEffects(pn->scopeBody(), answer);
    3495             : 
    3496             :       // We could methodically check every interpolated expression, but it's
    3497             :       // probably not worth the trouble.  Treat template strings as effect-free
    3498             :       // only if they don't contain any substitutions.
    3499             :       case PNK_TEMPLATE_STRING_LIST:
    3500           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3501           0 :         MOZ_ASSERT(pn->pn_count > 0);
    3502           0 :         MOZ_ASSERT((pn->pn_count % 2) == 1,
    3503             :                    "template strings must alternate template and substitution "
    3504             :                    "parts");
    3505           0 :         *answer = pn->pn_count > 1;
    3506           0 :         return true;
    3507             : 
    3508             :       case PNK_ARRAYCOMP:
    3509           0 :         MOZ_ASSERT(pn->isArity(PN_LIST));
    3510           0 :         MOZ_ASSERT(pn->pn_count == 1);
    3511           0 :         return checkSideEffects(pn->pn_head, answer);
    3512             : 
    3513             :       // This should be unreachable but is left as-is for now.
    3514             :       case PNK_PARAMSBODY:
    3515           0 :         *answer = true;
    3516           0 :         return true;
    3517             : 
    3518             :       case PNK_FORIN:           // by PNK_FOR/PNK_COMPREHENSIONFOR
    3519             :       case PNK_FOROF:           // by PNK_FOR/PNK_COMPREHENSIONFOR
    3520             :       case PNK_FORHEAD:         // by PNK_FOR/PNK_COMPREHENSIONFOR
    3521             :       case PNK_CLASSMETHOD:     // by PNK_CLASS
    3522             :       case PNK_CLASSNAMES:      // by PNK_CLASS
    3523             :       case PNK_CLASSMETHODLIST: // by PNK_CLASS
    3524             :       case PNK_IMPORT_SPEC_LIST: // by PNK_IMPORT
    3525             :       case PNK_IMPORT_SPEC:      // by PNK_IMPORT
    3526             :       case PNK_EXPORT_BATCH_SPEC:// by PNK_EXPORT
    3527             :       case PNK_EXPORT_SPEC_LIST: // by PNK_EXPORT
    3528             :       case PNK_EXPORT_SPEC:      // by PNK_EXPORT
    3529             :       case PNK_CALLSITEOBJ:      // by PNK_TAGGED_TEMPLATE
    3530             :       case PNK_POSHOLDER:        // by PNK_NEWTARGET
    3531             :       case PNK_SUPERBASE:        // by PNK_ELEM and others
    3532           0 :         MOZ_CRASH("handled by parent nodes");
    3533             : 
    3534             :       case PNK_LIMIT: // invalid sentinel value
    3535           0 :         MOZ_CRASH("invalid node kind");
    3536             :     }
    3537             : 
    3538           0 :     MOZ_CRASH("invalid, unenumerated ParseNodeKind value encountered in "
    3539             :               "BytecodeEmitter::checkSideEffects");
    3540             : }
    3541             : 
    3542             : bool
    3543        5883 : BytecodeEmitter::isInLoop()
    3544             : {
    3545        5883 :     return findInnermostNestableControl<LoopControl>();
    3546             : }
    3547             : 
    3548             : bool
    3549        6575 : BytecodeEmitter::checkSingletonContext()
    3550             : {
    3551        6575 :     if (!script->treatAsRunOnce() || sc->isFunctionBox() || isInLoop())
    3552        5135 :         return false;
    3553        1440 :     hasSingletons = true;
    3554        1440 :     return true;
    3555             : }
    3556             : 
    3557             : bool
    3558        5842 : BytecodeEmitter::checkRunOnceContext()
    3559             : {
    3560        5842 :     return checkSingletonContext() || (!isInLoop() && isRunOnceLambda());
    3561             : }
    3562             : 
    3563             : bool
    3564         264 : BytecodeEmitter::needsImplicitThis()
    3565             : {
    3566             :     // Short-circuit if there is an enclosing 'with' scope.
    3567         264 :     if (sc->inWith())
    3568           0 :         return true;
    3569             : 
    3570             :     // Otherwise see if the current point is under a 'with'.
    3571         638 :     for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) {
    3572         374 :         if (es->scope(this)->kind() == ScopeKind::With)
    3573           0 :             return true;
    3574             :     }
    3575             : 
    3576         264 :     return false;
    3577             : }
    3578             : 
    3579             : bool
    3580         284 : BytecodeEmitter::maybeSetDisplayURL()
    3581             : {
    3582         284 :     if (tokenStream().hasDisplayURL()) {
    3583           2 :         if (!parser.ss()->setDisplayURL(cx, tokenStream().displayURL()))
    3584           0 :             return false;
    3585             :     }
    3586         284 :     return true;
    3587             : }
    3588             : 
    3589             : bool
    3590         284 : BytecodeEmitter::maybeSetSourceMap()
    3591             : {
    3592         284 :     if (tokenStream().hasSourceMapURL()) {
    3593           0 :         MOZ_ASSERT(!parser.ss()->hasSourceMapURL());
    3594           0 :         if (!parser.ss()->setSourceMapURL(cx, tokenStream().sourceMapURL()))
    3595           0 :             return false;
    3596             :     }
    3597             : 
    3598             :     /*
    3599             :      * Source map URLs passed as a compile option (usually via a HTTP source map
    3600             :      * header) override any source map urls passed as comment pragmas.
    3601             :      */
    3602         284 :     if (parser.options().sourceMapURL()) {
    3603             :         // Warn about the replacement, but use the new one.
    3604           0 :         if (parser.ss()->hasSourceMapURL()) {
    3605           0 :             if (!parser.reportNoOffset(ParseWarning, false, JSMSG_ALREADY_HAS_PRAGMA,
    3606           0 :                                        parser.ss()->filename(), "//# sourceMappingURL"))
    3607             :             {
    3608           0 :                 return false;
    3609             :             }
    3610             :         }
    3611             : 
    3612           0 :         if (!parser.ss()->setSourceMapURL(cx, parser.options().sourceMapURL()))
    3613           0 :             return false;
    3614             :     }
    3615             : 
    3616         284 :     return true;
    3617             : }
    3618             : 
    3619             : void
    3620         284 : BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext* cx)
    3621             : {
    3622             :     // Note: when parsing off thread the resulting scripts need to be handed to
    3623             :     // the debugger after rejoining to the active thread.
    3624         284 :     if (cx->helperThread())
    3625           0 :         return;
    3626             : 
    3627             :     // Lazy scripts are never top level (despite always being invoked with a
    3628             :     // nullptr parent), and so the hook should never be fired.
    3629         284 :     if (emitterMode != LazyFunction && !parent)
    3630         284 :         Debugger::onNewScript(cx, script);
    3631             : }
    3632             : 
    3633             : inline TokenStreamAnyChars&
    3634        6244 : BytecodeEmitter::tokenStream()
    3635             : {
    3636        6244 :     return parser.tokenStream();
    3637             : }
    3638             : 
    3639             : void
    3640           0 : BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
    3641             : {
    3642           0 :     TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
    3643             : 
    3644             :     va_list args;
    3645           0 :     va_start(args, errorNumber);
    3646             : 
    3647           0 :     ErrorMetadata metadata;
    3648           0 :     if (parser.computeErrorMetadata(&metadata, pos.begin))
    3649           0 :         ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
    3650             : 
    3651           0 :     va_end(args);
    3652           0 : }
    3653             : 
    3654             : bool
    3655           0 : BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
    3656             : {
    3657           0 :     TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
    3658             : 
    3659             :     va_list args;
    3660           0 :     va_start(args, errorNumber);
    3661             : 
    3662           0 :     bool result = parser.reportExtraWarningErrorNumberVA(nullptr, pos.begin, errorNumber, args);
    3663             : 
    3664           0 :     va_end(args);
    3665           0 :     return result;
    3666             : }
    3667             : 
    3668             : bool
    3669           0 : BytecodeEmitter::reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...)
    3670             : {
    3671           0 :     TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
    3672             : 
    3673             :     va_list args;
    3674           0 :     va_start(args, errorNumber);
    3675           0 :     bool result = parser.reportStrictModeErrorNumberVA(nullptr, pos.begin, sc->strict(),
    3676           0 :                                                        errorNumber, args);
    3677           0 :     va_end(args);
    3678           0 :     return result;
    3679             : }
    3680             : 
    3681             : bool
    3682        1656 : BytecodeEmitter::emitNewInit(JSProtoKey key)
    3683             : {
    3684        1656 :     const size_t len = 1 + UINT32_INDEX_LEN;
    3685             :     ptrdiff_t offset;
    3686        1656 :     if (!emitCheck(len, &offset))
    3687           0 :         return false;
    3688             : 
    3689        1656 :     jsbytecode* code = this->code(offset);
    3690        1656 :     code[0] = JSOP_NEWINIT;
    3691        1656 :     code[1] = jsbytecode(key);
    3692        1656 :     code[2] = 0;
    3693        1656 :     code[3] = 0;
    3694        1656 :     code[4] = 0;
    3695        1656 :     checkTypeSet(JSOP_NEWINIT);
    3696        1656 :     updateDepth(offset);
    3697        1656 :     return true;
    3698             : }
    3699             : 
    3700             : bool
    3701          33 : BytecodeEmitter::iteratorResultShape(unsigned* shape)
    3702             : {
    3703             :     // No need to do any guessing for the object kind, since we know exactly how
    3704             :     // many properties we plan to have.
    3705          33 :     gc::AllocKind kind = gc::GetGCObjectKind(2);
    3706          66 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
    3707          33 :     if (!obj)
    3708           0 :         return false;
    3709             : 
    3710          66 :     Rooted<jsid> value_id(cx, AtomToId(cx->names().value));
    3711          66 :     Rooted<jsid> done_id(cx, AtomToId(cx->names().done));
    3712          33 :     if (!NativeDefineProperty(cx, obj, value_id, UndefinedHandleValue, nullptr, nullptr,
    3713             :                               JSPROP_ENUMERATE))
    3714             :     {
    3715           0 :         return false;
    3716             :     }
    3717          33 :     if (!NativeDefineProperty(cx, obj, done_id, UndefinedHandleValue, nullptr, nullptr,
    3718             :                               JSPROP_ENUMERATE))
    3719             :     {
    3720           0 :         return false;
    3721             :     }
    3722             : 
    3723          33 :     ObjectBox* objbox = parser.newObjectBox(obj);
    3724          33 :     if (!objbox)
    3725           0 :         return false;
    3726             : 
    3727          33 :     *shape = objectList.add(objbox);
    3728             : 
    3729          33 :     return true;
    3730             : }
    3731             : 
    3732             : bool
    3733          33 : BytecodeEmitter::emitPrepareIteratorResult()
    3734             : {
    3735             :     unsigned shape;
    3736          33 :     if (!iteratorResultShape(&shape))
    3737           0 :         return false;
    3738          33 :     return emitIndex32(JSOP_NEWOBJECT, shape);
    3739             : }
    3740             : 
    3741             : bool
    3742          33 : BytecodeEmitter::emitFinishIteratorResult(bool done)
    3743             : {
    3744             :     uint32_t value_id;
    3745          33 :     if (!makeAtomIndex(cx->names().value, &value_id))
    3746           0 :         return false;
    3747             :     uint32_t done_id;
    3748          33 :     if (!makeAtomIndex(cx->names().done, &done_id))
    3749           0 :         return false;
    3750             : 
    3751          33 :     if (!emitIndex32(JSOP_INITPROP, value_id))
    3752           0 :         return false;
    3753          33 :     if (!emit1(done ? JSOP_TRUE : JSOP_FALSE))
    3754           0 :         return false;
    3755          33 :     if (!emitIndex32(JSOP_INITPROP, done_id))
    3756           0 :         return false;
    3757          33 :     return true;
    3758             : }
    3759             : 
    3760             : bool
    3761           0 : BytecodeEmitter::emitToIteratorResult(bool done)
    3762             : {
    3763           0 :     if (!emitPrepareIteratorResult())    // VALUE OBJ
    3764           0 :         return false;
    3765           0 :     if (!emit1(JSOP_SWAP))               // OBJ VALUE
    3766           0 :         return false;
    3767           0 :     if (!emitFinishIteratorResult(done)) // RESULT
    3768           0 :         return false;
    3769           0 :     return true;
    3770             : }
    3771             : 
    3772             : bool
    3773       70685 : BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bool callContext)
    3774             : {
    3775       70685 :     switch (loc.kind()) {
    3776             :       case NameLocation::Kind::Dynamic:
    3777        1395 :         if (!emitAtomOp(name, JSOP_GETNAME))
    3778           0 :             return false;
    3779        1395 :         break;
    3780             : 
    3781             :       case NameLocation::Kind::Global:
    3782       11113 :         if (!emitAtomOp(name, JSOP_GETGNAME))
    3783           0 :             return false;
    3784       11113 :         break;
    3785             : 
    3786             :       case NameLocation::Kind::Intrinsic:
    3787        9273 :         if (!emitAtomOp(name, JSOP_GETINTRINSIC))
    3788           0 :             return false;
    3789        9273 :         break;
    3790             : 
    3791             :       case NameLocation::Kind::NamedLambdaCallee:
    3792          25 :         if (!emit1(JSOP_CALLEE))
    3793           0 :             return false;
    3794          25 :         break;
    3795             : 
    3796             :       case NameLocation::Kind::Import:
    3797           0 :         if (!emitAtomOp(name, JSOP_GETIMPORT))
    3798           0 :             return false;
    3799           0 :         break;
    3800             : 
    3801             :       case NameLocation::Kind::ArgumentSlot:
    3802       14065 :         if (!emitArgOp(JSOP_GETARG, loc.argumentSlot()))
    3803           0 :             return false;
    3804       14065 :         break;
    3805             : 
    3806             :       case NameLocation::Kind::FrameSlot:
    3807       28813 :         if (loc.isLexical()) {
    3808        9809 :             if (!emitTDZCheckIfNeeded(name, loc))
    3809           0 :                 return false;
    3810             :         }
    3811       28813 :         if (!emitLocalOp(JSOP_GETLOCAL, loc.frameSlot()))
    3812           0 :             return false;
    3813       28813 :         break;
    3814             : 
    3815             :       case NameLocation::Kind::EnvironmentCoordinate:
    3816        6001 :         if (loc.isLexical()) {
    3817        1945 :             if (!emitTDZCheckIfNeeded(name, loc))
    3818           0 :                 return false;
    3819             :         }
    3820        6001 :         if (!emitEnvCoordOp(JSOP_GETALIASEDVAR, loc.environmentCoordinate()))
    3821           0 :             return false;
    3822        6001 :         break;
    3823             : 
    3824             :       case NameLocation::Kind::DynamicAnnexBVar:
    3825           0 :         MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
    3826             :     }
    3827             : 
    3828             :     // Need to provide |this| value for call.
    3829       70685 :     if (callContext) {
    3830        8545 :         switch (loc.kind()) {
    3831             :           case NameLocation::Kind::Dynamic: {
    3832         264 :             JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS;
    3833         264 :             if (!emitAtomOp(name, thisOp))
    3834           0 :                 return false;
    3835         264 :             break;
    3836             :           }
    3837             : 
    3838             :           case NameLocation::Kind::Global:
    3839         887 :             if (!emitAtomOp(name, JSOP_GIMPLICITTHIS))
    3840           0 :                 return false;
    3841         887 :             break;
    3842             : 
    3843             :           case NameLocation::Kind::Intrinsic:
    3844             :           case NameLocation::Kind::NamedLambdaCallee:
    3845             :           case NameLocation::Kind::Import:
    3846             :           case NameLocation::Kind::ArgumentSlot:
    3847             :           case NameLocation::Kind::FrameSlot:
    3848             :           case NameLocation::Kind::EnvironmentCoordinate:
    3849        7394 :             if (!emit1(JSOP_UNDEFINED))
    3850           0 :                 return false;
    3851        7394 :             break;
    3852             : 
    3853             :           case NameLocation::Kind::DynamicAnnexBVar:
    3854           0 :             MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
    3855             :         }
    3856             :     }
    3857             : 
    3858       70685 :     return true;
    3859             : }
    3860             : 
    3861             : bool
    3862       69149 : BytecodeEmitter::emitGetName(ParseNode* pn, bool callContext)
    3863             : {
    3864       69149 :     return emitGetName(pn->name(), callContext);
    3865             : }
    3866             : 
    3867             : template <typename RHSEmitter>
    3868             : bool
    3869       16995 : BytecodeEmitter::emitSetOrInitializeNameAtLocation(HandleAtom name, const NameLocation& loc,
    3870             :                                                    RHSEmitter emitRhs, bool initialize)
    3871             : {
    3872       16995 :     bool emittedBindOp = false;
    3873             : 
    3874       16995 :     switch (loc.kind()) {
    3875             :       case NameLocation::Kind::Dynamic:
    3876             :       case NameLocation::Kind::Import:
    3877             :       case NameLocation::Kind::DynamicAnnexBVar: {
    3878             :         uint32_t atomIndex;
    3879          35 :         if (!makeAtomIndex(name, &atomIndex))
    3880           0 :             return false;
    3881          35 :         if (loc.kind() == NameLocation::Kind::DynamicAnnexBVar) {
    3882             :             // Annex B vars always go on the nearest variable environment,
    3883             :             // even if lexical environments in between contain same-named
    3884             :             // bindings.
    3885           0 :             if (!emit1(JSOP_BINDVAR))
    3886           0 :                 return false;
    3887             :         } else {
    3888          35 :             if (!emitIndexOp(JSOP_BINDNAME, atomIndex))
    3889           0 :                 return false;
    3890             :         }
    3891          35 :         emittedBindOp = true;
    3892          35 :         if (!emitRhs(this, loc, emittedBindOp))
    3893           0 :             return false;
    3894          35 :         if (!emitIndexOp(strictifySetNameOp(JSOP_SETNAME), atomIndex))
    3895           0 :             return false;
    3896          35 :         break;
    3897             :       }
    3898             : 
    3899             :       case NameLocation::Kind::Global: {
    3900             :         JSOp op;
    3901             :         uint32_t atomIndex;
    3902        1587 :         if (!makeAtomIndex(name, &atomIndex))
    3903           0 :             return false;
    3904        1587 :         if (loc.isLexical() && initialize) {
    3905             :             // INITGLEXICAL always gets the global lexical scope. It doesn't
    3906             :             // need a BINDGNAME.
    3907        1170 :             MOZ_ASSERT(innermostScope()->is<GlobalScope>());
    3908        1170 :             op = JSOP_INITGLEXICAL;
    3909             :         } else {
    3910         417 :             if (!emitIndexOp(JSOP_BINDGNAME, atomIndex))
    3911           0 :                 return false;
    3912         417 :             emittedBindOp = true;
    3913         417 :             op = strictifySetNameOp(JSOP_SETGNAME);
    3914             :         }
    3915        1587 :         if (!emitRhs(this, loc, emittedBindOp))
    3916           0 :             return false;
    3917        1588 :         if (!emitIndexOp(op, atomIndex))
    3918           0 :             return false;
    3919        1588 :         break;
    3920             :       }
    3921             : 
    3922             :       case NameLocation::Kind::Intrinsic:
    3923          87 :         if (!emitRhs(this, loc, emittedBindOp))
    3924           0 :             return false;
    3925          87 :         if (!emitAtomOp(name, JSOP_SETINTRINSIC))
    3926           0 :             return false;
    3927          87 :         break;
    3928             : 
    3929             :       case NameLocation::Kind::NamedLambdaCallee:
    3930           0 :         if (!emitRhs(this, loc, emittedBindOp))
    3931           0 :             return false;
    3932             :         // Assigning to the named lambda is a no-op in sloppy mode but
    3933             :         // throws in strict mode.
    3934           0 :         if (sc->strict() && !emit1(JSOP_THROWSETCALLEE))
    3935           0 :             return false;
    3936           0 :         break;
    3937             : 
    3938             :       case NameLocation::Kind::ArgumentSlot: {
    3939             :         // If we assign to a positional formal parameter and the arguments
    3940             :         // object is unmapped (strict mode or function with
    3941             :         // default/rest/destructing args), parameters do not alias
    3942             :         // arguments[i], and to make the arguments object reflect initial
    3943             :         // parameter values prior to any mutation we create it eagerly
    3944             :         // whenever parameters are (or might, in the case of calls to eval)
    3945             :         // assigned.
    3946         265 :         FunctionBox* funbox = sc->asFunctionBox();
    3947         265 :         if (funbox->argumentsHasLocalBinding() && !funbox->hasMappedArgsObj())
    3948           1 :             funbox->setDefinitelyNeedsArgsObj();
    3949             : 
    3950         265 :         if (!emitRhs(this, loc, emittedBindOp))
    3951           0 :             return false;
    3952         265 :         if (!emitArgOp(JSOP_SETARG, loc.argumentSlot()))
    3953           0 :             return false;
    3954         265 :         break;
    3955             :       }
    3956             : 
    3957             :       case NameLocation::Kind::FrameSlot: {
    3958       13519 :         JSOp op = JSOP_SETLOCAL;
    3959       13519 :         if (!emitRhs(this, loc, emittedBindOp))
    3960           0 :             return false;
    3961       13519 :         if (loc.isLexical()) {
    3962        5182 :             if (initialize) {
    3963        4378 :                 op = JSOP_INITLEXICAL;
    3964             :             } else {
    3965         804 :                 if (loc.isConst())
    3966           0 :                     op = JSOP_THROWSETCONST;
    3967             : 
    3968         804 :                 if (!emitTDZCheckIfNeeded(name, loc))
    3969           0 :                     return false;
    3970             :             }
    3971             :         }
    3972       13519 :         if (!emitLocalOp(op, loc.frameSlot()))
    3973           0 :             return false;
    3974       13519 :         if (op == JSOP_INITLEXICAL) {
    3975        4378 :             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
    3976           0 :                 return false;
    3977             :         }
    3978       13519 :         break;
    3979             :       }
    3980             : 
    3981             :       case NameLocation::Kind::EnvironmentCoordinate: {
    3982        1502 :         JSOp op = JSOP_SETALIASEDVAR;
    3983        1502 :         if (!emitRhs(this, loc, emittedBindOp))
    3984           0 :             return false;
    3985        1502 :         if (loc.isLexical()) {
    3986         904 :             if (initialize) {
    3987         724 :                 op = JSOP_INITALIASEDLEXICAL;
    3988             :             } else {
    3989         180 :                 if (loc.isConst())
    3990           0 :                     op = JSOP_THROWSETALIASEDCONST;
    3991             : 
    3992         180 :                 if (!emitTDZCheckIfNeeded(name, loc))
    3993           0 :                     return false;
    3994             :             }
    3995             :         }
    3996        1502 :         if (loc.bindingKind() == BindingKind::NamedLambdaCallee) {
    3997             :             // Assigning to the named lambda is a no-op in sloppy mode and throws
    3998             :             // in strict mode.
    3999           0 :             op = JSOP_THROWSETALIASEDCONST;
    4000           0 :             if (sc->strict() && !emitEnvCoordOp(op, loc.environmentCoordinate()))
    4001           0 :                 return false;
    4002             :         } else {
    4003        1502 :             if (!emitEnvCoordOp(op, loc.environmentCoordinate()))
    4004           0 :                 return false;
    4005             :         }
    4006        1502 :         if (op == JSOP_INITALIASEDLEXICAL) {
    4007         724 :             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
    4008           0 :                 return false;
    4009             :         }
    4010        1502 :         break;
    4011             :       }
    4012             :     }
    4013             : 
    4014       16996 :     return true;
    4015             : }
    4016             : 
    4017             : bool
    4018       12738 : BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc)
    4019             : {
    4020             :     // Dynamic accesses have TDZ checks built into their VM code and should
    4021             :     // never emit explicit TDZ checks.
    4022       12738 :     MOZ_ASSERT(loc.hasKnownSlot());
    4023       12738 :     MOZ_ASSERT(loc.isLexical());
    4024             : 
    4025       25476 :     Maybe<MaybeCheckTDZ> check = innermostTDZCheckCache->needsTDZCheck(this, name);
    4026       12738 :     if (!check)
    4027           0 :         return false;
    4028             : 
    4029             :     // We've already emitted a check in this basic block.
    4030       12738 :     if (*check == DontCheckTDZ)
    4031       12186 :         return true;
    4032             : 
    4033         552 :     if (loc.kind() == NameLocation::Kind::FrameSlot) {
    4034           1 :         if (!emitLocalOp(JSOP_CHECKLEXICAL, loc.frameSlot()))
    4035           0 :             return false;
    4036             :     } else {
    4037         551 :         if (!emitEnvCoordOp(JSOP_CHECKALIASEDLEXICAL, loc.environmentCoordinate()))
    4038           0 :             return false;
    4039             :     }
    4040             : 
    4041         552 :     return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
    4042             : }
    4043             : 
    4044             : bool
    4045       21731 : BytecodeEmitter::emitPropLHS(ParseNode* pn)
    4046             : {
    4047       21731 :     MOZ_ASSERT(pn->isKind(PNK_DOT));
    4048       21731 :     MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
    4049             : 
    4050       21731 :     ParseNode* pn2 = pn->pn_expr;
    4051             : 
    4052             :     /*
    4053             :      * If the object operand is also a dotted property reference, reverse the
    4054             :      * list linked via pn_expr temporarily so we can iterate over it from the
    4055             :      * bottom up (reversing again as we go), to avoid excessive recursion.
    4056             :      */
    4057       21731 :     if (pn2->isKind(PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
    4058        3863 :         ParseNode* pndot = pn2;
    4059        3863 :         ParseNode* pnup = nullptr;
    4060             :         ParseNode* pndown;
    4061             :         for (;;) {
    4062             :             /* Reverse pndot->pn_expr to point up, not down. */
    4063        4279 :             pndown = pndot->pn_expr;
    4064        4071 :             pndot->pn_expr = pnup;
    4065        4071 :             if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
    4066        3863 :                 break;
    4067         208 :             pnup = pndot;
    4068         208 :             pndot = pndown;
    4069             :         }
    4070             : 
    4071             :         /* pndown is a primary expression, not a dotted property reference. */
    4072        3863 :         if (!emitTree(pndown))
    4073           0 :             return false;
    4074             : 
    4075        4071 :         do {
    4076             :             /* Walk back up the list, emitting annotated name ops. */
    4077        4071 :             if (!emitAtomOp(pndot, JSOP_GETPROP))
    4078           0 :                 return false;
    4079             : 
    4080             :             /* Reverse the pn_expr link again. */
    4081        4071 :             pnup = pndot->pn_expr;
    4082        4071 :             pndot->pn_expr = pndown;
    4083        4071 :             pndown = pndot;
    4084        4071 :         } while ((pndot = pnup) != nullptr);
    4085        3863 :         return true;
    4086             :     }
    4087             : 
    4088             :     // The non-optimized case.
    4089       17868 :     return emitTree(pn2);
    4090             : }
    4091             : 
    4092             : bool
    4093          13 : BytecodeEmitter::emitSuperPropLHS(ParseNode* superBase, bool isCall)
    4094             : {
    4095          13 :     if (!emitGetThisForSuperBase(superBase))
    4096           0 :         return false;
    4097          13 :     if (isCall && !emit1(JSOP_DUP))
    4098           0 :         return false;
    4099          13 :     if (!emit1(JSOP_SUPERBASE))
    4100           0 :         return false;
    4101          13 :     return true;
    4102             : }
    4103             : 
    4104             : bool
    4105       21712 : BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
    4106             : {
    4107       21712 :     MOZ_ASSERT(pn->isArity(PN_NAME));
    4108             : 
    4109       21712 :     if (!emitPropLHS(pn))
    4110           0 :         return false;
    4111             : 
    4112       21713 :     if (op == JSOP_CALLPROP && !emit1(JSOP_DUP))
    4113           0 :         return false;
    4114             : 
    4115       21713 :     if (!emitAtomOp(pn, op))
    4116           0 :         return false;
    4117             : 
    4118       21713 :     if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP))
    4119           0 :         return false;
    4120             : 
    4121       21713 :     return true;
    4122             : }
    4123             : 
    4124             : bool
    4125          13 : BytecodeEmitter::emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall)
    4126             : {
    4127          13 :     ParseNode* base = &pn->as<PropertyAccess>().expression();
    4128          13 :     if (!emitSuperPropLHS(base, isCall))
    4129           0 :         return false;
    4130             : 
    4131          13 :     if (!emitAtomOp(pn, op))
    4132           0 :         return false;
    4133             : 
    4134          13 :     if (isCall && !emit1(JSOP_SWAP))
    4135           0 :         return false;
    4136             : 
    4137          13 :     return true;
    4138             : }
    4139             : 
    4140             : bool
    4141          19 : BytecodeEmitter::emitPropIncDec(ParseNode* pn)
    4142             : {
    4143          19 :     MOZ_ASSERT(pn->pn_kid->isKind(PNK_DOT));
    4144             : 
    4145             :     bool post;
    4146          19 :     bool isSuper = pn->pn_kid->as<PropertyAccess>().isSuper();
    4147          19 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4148             : 
    4149          19 :     if (isSuper) {
    4150           0 :         ParseNode* base = &pn->pn_kid->as<PropertyAccess>().expression();
    4151           0 :         if (!emitSuperPropLHS(base))                // THIS OBJ
    4152           0 :             return false;
    4153           0 :         if (!emit1(JSOP_DUP2))                      // THIS OBJ THIS OBJ
    4154           0 :             return false;
    4155             :     } else {
    4156          19 :         if (!emitPropLHS(pn->pn_kid))               // OBJ
    4157           0 :             return false;
    4158          19 :         if (!emit1(JSOP_DUP))                       // OBJ OBJ
    4159           0 :             return false;
    4160             :     }
    4161          19 :     if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
    4162           0 :         return false;
    4163          19 :     if (!emit1(JSOP_POS))                           // OBJ N
    4164           0 :         return false;
    4165          19 :     if (post && !emit1(JSOP_DUP))                   // OBJ N? N
    4166           0 :         return false;
    4167          19 :     if (!emit1(JSOP_ONE))                           // OBJ N? N 1
    4168           0 :         return false;
    4169          19 :     if (!emit1(binop))                              // OBJ N? N+1
    4170           0 :         return false;
    4171             : 
    4172          19 :     if (post) {
    4173          14 :         if (!emit2(JSOP_PICK, 2 + isSuper))        // N? N+1 OBJ
    4174           0 :             return false;
    4175          14 :         if (!emit1(JSOP_SWAP))                     // N? OBJ N+1
    4176           0 :             return false;
    4177          14 :         if (isSuper) {
    4178           0 :             if (!emit2(JSOP_PICK, 3))              // N THIS N+1 OBJ
    4179           0 :                 return false;
    4180           0 :             if (!emit1(JSOP_SWAP))                 // N THIS OBJ N+1
    4181           0 :                 return false;
    4182             :         }
    4183             :     }
    4184             : 
    4185          38 :     JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
    4186          38 :                          : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
    4187          19 :     if (!emitAtomOp(pn->pn_kid, setOp))             // N? N+1
    4188           0 :         return false;
    4189          19 :     if (post && !emit1(JSOP_POP))                   // RESULT
    4190           0 :         return false;
    4191             : 
    4192          19 :     return true;
    4193             : }
    4194             : 
    4195             : bool
    4196        1045 : BytecodeEmitter::emitGetNameAtLocationForCompoundAssignment(JSAtom* name, const NameLocation& loc)
    4197             : {
    4198        1045 :     if (loc.kind() == NameLocation::Kind::Dynamic) {
    4199             :         // For dynamic accesses we need to emit GETBOUNDNAME instead of
    4200             :         // GETNAME for correctness: looking up @@unscopables on the
    4201             :         // environment chain (due to 'with' environments) must only happen
    4202             :         // once.
    4203             :         //
    4204             :         // GETBOUNDNAME uses the environment already pushed on the stack from
    4205             :         // the earlier BINDNAME.
    4206           0 :         if (!emit1(JSOP_DUP))                              // ENV ENV
    4207           0 :             return false;
    4208           0 :         if (!emitAtomOp(name, JSOP_GETBOUNDNAME))          // ENV V
    4209           0 :             return false;
    4210             :     } else {
    4211        1045 :         if (!emitGetNameAtLocation(name, loc))             // ENV? V
    4212           0 :             return false;
    4213             :     }
    4214             : 
    4215        1045 :     return true;
    4216             : }
    4217             : 
    4218             : bool
    4219         674 : BytecodeEmitter::emitNameIncDec(ParseNode* pn)
    4220             : {
    4221         674 :     MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME));
    4222             : 
    4223             :     bool post;
    4224         674 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4225             : 
    4226             :     auto emitRhs = [pn, post, binop](BytecodeEmitter* bce, const NameLocation& loc,
    4227         674 :                                      bool emittedBindOp)
    4228        2696 :     {
    4229         674 :         JSAtom* name = pn->pn_kid->name();
    4230         674 :         if (!bce->emitGetNameAtLocationForCompoundAssignment(name, loc)) // ENV? V
    4231           0 :             return false;
    4232         674 :         if (!bce->emit1(JSOP_POS))                         // ENV? N
    4233           0 :             return false;
    4234         674 :         if (post && !bce->emit1(JSOP_DUP))                 // ENV? N? N
    4235           0 :             return false;
    4236         674 :         if (!bce->emit1(JSOP_ONE))                         // ENV? N? N 1
    4237           0 :             return false;
    4238         674 :         if (!bce->emit1(binop))                            // ENV? N? N+1
    4239           0 :             return false;
    4240             : 
    4241         674 :         if (post && emittedBindOp) {
    4242           6 :             if (!bce->emit2(JSOP_PICK, 2))                 // N? N+1 ENV?
    4243           0 :                 return false;
    4244           6 :             if (!bce->emit1(JSOP_SWAP))                    // N? ENV? N+1
    4245           0 :                 return false;
    4246             :         }
    4247             : 
    4248         674 :         return true;
    4249         674 :     };
    4250             : 
    4251         674 :     if (!emitSetName(pn->pn_kid, emitRhs))
    4252           0 :         return false;
    4253             : 
    4254         674 :     if (post && !emit1(JSOP_POP))
    4255           0 :         return false;
    4256             : 
    4257         674 :     return true;
    4258             : }
    4259             : 
    4260             : bool
    4261        2821 : BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
    4262             : {
    4263        2821 :     MOZ_ASSERT(pn->isArity(PN_BINARY));
    4264             : 
    4265        2821 :     if (!emitTree(pn->pn_left))
    4266           0 :         return false;
    4267             : 
    4268        2821 :     if (opts == EmitElemOption::IncDec) {
    4269          12 :         if (!emit1(JSOP_CHECKOBJCOERCIBLE))
    4270           0 :             return false;
    4271        2809 :     } else if (opts == EmitElemOption::Call) {
    4272           8 :         if (!emit1(JSOP_DUP))
    4273           0 :             return false;
    4274             :     }
    4275             : 
    4276        2821 :     if (!emitTree(pn->pn_right))
    4277           0 :         return false;
    4278             : 
    4279        2821 :     if (opts == EmitElemOption::Set) {
    4280           0 :         if (!emit2(JSOP_PICK, 2))
    4281           0 :             return false;
    4282        2821 :     } else if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
    4283          40 :         if (!emit1(JSOP_TOID))
    4284           0 :             return false;
    4285             :     }
    4286        2821 :     return true;
    4287             : }
    4288             : 
    4289             : bool
    4290           0 : BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
    4291             : {
    4292           0 :     MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
    4293             : 
    4294             :     // The ordering here is somewhat screwy. We need to evaluate the propval
    4295             :     // first, by spec. Do a little dance to not emit more than one JSOP_THIS.
    4296             :     // Since JSOP_THIS might throw in derived class constructors, we cannot
    4297             :     // just push it earlier as the receiver. We have to swap it down instead.
    4298             : 
    4299           0 :     if (!emitTree(pn->pn_right))
    4300           0 :         return false;
    4301             : 
    4302             :     // We need to convert the key to an object id first, so that we do not do
    4303             :     // it inside both the GETELEM and the SETELEM.
    4304           0 :     if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
    4305           0 :         if (!emit1(JSOP_TOID))
    4306           0 :             return false;
    4307             :     }
    4308             : 
    4309           0 :     if (!emitGetThisForSuperBase(pn->pn_left))
    4310           0 :         return false;
    4311             : 
    4312           0 :     if (opts == EmitElemOption::Call) {
    4313           0 :         if (!emit1(JSOP_SWAP))
    4314           0 :             return false;
    4315             : 
    4316             :         // We need another |this| on top, also
    4317           0 :         if (!emitDupAt(1))
    4318           0 :             return false;
    4319             :     }
    4320             : 
    4321           0 :     if (!emit1(JSOP_SUPERBASE))
    4322           0 :         return false;
    4323             : 
    4324           0 :     if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 3))
    4325           0 :         return false;
    4326             : 
    4327           0 :     return true;
    4328             : }
    4329             : 
    4330             : bool
    4331        2993 : BytecodeEmitter::emitElemOpBase(JSOp op)
    4332             : {
    4333        2993 :     if (!emit1(op))
    4334           0 :         return false;
    4335             : 
    4336        2993 :     checkTypeSet(op);
    4337        2993 :     return true;
    4338             : }
    4339             : 
    4340             : bool
    4341        2469 : BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op)
    4342             : {
    4343        2469 :     EmitElemOption opts = EmitElemOption::Get;
    4344        2469 :     if (op == JSOP_CALLELEM)
    4345           8 :         opts = EmitElemOption::Call;
    4346        2461 :     else if (op == JSOP_SETELEM || op == JSOP_STRICTSETELEM)
    4347           0 :         opts = EmitElemOption::Set;
    4348             : 
    4349        2469 :     return emitElemOperands(pn, opts) && emitElemOpBase(op);
    4350             : }
    4351             : 
    4352             : bool
    4353           0 : BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
    4354             : {
    4355           0 :     EmitElemOption opts = EmitElemOption::Get;
    4356           0 :     if (isCall)
    4357           0 :         opts = EmitElemOption::Call;
    4358           0 :     else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
    4359           0 :         opts = EmitElemOption::Set;
    4360             : 
    4361           0 :     if (!emitSuperElemOperands(pn, opts))
    4362           0 :         return false;
    4363           0 :     if (!emitElemOpBase(op))
    4364           0 :         return false;
    4365             : 
    4366           0 :     if (isCall && !emit1(JSOP_SWAP))
    4367           0 :         return false;
    4368             : 
    4369           0 :     return true;
    4370             : }
    4371             : 
    4372             : bool
    4373          12 : BytecodeEmitter::emitElemIncDec(ParseNode* pn)
    4374             : {
    4375          12 :     MOZ_ASSERT(pn->pn_kid->isKind(PNK_ELEM));
    4376             : 
    4377          12 :     bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
    4378             : 
    4379             :     // We need to convert the key to an object id first, so that we do not do
    4380             :     // it inside both the GETELEM and the SETELEM. This is done by
    4381             :     // emit(Super)ElemOperands.
    4382          12 :     if (isSuper) {
    4383           0 :         if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
    4384           0 :             return false;
    4385             :     } else {
    4386          12 :         if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec))
    4387           0 :             return false;
    4388             :     }
    4389             : 
    4390             :     bool post;
    4391          12 :     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
    4392             : 
    4393             :     JSOp getOp;
    4394          12 :     if (isSuper) {
    4395             :         // There's no such thing as JSOP_DUP3, so we have to be creative.
    4396             :         // Note that pushing things again is no fewer JSOps.
    4397           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY
    4398           0 :             return false;
    4399           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS
    4400           0 :             return false;
    4401           0 :         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS OBJ
    4402           0 :             return false;
    4403           0 :         getOp = JSOP_GETELEM_SUPER;
    4404             :     } else {
    4405             :                                                         // OBJ KEY
    4406          12 :         if (!emit1(JSOP_DUP2))                          // OBJ KEY OBJ KEY
    4407           0 :             return false;
    4408          12 :         getOp = JSOP_GETELEM;
    4409             :     }
    4410          12 :     if (!emitElemOpBase(getOp))                         // OBJ KEY V
    4411           0 :         return false;
    4412          12 :     if (!emit1(JSOP_POS))                               // OBJ KEY N
    4413           0 :         return false;
    4414          12 :     if (post && !emit1(JSOP_DUP))                       // OBJ KEY N? N
    4415           0 :         return false;
    4416          12 :     if (!emit1(JSOP_ONE))                               // OBJ KEY N? N 1
    4417           0 :         return false;
    4418          12 :     if (!emit1(binop))                                  // OBJ KEY N? N+1
    4419           0 :         return false;
    4420             : 
    4421          12 :     if (post) {
    4422          12 :         if (isSuper) {
    4423             :             // We have one more value to rotate around, because of |this|
    4424             :             // on the stack
    4425           0 :             if (!emit2(JSOP_PICK, 4))
    4426           0 :                 return false;
    4427             :         }
    4428          12 :         if (!emit2(JSOP_PICK, 3 + isSuper))             // KEY N N+1 OBJ
    4429           0 :             return false;
    4430          12 :         if (!emit2(JSOP_PICK, 3 + isSuper))             // N N+1 OBJ KEY
    4431           0 :             return false;
    4432          12 :         if (!emit2(JSOP_PICK, 2 + isSuper))             // N OBJ KEY N+1
    4433           0 :             return false;
    4434             :     }
    4435             : 
    4436          24 :     JSOp setOp = isSuper ? (sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER)
    4437          24 :                          : (sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM);
    4438          12 :     if (!emitElemOpBase(setOp))                         // N? N+1
    4439           0 :         return false;
    4440          12 :     if (post && !emit1(JSOP_POP))                       // RESULT
    4441           0 :         return false;
    4442             : 
    4443          12 :     return true;
    4444             : }
    4445             : 
    4446             : bool
    4447           0 : BytecodeEmitter::emitCallIncDec(ParseNode* incDec)
    4448             : {
    4449           0 :     MOZ_ASSERT(incDec->isKind(PNK_PREINCREMENT) ||
    4450             :                incDec->isKind(PNK_POSTINCREMENT) ||
    4451             :                incDec->isKind(PNK_PREDECREMENT) ||
    4452             :                incDec->isKind(PNK_POSTDECREMENT));
    4453             : 
    4454           0 :     MOZ_ASSERT(incDec->pn_kid->isKind(PNK_CALL));
    4455             : 
    4456           0 :     ParseNode* call = incDec->pn_kid;
    4457           0 :     if (!emitTree(call))                                // CALLRESULT
    4458           0 :         return false;
    4459           0 :     if (!emit1(JSOP_POS))                               // N
    4460           0 :         return false;
    4461             : 
    4462             :     // The increment/decrement has no side effects, so proceed to throw for
    4463             :     // invalid assignment target.
    4464           0 :     return emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS);
    4465             : }
    4466             : 
    4467             : bool
    4468        8079 : BytecodeEmitter::emitNumberOp(double dval)
    4469             : {
    4470             :     int32_t ival;
    4471        8079 :     if (NumberIsInt32(dval, &ival)) {
    4472        8028 :         if (ival == 0)
    4473        2882 :             return emit1(JSOP_ZERO);
    4474        5146 :         if (ival == 1)
    4475        1375 :             return emit1(JSOP_ONE);
    4476        3771 :         if ((int)(int8_t)ival == ival)
    4477        3187 :             return emit2(JSOP_INT8, uint8_t(int8_t(ival)));
    4478             : 
    4479         584 :         uint32_t u = uint32_t(ival);
    4480         584 :         if (u < JS_BIT(16)) {
    4481         502 :             if (!emitUint16Operand(JSOP_UINT16, u))
    4482           0 :                 return false;
    4483          82 :         } else if (u < JS_BIT(24)) {
    4484             :             ptrdiff_t off;
    4485          38 :             if (!emitN(JSOP_UINT24, 3, &off))
    4486           0 :                 return false;
    4487          38 :             SET_UINT24(code(off), u);
    4488             :         } else {
    4489             :             ptrdiff_t off;
    4490          44 :             if (!emitN(JSOP_INT32, 4, &off))
    4491           0 :                 return false;
    4492          44 :             SET_INT32(code(off), ival);
    4493             :         }
    4494         584 :         return true;
    4495             :     }
    4496             : 
    4497          51 :     if (!constList.append(DoubleValue(dval)))
    4498           0 :         return false;
    4499             : 
    4500          51 :     return emitIndex32(JSOP_DOUBLE, constList.length() - 1);
    4501             : }
    4502             : 
    4503             : /*
    4504             :  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
    4505             :  * LLVM is deciding to inline this function which uses a lot of stack space
    4506             :  * into emitTree which is recursive and uses relatively little stack space.
    4507             :  */
    4508             : MOZ_NEVER_INLINE bool
    4509         210 : BytecodeEmitter::emitSwitch(ParseNode* pn)
    4510             : {
    4511         210 :     ParseNode* cases = pn->pn_right;
    4512         210 :     MOZ_ASSERT(cases->isKind(PNK_LEXICALSCOPE) || cases->isKind(PNK_STATEMENTLIST));
    4513             : 
    4514             :     // Emit code for the discriminant.
    4515         210 :     if (!emitTree(pn->pn_left))
    4516           0 :         return false;
    4517             : 
    4518             :     // Enter the scope before pushing the switch BreakableControl since all
    4519             :     // breaks are under this scope.
    4520         420 :     Maybe<TDZCheckCache> tdzCache;
    4521         420 :     Maybe<EmitterScope> emitterScope;
    4522         210 :     if (cases->isKind(PNK_LEXICALSCOPE)) {
    4523         210 :         if (!cases->isEmptyScope()) {
    4524          10 :             tdzCache.emplace(this);
    4525          10 :             emitterScope.emplace(this);
    4526          10 :             if (!emitterScope->enterLexical(this, ScopeKind::Lexical, cases->scopeBindings()))
    4527           0 :                 return false;
    4528             :         }
    4529             : 
    4530             :         // Advance |cases| to refer to the switch case list.
    4531         210 :         cases = cases->scopeBody();
    4532             : 
    4533             :         // A switch statement may contain hoisted functions inside its
    4534             :         // cases. The PNX_FUNCDEFS flag is propagated from the STATEMENTLIST
    4535             :         // bodies of the cases to the case list.
    4536         210 :         if (cases->pn_xflags & PNX_FUNCDEFS) {
    4537           0 :             MOZ_ASSERT(emitterScope);
    4538           0 :             for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
    4539           0 :                 if (caseNode->pn_right->pn_xflags & PNX_FUNCDEFS) {
    4540           0 :                     if (!emitHoistedFunctionsInList(caseNode->pn_right))
    4541           0 :                         return false;
    4542             :                 }
    4543             :             }
    4544             :         }
    4545             :     }
    4546             : 
    4547             :     // After entering the scope, push the switch control.
    4548         420 :     BreakableControl controlInfo(this, StatementKind::Switch);
    4549             : 
    4550         210 :     ptrdiff_t top = offset();
    4551             : 
    4552             :     // Switch bytecodes run from here till end of final case.
    4553         210 :     uint32_t caseCount = cases->pn_count;
    4554         210 :     if (caseCount > JS_BIT(16)) {
    4555           0 :         parser.reportError(JSMSG_TOO_MANY_CASES);
    4556           0 :         return false;
    4557             :     }
    4558             : 
    4559             :     // Try for most optimal, fall back if not dense ints.
    4560         210 :     JSOp switchOp = JSOP_TABLESWITCH;
    4561         210 :     uint32_t tableLength = 0;
    4562             :     int32_t low, high;
    4563         210 :     bool hasDefault = false;
    4564         210 :     CaseClause* firstCase = cases->pn_head ? &cases->pn_head->as<CaseClause>() : nullptr;
    4565         210 :     if (caseCount == 0 ||
    4566          11 :         (caseCount == 1 && (hasDefault = firstCase->isDefault())))
    4567             :     {
    4568           0 :         caseCount = 0;
    4569           0 :         low = 0;
    4570           0 :         high = -1;
    4571             :     } else {
    4572         420 :         Vector<jsbitmap, 128, SystemAllocPolicy> intmap;
    4573         210 :         int32_t intmapBitLength = 0;
    4574             : 
    4575         210 :         low  = JSVAL_INT_MAX;
    4576         210 :         high = JSVAL_INT_MIN;
    4577             : 
    4578        1324 :         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4579        1114 :             if (caseNode->isDefault()) {
    4580          55 :                 hasDefault = true;
    4581          55 :                 caseCount--;  // one of the "cases" was the default
    4582         615 :                 continue;
    4583             :             }
    4584             : 
    4585        1059 :             if (switchOp == JSOP_CONDSWITCH)
    4586         374 :                 continue;
    4587             : 
    4588         685 :             MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4589             : 
    4590         685 :             ParseNode* caseValue = caseNode->caseExpression();
    4591             : 
    4592         685 :             if (caseValue->getKind() != PNK_NUMBER) {
    4593         131 :                 switchOp = JSOP_CONDSWITCH;
    4594         131 :                 continue;
    4595             :             }
    4596             : 
    4597             :             int32_t i;
    4598         554 :             if (!NumberIsInt32(caseValue->pn_dval, &i)) {
    4599           0 :                 switchOp = JSOP_CONDSWITCH;
    4600           0 :                 continue;
    4601             :             }
    4602             : 
    4603         554 :             if (unsigned(i + int(JS_BIT(15))) >= unsigned(JS_BIT(16))) {
    4604           0 :                 switchOp = JSOP_CONDSWITCH;
    4605           0 :                 continue;
    4606             :             }
    4607         554 :             if (i < low)
    4608          89 :                 low = i;
    4609         554 :             if (i > high)
    4610         454 :                 high = i;
    4611             : 
    4612             :             // Check for duplicates, which require a JSOP_CONDSWITCH.
    4613             :             // We bias i by 65536 if it's negative, and hope that's a rare
    4614             :             // case (because it requires a malloc'd bitmap).
    4615         554 :             if (i < 0)
    4616           0 :                 i += JS_BIT(16);
    4617         554 :             if (i >= intmapBitLength) {
    4618          79 :                 size_t newLength = (i / JS_BITMAP_NBITS) + 1;
    4619          79 :                 if (!intmap.resize(newLength))
    4620           0 :                     return false;
    4621          79 :                 intmapBitLength = newLength * JS_BITMAP_NBITS;
    4622             :             }
    4623         554 :             if (JS_TEST_BIT(intmap, i)) {
    4624           0 :                 switchOp = JSOP_CONDSWITCH;
    4625           0 :                 continue;
    4626             :             }
    4627         554 :             JS_SET_BIT(intmap, i);
    4628             :         }
    4629             : 
    4630             :         // Compute table length and select condswitch instead if overlarge or
    4631             :         // more than half-sparse.
    4632         210 :         if (switchOp == JSOP_TABLESWITCH) {
    4633          79 :             tableLength = uint32_t(high - low + 1);
    4634          79 :             if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
    4635           1 :                 switchOp = JSOP_CONDSWITCH;
    4636             :         }
    4637             :     }
    4638             : 
    4639             :     // The note has one or two offsets: first tells total switch code length;
    4640             :     // second (if condswitch) tells offset to first JSOP_CASE.
    4641             :     unsigned noteIndex;
    4642             :     size_t switchSize;
    4643         210 :     if (switchOp == JSOP_CONDSWITCH) {
    4644             :         // 0 bytes of immediate for unoptimized switch.
    4645         132 :         switchSize = 0;
    4646         132 :         if (!newSrcNote3(SRC_CONDSWITCH, 0, 0, &noteIndex))
    4647           0 :             return false;
    4648             :     } else {
    4649          78 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4650             : 
    4651             :         // 3 offsets (len, low, high) before the table, 1 per entry.
    4652          78 :         switchSize = size_t(JUMP_OFFSET_LEN * (3 + tableLength));
    4653          78 :         if (!newSrcNote2(SRC_TABLESWITCH, 0, &noteIndex))
    4654           0 :             return false;
    4655             :     }
    4656             : 
    4657             :     // Emit switchOp followed by switchSize bytes of jump or lookup table.
    4658         210 :     MOZ_ASSERT(top == offset());
    4659         210 :     if (!emitN(switchOp, switchSize))
    4660           0 :         return false;
    4661             : 
    4662         420 :     Vector<CaseClause*, 32, SystemAllocPolicy> table;
    4663             : 
    4664         210 :     JumpList condSwitchDefaultOff;
    4665         210 :     if (switchOp == JSOP_CONDSWITCH) {
    4666             :         unsigned caseNoteIndex;
    4667         132 :         bool beforeCases = true;
    4668         132 :         ptrdiff_t lastCaseOffset = -1;
    4669             : 
    4670             :         // The case conditions need their own TDZ cache since they might not
    4671             :         // all execute.
    4672         264 :         TDZCheckCache tdzCache(this);
    4673             : 
    4674             :         // Emit code for evaluating cases and jumping to case statements.
    4675         663 :         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4676         531 :             ParseNode* caseValue = caseNode->caseExpression();
    4677             : 
    4678             :             // If the expression is a literal, suppress line number emission so
    4679             :             // that debugging works more naturally.
    4680         531 :             if (caseValue) {
    4681         508 :                 if (!emitTree(caseValue, ValueUsage::WantValue,
    4682         508 :                               caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE))
    4683             :                 {
    4684           0 :                     return false;
    4685             :                 }
    4686             :             }
    4687             : 
    4688         531 :             if (!beforeCases) {
    4689             :                 // prevCase is the previous JSOP_CASE's bytecode offset.
    4690         399 :                 if (!setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
    4691           0 :                     return false;
    4692             :             }
    4693         531 :             if (!caseValue) {
    4694             :                 // This is the default clause.
    4695          23 :                 continue;
    4696             :             }
    4697             : 
    4698         508 :             if (!newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex))
    4699           0 :                 return false;
    4700             : 
    4701             :             // The case clauses are produced before any of the case body. The
    4702             :             // JumpList is saved on the parsed tree, then later restored and
    4703             :             // patched when generating the cases body.
    4704         508 :             JumpList caseJump;
    4705         508 :             if (!emitJump(JSOP_CASE, &caseJump))
    4706           0 :                 return false;
    4707         508 :             caseNode->setOffset(caseJump.offset);
    4708         508 :             lastCaseOffset = caseJump.offset;
    4709             : 
    4710         508 :             if (beforeCases) {
    4711             :                 // Switch note's second offset is to first JSOP_CASE.
    4712         132 :                 unsigned noteCount = notes().length();
    4713         132 :                 if (!setSrcNoteOffset(noteIndex, 1, lastCaseOffset - top))
    4714           0 :                     return false;
    4715         132 :                 unsigned noteCountDelta = notes().length() - noteCount;
    4716         132 :                 if (noteCountDelta != 0)
    4717           0 :                     caseNoteIndex += noteCountDelta;
    4718         132 :                 beforeCases = false;
    4719             :             }
    4720             :         }
    4721             : 
    4722             :         // If we didn't have an explicit default (which could fall in between
    4723             :         // cases, preventing us from fusing this setSrcNoteOffset with the call
    4724             :         // in the loop above), link the last case to the implicit default for
    4725             :         // the benefit of IonBuilder.
    4726         373 :         if (!hasDefault &&
    4727         241 :             !beforeCases &&
    4728         109 :             !setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
    4729             :         {
    4730           0 :             return false;
    4731             :         }
    4732             : 
    4733             :         // Emit default even if no explicit default statement.
    4734         132 :         if (!emitJump(JSOP_DEFAULT, &condSwitchDefaultOff))
    4735           0 :             return false;
    4736             :     } else {
    4737          78 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4738             : 
    4739             :         // skip default offset.
    4740          78 :         jsbytecode* pc = code(top + JUMP_OFFSET_LEN);
    4741             : 
    4742             :         // Fill in switch bounds, which we know fit in 16-bit offsets.
    4743          78 :         SET_JUMP_OFFSET(pc, low);
    4744          78 :         pc += JUMP_OFFSET_LEN;
    4745          78 :         SET_JUMP_OFFSET(pc, high);
    4746          78 :         pc += JUMP_OFFSET_LEN;
    4747             : 
    4748          78 :         if (tableLength != 0) {
    4749          78 :             if (!table.growBy(tableLength))
    4750           0 :                 return false;
    4751             : 
    4752         661 :             for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4753         583 :                 if (ParseNode* caseValue = caseNode->caseExpression()) {
    4754         551 :                     MOZ_ASSERT(caseValue->isKind(PNK_NUMBER));
    4755             : 
    4756         551 :                     int32_t i = int32_t(caseValue->pn_dval);
    4757         551 :                     MOZ_ASSERT(double(i) == caseValue->pn_dval);
    4758             : 
    4759         551 :                     i -= low;
    4760         551 :                     MOZ_ASSERT(uint32_t(i) < tableLength);
    4761         551 :                     MOZ_ASSERT(!table[i]);
    4762         551 :                     table[i] = caseNode;
    4763             :                 }
    4764             :             }
    4765             :         }
    4766             :     }
    4767             : 
    4768         210 :     JumpTarget defaultOffset{ -1 };
    4769             : 
    4770             :     // Emit code for each case's statements.
    4771        1324 :     for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
    4772        1114 :         if (switchOp == JSOP_CONDSWITCH && !caseNode->isDefault()) {
    4773             :             // The case offset got saved in the caseNode structure after
    4774             :             // emitting the JSOP_CASE jump instruction above.
    4775         508 :             JumpList caseCond;
    4776         508 :             caseCond.offset = caseNode->offset();
    4777         508 :             if (!emitJumpTargetAndPatch(caseCond))
    4778           0 :                 return false;
    4779             :         }
    4780             : 
    4781             :         JumpTarget here;
    4782        1114 :         if (!emitJumpTarget(&here))
    4783           0 :             return false;
    4784        1114 :         if (caseNode->isDefault())
    4785          55 :             defaultOffset = here;
    4786             : 
    4787             :         // If this is emitted as a TABLESWITCH, we'll need to know this case's
    4788             :         // offset later when emitting the table. Store it in the node's
    4789             :         // pn_offset (giving the field a different meaning vs. how we used it
    4790             :         // on the immediately preceding line of code).
    4791        1114 :         caseNode->setOffset(here.offset);
    4792             : 
    4793        2228 :         TDZCheckCache tdzCache(this);
    4794             : 
    4795        1114 :         if (!emitTree(caseNode->statementList()))
    4796           0 :             return false;
    4797             :     }
    4798             : 
    4799         210 :     if (!hasDefault) {
    4800             :         // If no default case, offset for default is to end of switch.
    4801         155 :         if (!emitJumpTarget(&defaultOffset))
    4802           0 :             return false;
    4803             :     }
    4804         210 :     MOZ_ASSERT(defaultOffset.offset != -1);
    4805             : 
    4806             :     // Set the default offset (to end of switch if no default).
    4807             :     jsbytecode* pc;
    4808         210 :     if (switchOp == JSOP_CONDSWITCH) {
    4809         132 :         pc = nullptr;
    4810         132 :         patchJumpsToTarget(condSwitchDefaultOff, defaultOffset);
    4811             :     } else {
    4812          78 :         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
    4813          78 :         pc = code(top);
    4814          78 :         SET_JUMP_OFFSET(pc, defaultOffset.offset - top);
    4815          78 :         pc += JUMP_OFFSET_LEN;
    4816             :     }
    4817             : 
    4818             :     // Set the SRC_SWITCH note's offset operand to tell end of switch.
    4819         210 :     if (!setSrcNoteOffset(noteIndex, 0, lastNonJumpTargetOffset() - top))
    4820           0 :         return false;
    4821             : 
    4822         210 :     if (switchOp == JSOP_TABLESWITCH) {
    4823             :         // Skip over the already-initialized switch bounds.
    4824          78 :         pc += 2 * JUMP_OFFSET_LEN;
    4825             : 
    4826             :         // Fill in the jump table, if there is one.
    4827         654 :         for (uint32_t i = 0; i < tableLength; i++) {
    4828         576 :             CaseClause* caseNode = table[i];
    4829         576 :             ptrdiff_t off = caseNode ? caseNode->offset() - top : 0;
    4830         576 :             SET_JUMP_OFFSET(pc, off);
    4831         576 :             pc += JUMP_OFFSET_LEN;
    4832             :         }
    4833             :     }
    4834             : 
    4835             :     // Patch breaks before leaving the scope, as all breaks are under the
    4836             :     // lexical scope if it exists.
    4837         210 :     if (!controlInfo.patchBreaks(this))
    4838           0 :         return false;
    4839             : 
    4840         210 :     if (emitterScope && !emitterScope->leave(this))
    4841           0 :         return false;
    4842             : 
    4843         210 :     return true;
    4844             : }
    4845             : 
    4846             : bool
    4847        9824 : BytecodeEmitter::isRunOnceLambda()
    4848             : {
    4849             :     // The run once lambda flags set by the parser are approximate, and we look
    4850             :     // at properties of the function itself before deciding to emit a function
    4851             :     // as a run once lambda.
    4852             : 
    4853       29296 :     if (!(parent && parent->emittingRunOnceLambda) &&
    4854       11401 :         (emitterMode != LazyFunction || !lazyScript->treatAsRunOnce()))
    4855             :     {
    4856        9736 :         return false;
    4857             :     }
    4858             : 
    4859          88 :     FunctionBox* funbox = sc->asFunctionBox();
    4860         176 :     return !funbox->argumentsHasLocalBinding() &&
    4861         176 :            !funbox->isStarGenerator() &&
    4862         176 :            !funbox->isLegacyGenerator() &&
    4863         264 :            !funbox->isAsync() &&
    4864         176 :            !funbox->function()->explicitName();
    4865             : }
    4866             : 
    4867             : bool
    4868         591 : BytecodeEmitter::emitYieldOp(JSOp op)
    4869             : {
    4870         591 :     if (op == JSOP_FINALYIELDRVAL)
    4871         211 :         return emit1(JSOP_FINALYIELDRVAL);
    4872             : 
    4873         380 :     MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD || op == JSOP_AWAIT);
    4874             : 
    4875             :     ptrdiff_t off;
    4876         380 :     if (!emitN(op, 3, &off))
    4877           0 :         return false;
    4878             : 
    4879         380 :     uint32_t yieldAndAwaitIndex = yieldAndAwaitOffsetList.length();
    4880         380 :     if (yieldAndAwaitIndex >= JS_BIT(24)) {
    4881           0 :         reportError(nullptr, JSMSG_TOO_MANY_YIELDS);
    4882           0 :         return false;
    4883             :     }
    4884             : 
    4885         380 :     if (op == JSOP_AWAIT)
    4886         235 :         yieldAndAwaitOffsetList.numAwaits++;
    4887             :     else
    4888         145 :         yieldAndAwaitOffsetList.numYields++;
    4889             : 
    4890         380 :     SET_UINT24(code(off), yieldAndAwaitIndex);
    4891             : 
    4892         380 :     if (!yieldAndAwaitOffsetList.append(offset()))
    4893           0 :         return false;
    4894             : 
    4895         380 :     return emit1(JSOP_DEBUGAFTERYIELD);
    4896             : }
    4897             : 
    4898             : bool
    4899          13 : BytecodeEmitter::emitSetThis(ParseNode* pn)
    4900             : {
    4901             :     // PNK_SETTHIS is used to update |this| after a super() call in a derived
    4902             :     // class constructor.
    4903             : 
    4904          13 :     MOZ_ASSERT(pn->isKind(PNK_SETTHIS));
    4905          13 :     MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME));
    4906             : 
    4907          26 :     RootedAtom name(cx, pn->pn_left->name());
    4908          26 :     auto emitRhs = [&name, pn](BytecodeEmitter* bce, const NameLocation&, bool) {
    4909             :         // Emit the new |this| value.
    4910          13 :         if (!bce->emitTree(pn->pn_right))
    4911           0 :             return false;
    4912             :         // Get the original |this| and throw if we already initialized
    4913             :         // it. Do *not* use the NameLocation argument, as that's the special
    4914             :         // lexical location below to deal with super() semantics.
    4915          13 :         if (!bce->emitGetName(name))
    4916           0 :             return false;
    4917          13 :         if (!bce->emit1(JSOP_CHECKTHISREINIT))
    4918           0 :             return false;
    4919          13 :         if (!bce->emit1(JSOP_POP))
    4920           0 :             return false;
    4921          13 :         return true;
    4922          13 :     };
    4923             : 
    4924             :     // The 'this' binding is not lexical, but due to super() semantics this
    4925             :     // initialization needs to be treated as a lexical one.
    4926          13 :     NameLocation loc = lookupName(name);
    4927          13 :     NameLocation lexicalLoc;
    4928          13 :     if (loc.kind() == NameLocation::Kind::FrameSlot) {
    4929          13 :         lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
    4930           0 :     } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
    4931           0 :         EnvironmentCoordinate coord = loc.environmentCoordinate();
    4932           0 :         uint8_t hops = AssertedCast<uint8_t>(coord.hops());
    4933           0 :         lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, coord.slot());
    4934             :     } else {
    4935           0 :         MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic);
    4936           0 :         lexicalLoc = loc;
    4937             :     }
    4938             : 
    4939          26 :     return emitSetOrInitializeNameAtLocation(name, lexicalLoc, emitRhs, true);
    4940             : }
    4941             : 
    4942             : bool
    4943         268 : BytecodeEmitter::emitScript(ParseNode* body)
    4944             : {
    4945         537 :     AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, tokenStream(), body);
    4946             : 
    4947         537 :     TDZCheckCache tdzCache(this);
    4948         537 :     EmitterScope emitterScope(this);
    4949         268 :     if (sc->isGlobalContext()) {
    4950         266 :         switchToPrologue();
    4951         266 :         if (!emitterScope.enterGlobal(this, sc->asGlobalContext()))
    4952           0 :             return false;
    4953         266 :         switchToMain();
    4954           2 :     } else if (sc->isEvalContext()) {
    4955           2 :         switchToPrologue();
    4956           2 :         if (!emitterScope.enterEval(this, sc->asEvalContext()))
    4957           0 :             return false;
    4958           2 :         switchToMain();
    4959             :     } else {
    4960           0 :         MOZ_ASSERT(sc->isModuleContext());
    4961           0 :         if (!emitterScope.enterModule(this, sc->asModuleContext()))
    4962           0 :             return false;
    4963             :     }
    4964             : 
    4965         268 :     setFunctionBodyEndPos(body->pn_pos);
    4966             : 
    4967         538 :     if (sc->isEvalContext() && !sc->strict() &&
    4968         268 :         body->isKind(PNK_LEXICALSCOPE) && !body->isEmptyScope())
    4969             :     {
    4970             :         // Sloppy eval scripts may need to emit DEFFUNs in the prologue. If there is
    4971             :         // an immediately enclosed lexical scope, we need to enter the lexical
    4972             :         // scope in the prologue for the DEFFUNs to pick up the right
    4973             :         // environment chain.
    4974           0 :         EmitterScope lexicalEmitterScope(this);
    4975             : 
    4976           0 :         switchToPrologue();
    4977           0 :         if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, body->scopeBindings()))
    4978           0 :             return false;
    4979           0 :         switchToMain();
    4980             : 
    4981           0 :         if (!emitLexicalScopeBody(body->scopeBody()))
    4982           0 :             return false;
    4983             : 
    4984           0 :         if (!lexicalEmitterScope.leave(this))
    4985           0 :             return false;
    4986             :     } else {
    4987         268 :         if (!emitTree(body))
    4988           0 :             return false;
    4989             :     }
    4990             : 
    4991         269 :     if (!emit1(JSOP_RETRVAL))
    4992           0 :         return false;
    4993             : 
    4994         269 :     if (!emitterScope.leave(this))
    4995           0 :         return false;
    4996             : 
    4997         269 :     if (!JSScript::fullyInitFromEmitter(cx, script, this))
    4998           0 :         return false;
    4999             : 
    5000             :     // URL and source map information must be set before firing
    5001             :     // Debugger::onNewScript.
    5002         269 :     if (!maybeSetDisplayURL() || !maybeSetSourceMap())
    5003           0 :         return false;
    5004             : 
    5005         269 :     tellDebuggerAboutCompiledScript(cx);
    5006             : 
    5007         269 :     return true;
    5008             : }
    5009             : 
    5010             : bool
    5011        5404 : BytecodeEmitter::emitFunctionScript(ParseNode* body)
    5012             : {
    5013        5404 :     FunctionBox* funbox = sc->asFunctionBox();
    5014       10809 :     AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, tokenStream(), funbox);
    5015             : 
    5016             :     // The ordering of these EmitterScopes is important. The named lambda
    5017             :     // scope needs to enclose the function scope needs to enclose the extra
    5018             :     // var scope.
    5019             : 
    5020       10809 :     Maybe<EmitterScope> namedLambdaEmitterScope;
    5021        5404 :     if (funbox->namedLambdaBindings()) {
    5022         391 :         namedLambdaEmitterScope.emplace(this);
    5023         391 :         if (!namedLambdaEmitterScope->enterNamedLambda(this, funbox))
    5024           0 :             return false;
    5025             :     }
    5026             : 
    5027             :     /*
    5028             :      * Emit a prologue for run-once scripts which will deoptimize JIT code
    5029             :      * if the script ends up running multiple times via foo.caller related
    5030             :      * shenanigans.
    5031             :      *
    5032             :      * Also mark the script so that initializers created within it may be
    5033             :      * given more precise types.
    5034             :      */
    5035        5404 :     if (isRunOnceLambda()) {
    5036          10 :         script->setTreatAsRunOnce();
    5037          10 :         MOZ_ASSERT(!script->hasRunOnce());
    5038             : 
    5039          10 :         switchToPrologue();
    5040          10 :         if (!emit1(JSOP_RUNONCE))
    5041           0 :             return false;
    5042          10 :         switchToMain();
    5043             :     }
    5044             : 
    5045        5404 :     setFunctionBodyEndPos(body->pn_pos);
    5046        5404 :     if (!emitTree(body))
    5047           0 :         return false;
    5048             : 
    5049        5405 :     if (!updateSourceCoordNotes(body->pn_pos.end))
    5050           0 :         return false;
    5051             : 
    5052             :     // Always end the script with a JSOP_RETRVAL. Some other parts of the
    5053             :     // codebase depend on this opcode,
    5054             :     // e.g. InterpreterRegs::setToEndOfScript.
    5055        5405 :     if (!emit1(JSOP_RETRVAL))
    5056           0 :         return false;
    5057             : 
    5058        5405 :     if (namedLambdaEmitterScope) {
    5059         391 :         if (!namedLambdaEmitterScope->leave(this))
    5060           0 :             return false;
    5061         391 :         namedLambdaEmitterScope.reset();
    5062             :     }
    5063             : 
    5064        5405 :     if (!JSScript::fullyInitFromEmitter(cx, script, this))
    5065           0 :         return false;
    5066             : 
    5067             :     // URL and source map information must be set before firing
    5068             :     // Debugger::onNewScript. Only top-level functions need this, as compiling
    5069             :     // the outer scripts of nested functions already processed the source.
    5070        5405 :     if (emitterMode != LazyFunction && !parent) {
    5071          15 :         if (!maybeSetDisplayURL() || !maybeSetSourceMap())
    5072           0 :             return false;
    5073             : 
    5074          15 :         tellDebuggerAboutCompiledScript(cx);
    5075             :     }
    5076             : 
    5077        5405 :     return true;
    5078             : }
    5079             : 
    5080             : template <typename NameEmitter>
    5081             : bool
    5082             : BytecodeEmitter::emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName)
    5083             : {
    5084             :     if (pattern->isKind(PNK_ARRAY)) {
    5085             :         for (ParseNode* element = pattern->pn_head; element; element = element->pn_next) {
    5086             :             if (element->isKind(PNK_ELISION))
    5087             :                 continue;
    5088             :             ParseNode* target = element;
    5089             :             if (element->isKind(PNK_SPREAD)) {
    5090             :                 target = element->pn_kid;
    5091             :             }
    5092             :             if (target->isKind(PNK_ASSIGN))
    5093             :                 target = target->pn_left;
    5094             :             if (target->isKind(PNK_NAME)) {
    5095             :                 if (!emitName(this, target))
    5096             :                     return false;
    5097             :             } else {
    5098             :                 if (!emitDestructuringDeclsWithEmitter(target, emitName))
    5099             :                     return false;
    5100             :             }
    5101             :         }
    5102             :         return true;
    5103             :     }
    5104             : 
    5105             :     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
    5106             :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    5107             :         MOZ_ASSERT(member->isKind(PNK_MUTATEPROTO) ||
    5108             :                    member->isKind(PNK_COLON) ||
    5109             :                    member->isKind(PNK_SHORTHAND));
    5110             : 
    5111             :         ParseNode* target = member->isKind(PNK_MUTATEPROTO) ? member->pn_kid : member->pn_right;
    5112             : 
    5113             :         if (target->isKind(PNK_ASSIGN))
    5114             :             target = target->pn_left;
    5115             :         if (target->isKind(PNK_NAME)) {
    5116             :             if (!emitName(this, target))
    5117             :                 return false;
    5118             :         } else {
    5119             :             if (!emitDestructuringDeclsWithEmitter(target, emitName))
    5120             :                 return false;
    5121             :         }
    5122             :     }
    5123             :     return true;
    5124             : }
    5125             : 
    5126             : bool
    5127         542 : BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted)
    5128             : {
    5129         542 :     *emitted = 0;
    5130             : 
    5131         542 :     if (target->isKind(PNK_SPREAD))
    5132           0 :         target = target->pn_kid;
    5133         542 :     else if (target->isKind(PNK_ASSIGN))
    5134           0 :         target = target->pn_left;
    5135             : 
    5136             :     // No need to recur into PNK_ARRAY and PNK_OBJECT subpatterns here, since
    5137             :     // emitSetOrInitializeDestructuring does the recursion when setting or
    5138             :     // initializing value.  Getting reference doesn't recur.
    5139         542 :     if (target->isKind(PNK_NAME) || target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT))
    5140         538 :         return true;
    5141             : 
    5142             : #ifdef DEBUG
    5143           4 :     int depth = stackDepth;
    5144             : #endif
    5145             : 
    5146           4 :     switch (target->getKind()) {
    5147             :       case PNK_DOT: {
    5148           4 :         if (target->as<PropertyAccess>().isSuper()) {
    5149           0 :             if (!emitSuperPropLHS(&target->as<PropertyAccess>().expression()))
    5150           0 :                 return false;
    5151           0 :             *emitted = 2;
    5152             :         } else {
    5153           4 :             if (!emitTree(target->pn_expr))
    5154           0 :                 return false;
    5155           4 :             *emitted = 1;
    5156             :         }
    5157           4 :         break;
    5158             :       }
    5159             : 
    5160             :       case PNK_ELEM: {
    5161           0 :         if (target->as<PropertyByValue>().isSuper()) {
    5162           0 :             if (!emitSuperElemOperands(target, EmitElemOption::Ref))
    5163           0 :                 return false;
    5164           0 :             *emitted = 3;
    5165             :         } else {
    5166           0 :             if (!emitElemOperands(target, EmitElemOption::Ref))
    5167           0 :                 return false;
    5168           0 :             *emitted = 2;
    5169             :         }
    5170           0 :         break;
    5171             :       }
    5172             : 
    5173             :       case PNK_CALL:
    5174           0 :         MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
    5175             :                                "rejects function calls as assignment "
    5176             :                                "targets in destructuring assignments");
    5177             :         break;
    5178             : 
    5179             :       default:
    5180           0 :         MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
    5181             :     }
    5182             : 
    5183           4 :     MOZ_ASSERT(stackDepth == depth + int(*emitted));
    5184             : 
    5185           4 :     return true;
    5186             : }
    5187             : 
    5188             : bool
    5189         542 : BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav)
    5190             : {
    5191             :     // Now emit the lvalue opcode sequence. If the lvalue is a nested
    5192             :     // destructuring initialiser-form, call ourselves to handle it, then pop
    5193             :     // the matched value. Otherwise emit an lvalue bytecode sequence followed
    5194             :     // by an assignment op.
    5195         542 :     if (target->isKind(PNK_SPREAD))
    5196           0 :         target = target->pn_kid;
    5197         542 :     else if (target->isKind(PNK_ASSIGN))
    5198           4 :         target = target->pn_left;
    5199         542 :     if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) {
    5200          13 :         if (!emitDestructuringOps(target, flav))
    5201           0 :             return false;
    5202             :         // Per its post-condition, emitDestructuringOps has left the
    5203             :         // to-be-destructured value on top of the stack.
    5204          13 :         if (!emit1(JSOP_POP))
    5205           0 :             return false;
    5206             :     } else {
    5207         529 :         switch (target->getKind()) {
    5208             :           case PNK_NAME: {
    5209             :             auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
    5210         525 :                                           bool emittedBindOp)
    5211             :             {
    5212         525 :                 if (emittedBindOp) {
    5213             :                     // This is like ordinary assignment, but with one
    5214             :                     // difference.
    5215             :                     //
    5216             :                     // In `a = b`, we first determine a binding for `a` (using
    5217             :                     // JSOP_BINDNAME or JSOP_BINDGNAME), then we evaluate `b`,
    5218             :                     // then a JSOP_SETNAME instruction.
    5219             :                     //
    5220             :                     // In `[a] = [b]`, per spec, `b` is evaluated first, then
    5221             :                     // we determine a binding for `a`. Then we need to do
    5222             :                     // assignment-- but the operands are on the stack in the
    5223             :                     // wrong order for JSOP_SETPROP, so we have to add a
    5224             :                     // JSOP_SWAP.
    5225             :                     //
    5226             :                     // In the cases where we are emitting a name op, emit a
    5227             :                     // swap because of this.
    5228          26 :                     return bce->emit1(JSOP_SWAP);
    5229             :                 }
    5230             : 
    5231             :                 // In cases of emitting a frame slot or environment slot,
    5232             :                 // nothing needs be done.
    5233         499 :                 return true;
    5234             :             };
    5235             : 
    5236         525 :             RootedAtom name(cx, target->name());
    5237         525 :             switch (flav) {
    5238             :               case DestructuringDeclaration:
    5239         516 :                 if (!emitInitializeName(name, emitSwapScopeAndRhs))
    5240           0 :                     return false;
    5241         516 :                 break;
    5242             : 
    5243             :               case DestructuringFormalParameterInVarScope: {
    5244             :                 // If there's an parameter expression var scope, the
    5245             :                 // destructuring declaration needs to initialize the name in
    5246             :                 // the function scope. The innermost scope is the var scope,
    5247             :                 // and its enclosing scope is the function scope.
    5248           0 :                 EmitterScope* funScope = innermostEmitterScope->enclosingInFrame();
    5249           0 :                 NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope);
    5250           0 :                 if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true))
    5251           0 :                     return false;
    5252           0 :                 break;
    5253             :               }
    5254             : 
    5255             :               case DestructuringAssignment:
    5256           9 :                 if (!emitSetName(name, emitSwapScopeAndRhs))
    5257           0 :                     return false;
    5258           9 :                 break;
    5259             :             }
    5260             : 
    5261         525 :             break;
    5262             :           }
    5263             : 
    5264             :           case PNK_DOT: {
    5265             :             // The reference is already pushed by emitDestructuringLHSRef.
    5266             :             JSOp setOp;
    5267           4 :             if (target->as<PropertyAccess>().isSuper())
    5268           0 :                 setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
    5269             :             else
    5270           4 :                 setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
    5271           4 :             if (!emitAtomOp(target, setOp))
    5272           0 :                 return false;
    5273           4 :             break;
    5274             :           }
    5275             : 
    5276             :           case PNK_ELEM: {
    5277             :             // The reference is already pushed by emitDestructuringLHSRef.
    5278           0 :             if (target->as<PropertyByValue>().isSuper()) {
    5279           0 :                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER;
    5280             :                 // emitDestructuringLHSRef already did emitSuperElemOperands
    5281             :                 // part of emitSuperElemOp.  Perform remaining part here.
    5282           0 :                 if (!emitElemOpBase(setOp))
    5283           0 :                     return false;
    5284             :             } else {
    5285           0 :                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
    5286           0 :                 if (!emitElemOpBase(setOp))
    5287           0 :                     return false;
    5288             :             }
    5289           0 :             break;
    5290             :           }
    5291             : 
    5292             :           case PNK_CALL:
    5293           0 :             MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
    5294             :                                    "rejects function calls as assignment "
    5295             :                                    "targets in destructuring assignments");
    5296             :             break;
    5297             : 
    5298             :           default:
    5299           0 :             MOZ_CRASH("emitSetOrInitializeDestructuring: bad lhs kind");
    5300             :         }
    5301             : 
    5302             :         // Pop the assigned value.
    5303         529 :         if (!emit1(JSOP_POP))
    5304           0 :             return false;
    5305             :     }
    5306             : 
    5307         542 :     return true;
    5308             : }
    5309             : 
    5310             : bool
    5311         541 : BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = IteratorKind::Sync */,
    5312             :                                   bool allowSelfHosted /* = false */)
    5313             : {
    5314         541 :     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
    5315             :                ".next() iteration is prohibited in self-hosted code because it "
    5316             :                "can run user-modifiable iteration code");
    5317             : 
    5318         541 :     if (!emit1(JSOP_DUP))                                 // ... ITER ITER
    5319           0 :         return false;
    5320         541 :     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))     // ... ITER NEXT
    5321           0 :         return false;
    5322         541 :     if (!emit1(JSOP_SWAP))                                // ... NEXT ITER
    5323           0 :         return false;
    5324         541 :     if (!emitCall(JSOP_CALL, 0, pn))                      // ... RESULT
    5325           0 :         return false;
    5326             : 
    5327         541 :     if (iterKind == IteratorKind::Async) {
    5328           0 :         if (!emitAwait())                                 // ... RESULT
    5329           0 :             return false;
    5330             :     }
    5331             : 
    5332         541 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
    5333           0 :         return false;
    5334         541 :     checkTypeSet(JSOP_CALL);
    5335         541 :     return true;
    5336             : }
    5337             : 
    5338             : bool
    5339         491 : BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */,
    5340             :                                    CompletionKind completionKind /* = CompletionKind::Normal */,
    5341             :                                    bool allowSelfHosted /* = false */)
    5342             : {
    5343         491 :     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
    5344             :                ".close() on iterators is prohibited in self-hosted code because it "
    5345             :                "can run user-modifiable iteration code");
    5346             : 
    5347             :     // Generate inline logic corresponding to IteratorClose (ES 7.4.6).
    5348             :     //
    5349             :     // Callers need to ensure that the iterator object is at the top of the
    5350             :     // stack.
    5351             : 
    5352         491 :     if (!emit1(JSOP_DUP))                                 // ... ITER ITER
    5353           0 :         return false;
    5354             : 
    5355             :     // Step 3.
    5356             :     //
    5357             :     // Get the "return" method.
    5358         491 :     if (!emitAtomOp(cx->names().return_, JSOP_CALLPROP))  // ... ITER RET
    5359           0 :         return false;
    5360             : 
    5361             :     // Step 4.
    5362             :     //
    5363             :     // Do nothing if "return" is null or undefined.
    5364         982 :     IfThenElseEmitter ifReturnMethodIsDefined(this);
    5365         491 :     if (!emit1(JSOP_DUP))                                 // ... ITER RET RET
    5366           0 :         return false;
    5367         491 :     if (!emit1(JSOP_UNDEFINED))                           // ... ITER RET RET UNDEFINED
    5368           0 :         return false;
    5369         491 :     if (!emit1(JSOP_NE))                                  // ... ITER RET ?NEQL
    5370           0 :         return false;
    5371         491 :     if (!ifReturnMethodIsDefined.emitIfElse())
    5372           0 :         return false;
    5373             : 
    5374         491 :     if (completionKind == CompletionKind::Throw) {
    5375             :         // 7.4.6 IteratorClose ( iterator, completion )
    5376             :         //   ...
    5377             :         //   3. Let return be ? GetMethod(iterator, "return").
    5378             :         //   4. If return is undefined, return Completion(completion).
    5379             :         //   5. Let innerResult be Call(return, iterator, « »).
    5380             :         //   6. If completion.[[Type]] is throw, return Completion(completion).
    5381             :         //   7. If innerResult.[[Type]] is throw, return
    5382             :         //      Completion(innerResult).
    5383             :         //
    5384             :         // For CompletionKind::Normal case, JSOP_CALL for step 5 checks if RET
    5385             :         // is callable, and throws if not.  Since step 6 doesn't match and
    5386             :         // error handling in step 3 and step 7 can be merged.
    5387             :         //
    5388             :         // For CompletionKind::Throw case, an error thrown by JSOP_CALL for
    5389             :         // step 5 is ignored by try-catch.  So we should check if RET is
    5390             :         // callable here, outside of try-catch, and the throw immediately if
    5391             :         // not.
    5392         336 :         CheckIsCallableKind kind = CheckIsCallableKind::IteratorReturn;
    5393         336 :         if (!emitCheckIsCallable(kind))                   // ... ITER RET
    5394           0 :             return false;
    5395             :     }
    5396             : 
    5397             :     // Steps 5, 8.
    5398             :     //
    5399             :     // Call "return" if it is not undefined or null, and check that it returns
    5400             :     // an Object.
    5401         491 :     if (!emit1(JSOP_SWAP))                                // ... RET ITER
    5402           0 :         return false;
    5403             : 
    5404         982 :     Maybe<TryEmitter> tryCatch;
    5405             : 
    5406         491 :     if (completionKind == CompletionKind::Throw) {
    5407         672 :         tryCatch.emplace(this, TryEmitter::TryCatch, TryEmitter::DontUseRetVal,
    5408         336 :                          TryEmitter::DontUseControl);
    5409             : 
    5410             :         // Mutate stack to balance stack for try-catch.
    5411         336 :         if (!emit1(JSOP_UNDEFINED))                       // ... RET ITER UNDEF
    5412           0 :             return false;
    5413         336 :         if (!tryCatch->emitTry())                         // ... RET ITER UNDEF
    5414           0 :             return false;
    5415         336 :         if (!emitDupAt(2))                                // ... RET ITER UNDEF RET
    5416           0 :             return false;
    5417         336 :         if (!emitDupAt(2))                                // ... RET ITER UNDEF RET ITER
    5418           0 :             return false;
    5419             :     }
    5420             : 
    5421         491 :     if (!emitCall(JSOP_CALL, 0))                          // ... ... RESULT
    5422           0 :         return false;
    5423         491 :     checkTypeSet(JSOP_CALL);
    5424             : 
    5425         491 :     if (iterKind == IteratorKind::Async) {
    5426           0 :         if (completionKind != CompletionKind::Throw) {
    5427             :             // Await clobbers rval, so save the current rval.
    5428           0 :             if (!emit1(JSOP_GETRVAL))                     // ... ... RESULT RVAL
    5429           0 :                 return false;
    5430           0 :             if (!emit1(JSOP_SWAP))                        // ... ... RVAL RESULT
    5431           0 :                 return false;
    5432             :         }
    5433           0 :         if (!emitAwait())                                 // ... ... RVAL? RESULT
    5434           0 :             return false;
    5435             :     }
    5436             : 
    5437         491 :     if (completionKind == CompletionKind::Throw) {
    5438         336 :         if (!emit1(JSOP_SWAP))                            // ... RET ITER RESULT UNDEF
    5439           0 :             return false;
    5440         336 :         if (!emit1(JSOP_POP))                             // ... RET ITER RESULT
    5441           0 :             return false;
    5442             : 
    5443         336 :         if (!tryCatch->emitCatch())                       // ... RET ITER RESULT
    5444           0 :             return false;
    5445             : 
    5446             :         // Just ignore the exception thrown by call and await.
    5447         336 :         if (!emit1(JSOP_EXCEPTION))                       // ... RET ITER RESULT EXC
    5448           0 :             return false;
    5449         336 :         if (!emit1(JSOP_POP))                             // ... RET ITER RESULT
    5450           0 :             return false;
    5451             : 
    5452         336 :         if (!tryCatch->emitEnd())                         // ... RET ITER RESULT
    5453           0 :             return false;
    5454             : 
    5455             :         // Restore stack.
    5456         336 :         if (!emit2(JSOP_UNPICK, 2))                       // ... RESULT RET ITER
    5457           0 :             return false;
    5458         336 :         if (!emitPopN(2))                                 // ... RESULT
    5459           0 :             return false;
    5460             :     } else {
    5461         155 :         if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) // ... RVAL? RESULT
    5462           0 :             return false;
    5463             : 
    5464         155 :         if (iterKind == IteratorKind::Async) {
    5465           0 :             if (!emit1(JSOP_SWAP))                        // ... RESULT RVAL
    5466           0 :                 return false;
    5467           0 :             if (!emit1(JSOP_SETRVAL))                     // ... RESULT
    5468           0 :                 return false;
    5469             :         }
    5470             :     }
    5471             : 
    5472         491 :     if (!ifReturnMethodIsDefined.emitElse())
    5473           0 :         return false;
    5474         491 :     if (!emit1(JSOP_POP))                                 // ... ITER
    5475           0 :         return false;
    5476         491 :     if (!ifReturnMethodIsDefined.emitEnd())
    5477           0 :         return false;
    5478             : 
    5479         491 :     return emit1(JSOP_POP);                               // ...
    5480             : }
    5481             : 
    5482             : template <typename InnerEmitter>
    5483             : bool
    5484         291 : BytecodeEmitter::wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, InnerEmitter emitter)
    5485             : {
    5486         291 :     MOZ_ASSERT(this->stackDepth >= iterDepth);
    5487             : 
    5488             :     // Pad a nop at the beginning of the bytecode covered by the trynote so
    5489             :     // that when unwinding environments, we may unwind to the scope
    5490             :     // corresponding to the pc *before* the start, in case the first bytecode
    5491             :     // emitted by |emitter| is the start of an inner scope. See comment above
    5492             :     // UnwindEnvironmentToTryPc.
    5493         291 :     if (!emit1(JSOP_TRY_DESTRUCTURING_ITERCLOSE))
    5494           0 :         return false;
    5495             : 
    5496         291 :     ptrdiff_t start = offset();
    5497         291 :     if (!emitter(this))
    5498           0 :         return false;
    5499         291 :     ptrdiff_t end = offset();
    5500         291 :     if (start != end)
    5501         151 :         return tryNoteList.append(JSTRY_DESTRUCTURING_ITERCLOSE, iterDepth, start, end);
    5502         140 :     return true;
    5503             : }
    5504             : 
    5505             : bool
    5506           7 : BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern)
    5507             : {
    5508           7 :     if (!emit1(JSOP_DUP))                                 // VALUE VALUE
    5509           0 :         return false;
    5510           7 :     if (!emit1(JSOP_UNDEFINED))                           // VALUE VALUE UNDEFINED
    5511           0 :         return false;
    5512           7 :     if (!emit1(JSOP_STRICTEQ))                            // VALUE EQL?
    5513           0 :         return false;
    5514             :     // Emit source note to enable ion compilation.
    5515           7 :     if (!newSrcNote(SRC_IF))
    5516           0 :         return false;
    5517           7 :     JumpList jump;
    5518           7 :     if (!emitJump(JSOP_IFEQ, &jump))                      // VALUE
    5519           0 :         return false;
    5520           7 :     if (!emit1(JSOP_POP))                                 // .
    5521           0 :         return false;
    5522           7 :     if (!emitInitializerInBranch(defaultExpr, pattern))   // DEFAULTVALUE
    5523           0 :         return false;
    5524           7 :     if (!emitJumpTargetAndPatch(jump))
    5525           0 :         return false;
    5526           7 :     return true;
    5527             : }
    5528             : 
    5529             : bool
    5530         385 : BytecodeEmitter::setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name,
    5531             :                                      FunctionPrefixKind prefixKind)
    5532             : {
    5533         385 :     if (maybeFun->isKind(PNK_FUNCTION)) {
    5534             :         // Function doesn't have 'name' property at this point.
    5535             :         // Set function's name at compile time.
    5536         379 :         JSFunction* fun = maybeFun->pn_funbox->function();
    5537             : 
    5538             :         // Single node can be emitted multiple times if it appears in
    5539             :         // array destructuring default.  If function already has a name,
    5540             :         // just return.
    5541         379 :         if (fun->hasCompileTimeName()) {
    5542             : #ifdef DEBUG
    5543           0 :             RootedFunction rootedFun(cx, fun);
    5544           0 :             JSAtom* funName = NameToFunctionName(cx, name, prefixKind);
    5545           0 :             if (!funName)
    5546           0 :                 return false;
    5547           0 :             MOZ_ASSERT(funName == rootedFun->compileTimeName());
    5548             : #endif
    5549           0 :             return true;
    5550             :         }
    5551             : 
    5552         379 :         fun->setCompileTimeName(name);
    5553         379 :         return true;
    5554             :     }
    5555             : 
    5556             :     uint32_t nameIndex;
    5557           6 :     if (!makeAtomIndex(name, &nameIndex))
    5558           0 :         return false;
    5559           6 :     if (!emitIndexOp(JSOP_STRING, nameIndex))   // FUN NAME
    5560           0 :         return false;
    5561           6 :     uint8_t kind = uint8_t(prefixKind);
    5562           6 :     if (!emit2(JSOP_SETFUNNAME, kind))          // FUN
    5563           0 :         return false;
    5564           6 :     return true;
    5565             : }
    5566             : 
    5567             : bool
    5568        9300 : BytecodeEmitter::emitInitializer(ParseNode* initializer, ParseNode* pattern)
    5569             : {
    5570        9300 :     if (!emitTree(initializer))
    5571           0 :         return false;
    5572             : 
    5573       18602 :     if (!pattern->isInParens() && pattern->isKind(PNK_NAME) &&
    5574        9301 :         initializer->isDirectRHSAnonFunction())
    5575             :     {
    5576         216 :         RootedAtom name(cx, pattern->name());
    5577         108 :         if (!setOrEmitSetFunName(initializer, name, FunctionPrefixKind::None))
    5578           0 :             return false;
    5579             :     }
    5580             : 
    5581        9301 :     return true;
    5582             : }
    5583             : 
    5584             : bool
    5585         220 : BytecodeEmitter::emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern)
    5586             : {
    5587         440 :     TDZCheckCache tdzCache(this);
    5588         440 :     return emitInitializer(initializer, pattern);
    5589             : }
    5590             : 
    5591             : bool
    5592          75 : BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav)
    5593             : {
    5594          75 :     MOZ_ASSERT(pattern->isKind(PNK_ARRAY));
    5595          75 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    5596          75 :     MOZ_ASSERT(this->stackDepth != 0);
    5597             : 
    5598             :     // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
    5599             :     //
    5600             :     // Lines that are annotated "covered by trynote" mean that upon throwing
    5601             :     // an exception, IteratorClose is called on iter only if done is false.
    5602             :     //
    5603             :     //   let x, y;
    5604             :     //   let a, b, c, d;
    5605             :     //   let iter, lref, result, done, value; // stack values
    5606             :     //
    5607             :     //   iter = x[Symbol.iterator]();
    5608             :     //
    5609             :     //   // ==== emitted by loop for a ====
    5610             :     //   lref = GetReference(a);              // covered by trynote
    5611             :     //
    5612             :     //   result = iter.next();
    5613             :     //   done = result.done;
    5614             :     //
    5615             :     //   if (done)
    5616             :     //     value = undefined;
    5617             :     //   else
    5618             :     //     value = result.value;
    5619             :     //
    5620             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5621             :     //
    5622             :     //   // ==== emitted by loop for b ====
    5623             :     //   lref = GetReference(b);              // covered by trynote
    5624             :     //
    5625             :     //   if (done) {
    5626             :     //     value = undefined;
    5627             :     //   } else {
    5628             :     //     result = iter.next();
    5629             :     //     done = result.done;
    5630             :     //     if (done)
    5631             :     //       value = undefined;
    5632             :     //     else
    5633             :     //       value = result.value;
    5634             :     //   }
    5635             :     //
    5636             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5637             :     //
    5638             :     //   // ==== emitted by loop for elision ====
    5639             :     //   if (done) {
    5640             :     //     value = undefined;
    5641             :     //   } else {
    5642             :     //     result = iter.next();
    5643             :     //     done = result.done;
    5644             :     //     if (done)
    5645             :     //       value = undefined;
    5646             :     //     else
    5647             :     //       value = result.value;
    5648             :     //   }
    5649             :     //
    5650             :     //   // ==== emitted by loop for c ====
    5651             :     //   lref = GetReference(c);              // covered by trynote
    5652             :     //
    5653             :     //   if (done) {
    5654             :     //     value = undefined;
    5655             :     //   } else {
    5656             :     //     result = iter.next();
    5657             :     //     done = result.done;
    5658             :     //     if (done)
    5659             :     //       value = undefined;
    5660             :     //     else
    5661             :     //       value = result.value;
    5662             :     //   }
    5663             :     //
    5664             :     //   if (value === undefined)
    5665             :     //     value = y;                         // covered by trynote
    5666             :     //
    5667             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5668             :     //
    5669             :     //   // ==== emitted by loop for d ====
    5670             :     //   lref = GetReference(d);              // covered by trynote
    5671             :     //
    5672             :     //   if (done)
    5673             :     //     value = [];
    5674             :     //   else
    5675             :     //     value = [...iter];
    5676             :     //
    5677             :     //   SetOrInitialize(lref, value);        // covered by trynote
    5678             :     //
    5679             :     //   // === emitted after loop ===
    5680             :     //   if (!done)
    5681             :     //      IteratorClose(iter);
    5682             : 
    5683             :     // Use an iterator to destructure the RHS, instead of index lookup. We
    5684             :     // must leave the *original* value on the stack.
    5685          75 :     if (!emit1(JSOP_DUP))                                         // ... OBJ OBJ
    5686           0 :         return false;
    5687          75 :     if (!emitIterator())                                          // ... OBJ ITER
    5688           0 :         return false;
    5689             : 
    5690             :     // For an empty pattern [], call IteratorClose unconditionally. Nothing
    5691             :     // else needs to be done.
    5692          75 :     if (!pattern->pn_head)
    5693           0 :         return emitIteratorClose();                               // ... OBJ
    5694             : 
    5695             :     // Push an initial FALSE value for DONE.
    5696          75 :     if (!emit1(JSOP_FALSE))                                       // ... OBJ ITER FALSE
    5697           0 :         return false;
    5698             : 
    5699             :     // JSTRY_DESTRUCTURING_ITERCLOSE expects the iterator and the done value
    5700             :     // to be the second to top and the top of the stack, respectively.
    5701             :     // IteratorClose is called upon exception only if done is false.
    5702          75 :     int32_t tryNoteDepth = stackDepth;
    5703             : 
    5704         222 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    5705         147 :         bool isFirst = member == pattern->pn_head;
    5706         294 :         DebugOnly<bool> hasNext = !!member->pn_next;
    5707             : 
    5708         147 :         size_t emitted = 0;
    5709             : 
    5710             :         // Spec requires LHS reference to be evaluated first.
    5711         147 :         ParseNode* lhsPattern = member;
    5712         147 :         if (lhsPattern->isKind(PNK_ASSIGN))
    5713           3 :             lhsPattern = lhsPattern->pn_left;
    5714             : 
    5715         147 :         bool isElision = lhsPattern->isKind(PNK_ELISION);
    5716         147 :         if (!isElision) {
    5717         144 :             auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) {
    5718             :                 return bce->emitDestructuringLHSRef(lhsPattern, &emitted); // ... OBJ ITER DONE *LREF
    5719         288 :             };
    5720         144 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitLHSRef))
    5721           0 :                 return false;
    5722             :         }
    5723             : 
    5724             :         // Pick the DONE value to the top of the stack.
    5725         147 :         if (emitted) {
    5726           4 :             if (!emit2(JSOP_PICK, emitted))                       // ... OBJ ITER *LREF DONE
    5727           0 :                 return false;
    5728             :         }
    5729             : 
    5730         147 :         if (isFirst) {
    5731             :             // If this element is the first, DONE is always FALSE, so pop it.
    5732             :             //
    5733             :             // Non-first elements should emit if-else depending on the
    5734             :             // member pattern, below.
    5735          75 :             if (!emit1(JSOP_POP))                                 // ... OBJ ITER *LREF
    5736           0 :                 return false;
    5737             :         }
    5738             : 
    5739         147 :         if (member->isKind(PNK_SPREAD)) {
    5740           0 :             IfThenElseEmitter ifThenElse(this);
    5741           0 :             if (!isFirst) {
    5742             :                 // If spread is not the first element of the pattern,
    5743             :                 // iterator can already be completed.
    5744             :                                                                   // ... OBJ ITER *LREF DONE
    5745           0 :                 if (!ifThenElse.emitIfElse())                     // ... OBJ ITER *LREF
    5746           0 :                     return false;
    5747             : 
    5748           0 :                 if (!emitUint32Operand(JSOP_NEWARRAY, 0))         // ... OBJ ITER *LREF ARRAY
    5749           0 :                     return false;
    5750           0 :                 if (!ifThenElse.emitElse())                       // ... OBJ ITER *LREF
    5751           0 :                     return false;
    5752             :             }
    5753             : 
    5754             :             // If iterator is not completed, create a new array with the rest
    5755             :             // of the iterator.
    5756           0 :             if (!emitDupAt(emitted))                              // ... OBJ ITER *LREF ITER
    5757           0 :                 return false;
    5758           0 :             if (!emitUint32Operand(JSOP_NEWARRAY, 0))             // ... OBJ ITER *LREF ITER ARRAY
    5759           0 :                 return false;
    5760           0 :             if (!emitNumberOp(0))                                 // ... OBJ ITER *LREF ITER ARRAY INDEX
    5761           0 :                 return false;
    5762           0 :             if (!emitSpread())                                    // ... OBJ ITER *LREF ARRAY INDEX
    5763           0 :                 return false;
    5764           0 :             if (!emit1(JSOP_POP))                                 // ... OBJ ITER *LREF ARRAY
    5765           0 :                 return false;
    5766             : 
    5767           0 :             if (!isFirst) {
    5768           0 :                 if (!ifThenElse.emitEnd())
    5769           0 :                     return false;
    5770           0 :                 MOZ_ASSERT(ifThenElse.pushed() == 1);
    5771             :             }
    5772             : 
    5773             :             // At this point the iterator is done. Unpick a TRUE value for DONE above ITER.
    5774           0 :             if (!emit1(JSOP_TRUE))                                // ... OBJ ITER *LREF ARRAY TRUE
    5775           0 :                 return false;
    5776           0 :             if (!emit2(JSOP_UNPICK, emitted + 1))                 // ... OBJ ITER TRUE *LREF ARRAY
    5777           0 :                 return false;
    5778             : 
    5779           0 :             auto emitAssignment = [member, flav](BytecodeEmitter* bce) {
    5780             :                 return bce->emitSetOrInitializeDestructuring(member, flav); // ... OBJ ITER TRUE
    5781           0 :             };
    5782           0 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitAssignment))
    5783           0 :                 return false;
    5784             : 
    5785           0 :             MOZ_ASSERT(!hasNext);
    5786           0 :             break;
    5787             :         }
    5788             : 
    5789         147 :         ParseNode* pndefault = nullptr;
    5790         147 :         if (member->isKind(PNK_ASSIGN))
    5791           3 :             pndefault = member->pn_right;
    5792             : 
    5793         147 :         MOZ_ASSERT(!member->isKind(PNK_SPREAD));
    5794             : 
    5795         294 :         IfThenElseEmitter ifAlreadyDone(this);
    5796         147 :         if (!isFirst) {
    5797             :                                                                   // ... OBJ ITER *LREF DONE
    5798          72 :             if (!ifAlreadyDone.emitIfElse())                      // ... OBJ ITER *LREF
    5799           0 :                 return false;
    5800             : 
    5801          72 :             if (!emit1(JSOP_UNDEFINED))                           // ... OBJ ITER *LREF UNDEF
    5802           0 :                 return false;
    5803          72 :             if (!emit1(JSOP_NOP_DESTRUCTURING))                   // ... OBJ ITER *LREF UNDEF
    5804           0 :                 return false;
    5805             : 
    5806             :             // The iterator is done. Unpick a TRUE value for DONE above ITER.
    5807          72 :             if (!emit1(JSOP_TRUE))                                // ... OBJ ITER *LREF UNDEF TRUE
    5808           0 :                 return false;
    5809          72 :             if (!emit2(JSOP_UNPICK, emitted + 1))                 // ... OBJ ITER TRUE *LREF UNDEF
    5810           0 :                 return false;
    5811             : 
    5812          72 :             if (!ifAlreadyDone.emitElse())                        // ... OBJ ITER *LREF
    5813           0 :                 return false;
    5814             :         }
    5815             : 
    5816         147 :         if (!emitDupAt(emitted))                                  // ... OBJ ITER *LREF ITER
    5817           0 :             return false;
    5818         147 :         if (!emitIteratorNext(pattern))                           // ... OBJ ITER *LREF RESULT
    5819           0 :             return false;
    5820         147 :         if (!emit1(JSOP_DUP))                                     // ... OBJ ITER *LREF RESULT RESULT
    5821           0 :             return false;
    5822         147 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))          // ... OBJ ITER *LREF RESULT DONE
    5823           0 :             return false;
    5824             : 
    5825         147 :         if (!emit1(JSOP_DUP))                                     // ... OBJ ITER *LREF RESULT DONE DONE
    5826           0 :             return false;
    5827         147 :         if (!emit2(JSOP_UNPICK, emitted + 2))                     // ... OBJ ITER DONE *LREF RESULT DONE
    5828           0 :             return false;
    5829             : 
    5830         294 :         IfThenElseEmitter ifDone(this);
    5831         147 :         if (!ifDone.emitIfElse())                                 // ... OBJ ITER DONE *LREF RESULT
    5832           0 :             return false;
    5833             : 
    5834         147 :         if (!emit1(JSOP_POP))                                     // ... OBJ ITER DONE *LREF
    5835           0 :             return false;
    5836         147 :         if (!emit1(JSOP_UNDEFINED))                               // ... OBJ ITER DONE *LREF UNDEF
    5837           0 :             return false;
    5838         147 :         if (!emit1(JSOP_NOP_DESTRUCTURING))                       // ... OBJ ITER DONE *LREF UNDEF
    5839           0 :             return false;
    5840             : 
    5841         147 :         if (!ifDone.emitElse())                                   // ... OBJ ITER DONE *LREF RESULT
    5842           0 :             return false;
    5843             : 
    5844         147 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP))         // ... OBJ ITER DONE *LREF VALUE
    5845           0 :             return false;
    5846             : 
    5847         147 :         if (!ifDone.emitEnd())
    5848           0 :             return false;
    5849         147 :         MOZ_ASSERT(ifDone.pushed() == 0);
    5850             : 
    5851         147 :         if (!isFirst) {
    5852          72 :             if (!ifAlreadyDone.emitEnd())
    5853           0 :                 return false;
    5854          72 :             MOZ_ASSERT(ifAlreadyDone.pushed() == 2);
    5855             :         }
    5856             : 
    5857         147 :         if (pndefault) {
    5858           3 :             auto emitDefault = [pndefault, lhsPattern](BytecodeEmitter* bce) {
    5859             :                 return bce->emitDefault(pndefault, lhsPattern);    // ... OBJ ITER DONE *LREF VALUE
    5860           6 :             };
    5861             : 
    5862           3 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitDefault))
    5863           0 :                 return false;
    5864             :         }
    5865             : 
    5866         147 :         if (!isElision) {
    5867         144 :             auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) {
    5868             :                 return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); // ... OBJ ITER DONE
    5869         288 :             };
    5870             : 
    5871         144 :             if (!wrapWithDestructuringIteratorCloseTryNote(tryNoteDepth, emitAssignment))
    5872           0 :                 return false;
    5873             :         } else {
    5874           3 :             if (!emit1(JSOP_POP))                                 // ... OBJ ITER DONE
    5875           0 :                 return false;
    5876             :         }
    5877             :     }
    5878             : 
    5879             :     // The last DONE value is on top of the stack. If not DONE, call
    5880             :     // IteratorClose.
    5881             :                                                                   // ... OBJ ITER DONE
    5882         150 :     IfThenElseEmitter ifDone(this);
    5883          75 :     if (!ifDone.emitIfElse())                                     // ... OBJ ITER
    5884           0 :         return false;
    5885          75 :     if (!emit1(JSOP_POP))                                         // ... OBJ
    5886           0 :         return false;
    5887          75 :     if (!ifDone.emitElse())                                       // ... OBJ ITER
    5888           0 :         return false;
    5889          75 :     if (!emitIteratorClose())                                     // ... OBJ
    5890           0 :         return false;
    5891          75 :     if (!ifDone.emitEnd())
    5892           0 :         return false;
    5893             : 
    5894          75 :     return true;
    5895             : }
    5896             : 
    5897             : bool
    5898           5 : BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName)
    5899             : {
    5900           5 :     MOZ_ASSERT(computedPropName->isKind(PNK_COMPUTED_NAME));
    5901           5 :     return emitTree(computedPropName->pn_kid) && emit1(JSOP_TOID);
    5902             : }
    5903             : 
    5904             : bool
    5905         169 : BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
    5906             : {
    5907         169 :     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
    5908         169 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    5909             : 
    5910         169 :     MOZ_ASSERT(this->stackDepth > 0);                             // ... RHS
    5911             : 
    5912         169 :     if (!emit1(JSOP_CHECKOBJCOERCIBLE))                           // ... RHS
    5913           0 :         return false;
    5914             : 
    5915         279 :     bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
    5916         279 :                                         pattern->last()->isKind(PNK_SPREAD);
    5917         169 :     if (needsRestPropertyExcludedSet) {
    5918           0 :         if (!emitDestructuringObjRestExclusionSet(pattern))       // ... RHS SET
    5919           0 :             return false;
    5920             : 
    5921           0 :         if (!emit1(JSOP_SWAP))                                    // ... SET RHS
    5922           0 :             return false;
    5923             :     }
    5924             : 
    5925         567 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    5926             :         ParseNode* subpattern;
    5927         398 :         if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD))
    5928           0 :             subpattern = member->pn_kid;
    5929             :         else
    5930         398 :             subpattern = member->pn_right;
    5931             : 
    5932         398 :         ParseNode* lhs = subpattern;
    5933         398 :         MOZ_ASSERT_IF(member->isKind(PNK_SPREAD), !lhs->isKind(PNK_ASSIGN));
    5934         398 :         if (lhs->isKind(PNK_ASSIGN))
    5935           4 :             lhs = lhs->pn_left;
    5936             : 
    5937             :         size_t emitted;
    5938         398 :         if (!emitDestructuringLHSRef(lhs, &emitted))              // ... *SET RHS *LREF
    5939           0 :             return false;
    5940             : 
    5941             :         // Duplicate the value being destructured to use as a reference base.
    5942         398 :         if (!emitDupAt(emitted))                                  // ... *SET RHS *LREF RHS
    5943           0 :             return false;
    5944             : 
    5945         398 :         if (member->isKind(PNK_SPREAD)) {
    5946           0 :             if (!updateSourceCoordNotes(member->pn_pos.begin))
    5947           0 :                 return false;
    5948             : 
    5949           0 :             if (!emitNewInit(JSProto_Object))                     // ... *SET RHS *LREF RHS TARGET
    5950           0 :                 return false;
    5951           0 :             if (!emit1(JSOP_DUP))                                 // ... *SET RHS *LREF RHS TARGET TARGET
    5952           0 :                 return false;
    5953           0 :             if (!emit2(JSOP_PICK, 2))                             // ... *SET RHS *LREF TARGET TARGET RHS
    5954           0 :                 return false;
    5955             : 
    5956           0 :             if (needsRestPropertyExcludedSet) {
    5957           0 :                 if (!emit2(JSOP_PICK, emitted + 4))               // ... RHS *LREF TARGET TARGET RHS SET
    5958           0 :                     return false;
    5959             :             }
    5960             : 
    5961             :             CopyOption option = needsRestPropertyExcludedSet
    5962           0 :                                 ? CopyOption::Filtered
    5963           0 :                                 : CopyOption::Unfiltered;
    5964           0 :             if (!emitCopyDataProperties(option))                  // ... RHS *LREF TARGET
    5965           0 :                 return false;
    5966             : 
    5967             :             // Destructure TARGET per this member's lhs.
    5968           0 :             if (!emitSetOrInitializeDestructuring(lhs, flav))     // ... RHS
    5969           0 :                 return false;
    5970             : 
    5971           0 :             MOZ_ASSERT(member == pattern->last(), "Rest property is always last");
    5972           0 :             break;
    5973             :         }
    5974             : 
    5975             :         // Now push the property name currently being matched, which is the
    5976             :         // current property name "label" on the left of a colon in the object
    5977             :         // initialiser.
    5978         398 :         bool needsGetElem = true;
    5979             : 
    5980         398 :         if (member->isKind(PNK_MUTATEPROTO)) {
    5981           0 :             if (!emitAtomOp(cx->names().proto, JSOP_GETPROP))     // ... *SET RHS *LREF PROP
    5982           0 :                 return false;
    5983           0 :             needsGetElem = false;
    5984             :         } else {
    5985         398 :             MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
    5986             : 
    5987         398 :             ParseNode* key = member->pn_left;
    5988         398 :             if (key->isKind(PNK_NUMBER)) {
    5989           0 :                 if (!emitNumberOp(key->pn_dval))                  // ... *SET RHS *LREF RHS KEY
    5990           0 :                     return false;
    5991         398 :             } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
    5992         398 :                 if (!emitAtomOp(key->pn_atom, JSOP_GETPROP))      // ... *SET RHS *LREF PROP
    5993           0 :                     return false;
    5994         398 :                 needsGetElem = false;
    5995             :             } else {
    5996           0 :                 if (!emitComputedPropertyName(key))               // ... *SET RHS *LREF RHS KEY
    5997           0 :                     return false;
    5998             : 
    5999             :                 // Add the computed property key to the exclusion set.
    6000           0 :                 if (needsRestPropertyExcludedSet) {
    6001           0 :                     if (!emitDupAt(emitted + 3))                  // ... SET RHS *LREF RHS KEY SET
    6002           0 :                         return false;
    6003           0 :                     if (!emitDupAt(1))                            // ... SET RHS *LREF RHS KEY SET KEY
    6004           0 :                         return false;
    6005           0 :                     if (!emit1(JSOP_UNDEFINED))                   // ... SET RHS *LREF RHS KEY SET KEY UNDEFINED
    6006           0 :                         return false;
    6007           0 :                     if (!emit1(JSOP_INITELEM))                    // ... SET RHS *LREF RHS KEY SET
    6008           0 :                         return false;
    6009           0 :                     if (!emit1(JSOP_POP))                         // ... SET RHS *LREF RHS KEY
    6010           0 :                         return false;
    6011             :                 }
    6012             :             }
    6013             :         }
    6014             : 
    6015             :         // Get the property value if not done already.
    6016         398 :         if (needsGetElem && !emitElemOpBase(JSOP_GETELEM))        // ... *SET RHS *LREF PROP
    6017           0 :             return false;
    6018             : 
    6019         398 :         if (subpattern->isKind(PNK_ASSIGN)) {
    6020           4 :             if (!emitDefault(subpattern->pn_right, lhs))          // ... *SET RHS *LREF VALUE
    6021           0 :                 return false;
    6022             :         }
    6023             : 
    6024             :         // Destructure PROP per this member's lhs.
    6025         398 :         if (!emitSetOrInitializeDestructuring(subpattern, flav))  // ... *SET RHS
    6026           0 :             return false;
    6027             :     }
    6028             : 
    6029         169 :     return true;
    6030             : }
    6031             : 
    6032             : bool
    6033           0 : BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
    6034             : {
    6035           0 :     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
    6036           0 :     MOZ_ASSERT(pattern->isArity(PN_LIST));
    6037           0 :     MOZ_ASSERT(pattern->last()->isKind(PNK_SPREAD));
    6038             : 
    6039           0 :     ptrdiff_t offset = this->offset();
    6040           0 :     if (!emitNewInit(JSProto_Object))
    6041           0 :         return false;
    6042             : 
    6043             :     // Try to construct the shape of the object as we go, so we can emit a
    6044             :     // JSOP_NEWOBJECT with the final shape instead.
    6045             :     // In the case of computed property names and indices, we cannot fix the
    6046             :     // shape at bytecode compile time. When the shape cannot be determined,
    6047             :     // |obj| is nulled out.
    6048             : 
    6049             :     // No need to do any guessing for the object kind, since we know the upper
    6050             :     // bound of how many properties we plan to have.
    6051           0 :     gc::AllocKind kind = gc::GetGCObjectKind(pattern->pn_count - 1);
    6052           0 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
    6053           0 :     if (!obj)
    6054           0 :         return false;
    6055             : 
    6056           0 :     RootedAtom pnatom(cx);
    6057           0 :     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
    6058           0 :         if (member->isKind(PNK_SPREAD))
    6059           0 :             break;
    6060             : 
    6061           0 :         bool isIndex = false;
    6062           0 :         if (member->isKind(PNK_MUTATEPROTO)) {
    6063           0 :             pnatom.set(cx->names().proto);
    6064             :         } else {
    6065           0 :             ParseNode* key = member->pn_left;
    6066           0 :             if (key->isKind(PNK_NUMBER)) {
    6067           0 :                 if (!emitNumberOp(key->pn_dval))
    6068           0 :                     return false;
    6069           0 :                 isIndex = true;
    6070           0 :             } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
    6071           0 :                 pnatom.set(key->pn_atom);
    6072             :             } else {
    6073             :                 // Otherwise this is a computed property name which needs to
    6074             :                 // be added dynamically.
    6075           0 :                 obj.set(nullptr);
    6076           0 :                 continue;
    6077             :             }
    6078             :         }
    6079             : 
    6080             :         // Initialize elements with |undefined|.
    6081           0 :         if (!emit1(JSOP_UNDEFINED))
    6082           0 :             return false;
    6083             : 
    6084           0 :         if (isIndex) {
    6085           0 :             obj.set(nullptr);
    6086           0 :             if (!emit1(JSOP_INITELEM))
    6087           0 :                 return false;
    6088             :         } else {
    6089             :             uint32_t index;
    6090           0 :             if (!makeAtomIndex(pnatom, &index))
    6091           0 :                 return false;
    6092             : 
    6093           0 :             if (obj) {
    6094           0 :                 MOZ_ASSERT(!obj->inDictionaryMode());
    6095           0 :                 Rooted<jsid> id(cx, AtomToId(pnatom));
    6096           0 :                 if (!NativeDefineProperty(cx, obj, id, UndefinedHandleValue, nullptr, nullptr,
    6097             :                                           JSPROP_ENUMERATE))
    6098             :                 {
    6099           0 :                     return false;
    6100             :                 }
    6101           0 :                 if (obj->inDictionaryMode())
    6102           0 :                     obj.set(nullptr);
    6103             :             }
    6104             : 
    6105           0 :             if (!emitIndex32(JSOP_INITPROP, index))
    6106           0 :                 return false;
    6107             :         }
    6108             :     }
    6109             : 
    6110           0 :     if (obj) {
    6111             :         // The object survived and has a predictable shape: update the
    6112             :         // original bytecode.
    6113           0 :         if (!replaceNewInitWithNewObject(obj, offset))
    6114           0 :             return false;
    6115             :     }
    6116             : 
    6117           0 :     return true;
    6118             : }
    6119             : 
    6120             : bool
    6121         244 : BytecodeEmitter::emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav)
    6122             : {
    6123         244 :     if (pattern->isKind(PNK_ARRAY))
    6124          75 :         return emitDestructuringOpsArray(pattern, flav);
    6125         169 :     return emitDestructuringOpsObject(pattern, flav);
    6126             : }
    6127             : 
    6128             : bool
    6129         252 : BytecodeEmitter::emitTemplateString(ParseNode* pn)
    6130             : {
    6131         252 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    6132             : 
    6133         252 :     bool pushedString = false;
    6134             : 
    6135        1708 :     for (ParseNode* pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
    6136        1456 :         bool isString = (pn2->getKind() == PNK_STRING || pn2->getKind() == PNK_TEMPLATE_STRING);
    6137             : 
    6138             :         // Skip empty strings. These are very common: a template string like
    6139             :         // `${a}${b}` has three empty strings and without this optimization
    6140             :         // we'd emit four JSOP_ADD operations instead of just one.
    6141        1456 :         if (isString && pn2->pn_atom->empty())
    6142         115 :             continue;
    6143             : 
    6144        1341 :         if (!isString) {
    6145             :             // We update source notes before emitting the expression
    6146         602 :             if (!updateSourceCoordNotes(pn2->pn_pos.begin))
    6147           0 :                 return false;
    6148             :         }
    6149             : 
    6150        1341 :         if (!emitTree(pn2))
    6151           0 :             return false;
    6152             : 
    6153        1341 :         if (!isString) {
    6154             :             // We need to convert the expression to a string
    6155         602 :             if (!emit1(JSOP_TOSTRING))
    6156           0 :                 return false;
    6157             :         }
    6158             : 
    6159        1341 :         if (pushedString) {
    6160             :             // We've pushed two strings onto the stack. Add them together, leaving just one.
    6161        1089 :             if (!emit1(JSOP_ADD))
    6162           0 :                 return false;
    6163             :         } else {
    6164         252 :             pushedString = true;
    6165             :         }
    6166             :     }
    6167             : 
    6168         252 :     if (!pushedString) {
    6169             :         // All strings were empty, this can happen for something like `${""}`.
    6170             :         // Just push an empty string.
    6171           0 :         if (!emitAtomOp(cx->names().empty, JSOP_STRING))
    6172           0 :             return false;
    6173             :     }
    6174             : 
    6175         252 :     return true;
    6176             : }
    6177             : 
    6178             : bool
    6179        9556 : BytecodeEmitter::emitDeclarationList(ParseNode* declList)
    6180             : {
    6181        9556 :     MOZ_ASSERT(declList->isArity(PN_LIST));
    6182             : 
    6183             :     ParseNode* next;
    6184       19223 :     for (ParseNode* decl = declList->pn_head; decl; decl = next) {
    6185        9666 :         if (!updateSourceCoordNotes(decl->pn_pos.begin))
    6186           0 :             return false;
    6187        9666 :         next = decl->pn_next;
    6188             : 
    6189        9666 :         if (decl->isKind(PNK_ASSIGN)) {
    6190         130 :             MOZ_ASSERT(decl->isOp(JSOP_NOP));
    6191             : 
    6192         130 :             ParseNode* pattern = decl->pn_left;
    6193         130 :             MOZ_ASSERT(pattern->isKind(PNK_ARRAY) || pattern->isKind(PNK_OBJECT));
    6194             : 
    6195         130 :             if (!emitTree(decl->pn_right))
    6196           0 :                 return false;
    6197             : 
    6198         130 :             if (!emitDestructuringOps(pattern, DestructuringDeclaration))
    6199           0 :                 return false;
    6200             : 
    6201         130 :             if (!emit1(JSOP_POP))
    6202           0 :                 return false;
    6203             :         } else {
    6204        9536 :             if (!emitSingleDeclaration(declList, decl, decl->expr()))
    6205           0 :                 return false;
    6206             :         }
    6207             :     }
    6208        9557 :     return true;
    6209             : }
    6210             : 
    6211             : bool
    6212        9536 : BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
    6213             :                                        ParseNode* initializer)
    6214             : {
    6215        9536 :     MOZ_ASSERT(decl->isKind(PNK_NAME));
    6216             : 
    6217             :     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
    6218        9536 :     if (!initializer && declList->isKind(PNK_VAR))
    6219         304 :         return true;
    6220             : 
    6221       27544 :     auto emitRhs = [initializer, declList, decl](BytecodeEmitter* bce, const NameLocation&, bool) {
    6222        9232 :         if (!initializer) {
    6223             :             // Lexical declarations are initialized to undefined without an
    6224             :             // initializer.
    6225         152 :             MOZ_ASSERT(declList->isKind(PNK_LET),
    6226             :                        "var declarations without initializers handled above, "
    6227             :                        "and const declarations must have initializers");
    6228         152 :             Unused << declList; // silence clang -Wunused-lambda-capture in opt builds
    6229         152 :             return bce->emit1(JSOP_UNDEFINED);
    6230             :         }
    6231             : 
    6232        9080 :         MOZ_ASSERT(initializer);
    6233        9080 :         return bce->emitInitializer(initializer, decl);
    6234        9232 :     };
    6235             : 
    6236        9232 :     if (!emitInitializeName(decl, emitRhs))
    6237           0 :         return false;
    6238             : 
    6239             :     // Pop the RHS.
    6240        9233 :     return emit1(JSOP_POP);
    6241             : }
    6242             : 
    6243             : static bool
    6244        5736 : EmitAssignmentRhs(BytecodeEmitter* bce, ParseNode* rhs, uint8_t offset)
    6245             : {
    6246             :     // If there is a RHS tree, emit the tree.
    6247        5736 :     if (rhs)
    6248        5736 :         return bce->emitTree(rhs);
    6249             : 
    6250             :     // Otherwise the RHS value to assign is already on the stack, i.e., the
    6251             :     // next enumeration value in a for-in or for-of loop. Depending on how
    6252             :     // many other values have been pushed on the stack, we need to get the
    6253             :     // already-pushed RHS value.
    6254           0 :     if (offset != 1 && !bce->emit2(JSOP_PICK, offset - 1))
    6255           0 :         return false;
    6256             : 
    6257           0 :     return true;
    6258             : }
    6259             : 
    6260             : bool
    6261        5736 : BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
    6262             : {
    6263             :     // Name assignments are handled separately because choosing ops and when
    6264             :     // to emit BINDNAME is involved and should avoid duplication.
    6265        5736 :     if (lhs->isKind(PNK_NAME)) {
    6266             :         auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc,
    6267        2654 :                                       bool emittedBindOp)
    6268       18622 :         {
    6269             :             // For compound assignments, first get the LHS value, then emit
    6270             :             // the RHS and the op.
    6271        2654 :             if (op != JSOP_NOP) {
    6272         371 :                 if (!bce->emitGetNameAtLocationForCompoundAssignment(lhs->name(), lhsLoc))
    6273           0 :                     return false;
    6274             :             }
    6275             : 
    6276             :             // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on
    6277             :             // the top of the stack and we need to pick the right RHS value.
    6278        5308 :             if (!EmitAssignmentRhs(bce, rhs, emittedBindOp ? 2 : 1))
    6279           0 :                 return false;
    6280             : 
    6281        9874 :             if (!lhs->isInParens() && op == JSOP_NOP && rhs && rhs->isDirectRHSAnonFunction()) {
    6282          44 :                 RootedAtom name(bce->cx, lhs->name());
    6283          44 :                 if (!bce->setOrEmitSetFunName(rhs, name, FunctionPrefixKind::None))
    6284           0 :                     return false;
    6285             :             }
    6286             : 
    6287             :             // Emit the compound assignment op if there is one.
    6288        3025 :             if (op != JSOP_NOP && !bce->emit1(op))
    6289           0 :                 return false;
    6290             : 
    6291        2654 :             return true;
    6292        2654 :         };
    6293             : 
    6294        2654 :         return emitSetName(lhs, emitRhs);
    6295             :     }
    6296             : 
    6297             :     // Deal with non-name assignments.
    6298        3082 :     uint32_t atomIndex = (uint32_t) -1;
    6299        3082 :     uint8_t offset = 1;
    6300             : 
    6301        3082 :     switch (lhs->getKind()) {
    6302             :       case PNK_DOT:
    6303        2735 :         if (lhs->as<PropertyAccess>().isSuper()) {
    6304           0 :             if (!emitSuperPropLHS(&lhs->as<PropertyAccess>().expression()))
    6305           0 :                 return false;
    6306           0 :             offset += 2;
    6307             :         } else {
    6308        2735 :             if (!emitTree(lhs->expr()))
    6309           0 :                 return false;
    6310        2735 :             offset += 1;
    6311             :         }
    6312        2735 :         if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
    6313           0 :             return false;
    6314        2735 :         break;
    6315             :       case PNK_ELEM: {
    6316         340 :         MOZ_ASSERT(lhs->isArity(PN_BINARY));
    6317         340 :         EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign;
    6318         340 :         if (lhs->as<PropertyByValue>().isSuper()) {
    6319           0 :             if (!emitSuperElemOperands(lhs, opt))
    6320           0 :                 return false;
    6321           0 :             offset += 3;
    6322             :         } else {
    6323         340 :             if (!emitElemOperands(lhs, opt))
    6324           0 :                 return false;
    6325         340 :             offset += 2;
    6326             :         }
    6327         340 :         break;
    6328             :       }
    6329             :       case PNK_ARRAY:
    6330             :       case PNK_OBJECT:
    6331           7 :         break;
    6332             :       case PNK_CALL:
    6333           0 :         if (!emitTree(lhs))
    6334           0 :             return false;
    6335             : 
    6336             :         // Assignment to function calls is forbidden, but we have to make the
    6337             :         // call first.  Now we can throw.
    6338           0 :         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS))
    6339           0 :             return false;
    6340             : 
    6341             :         // Rebalance the stack to placate stack-depth assertions.
    6342           0 :         if (!emit1(JSOP_POP))
    6343           0 :             return false;
    6344           0 :         break;
    6345             :       default:
    6346           0 :         MOZ_ASSERT(0);
    6347             :     }
    6348             : 
    6349        3082 :     if (op != JSOP_NOP) {
    6350          60 :         MOZ_ASSERT(rhs);
    6351          60 :         switch (lhs->getKind()) {
    6352             :           case PNK_DOT: {
    6353             :             JSOp getOp;
    6354          32 :             if (lhs->as<PropertyAccess>().isSuper()) {
    6355           0 :                 if (!emit1(JSOP_DUP2))
    6356           0 :                     return false;
    6357           0 :                 getOp = JSOP_GETPROP_SUPER;
    6358             :             } else {
    6359          32 :                 if (!emit1(JSOP_DUP))
    6360           0 :                     return false;
    6361          32 :                 bool isLength = (lhs->pn_atom == cx->names().length);
    6362          32 :                 getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
    6363             :             }
    6364          32 :             if (!emitIndex32(getOp, atomIndex))
    6365           0 :                 return false;
    6366          32 :             break;
    6367             :           }
    6368             :           case PNK_ELEM: {
    6369             :             JSOp elemOp;
    6370          28 :             if (lhs->as<PropertyByValue>().isSuper()) {
    6371           0 :                 if (!emitDupAt(2))
    6372           0 :                     return false;
    6373           0 :                 if (!emitDupAt(2))
    6374           0 :                     return false;
    6375           0 :                 if (!emitDupAt(2))
    6376           0 :                     return false;
    6377           0 :                 elemOp = JSOP_GETELEM_SUPER;
    6378             :             } else {
    6379          28 :                 if (!emit1(JSOP_DUP2))
    6380           0 :                     return false;
    6381          28 :                 elemOp = JSOP_GETELEM;
    6382             :             }
    6383          28 :             if (!emitElemOpBase(elemOp))
    6384           0 :                 return false;
    6385          28 :             break;
    6386             :           }
    6387             :           case PNK_CALL:
    6388             :             // We just emitted a JSOP_THROWMSG and popped the call's return
    6389             :             // value.  Push a random value to make sure the stack depth is
    6390             :             // correct.
    6391           0 :             if (!emit1(JSOP_NULL))
    6392           0 :                 return false;
    6393           0 :             break;
    6394             :           default:;
    6395             :         }
    6396             :     }
    6397             : 
    6398        3082 :     if (!EmitAssignmentRhs(this, rhs, offset))
    6399           0 :         return false;
    6400             : 
    6401             :     /* If += etc., emit the binary operator with a source note. */
    6402        3082 :     if (op != JSOP_NOP) {
    6403          60 :         if (!newSrcNote(SRC_ASSIGNOP))
    6404           0 :             return false;
    6405          60 :         if (!emit1(op))
    6406           0 :             return false;
    6407             :     }
    6408             : 
    6409             :     /* Finally, emit the specialized assignment bytecode. */
    6410        3082 :     switch (lhs->getKind()) {
    6411             :       case PNK_DOT: {
    6412        5470 :         JSOp setOp = lhs->as<PropertyAccess>().isSuper() ?
    6413           0 :                        (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) :
    6414        5470 :                        (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP);
    6415        2735 :         if (!emitIndexOp(setOp, atomIndex))
    6416           0 :             return false;
    6417        2735 :         break;
    6418             :       }
    6419             :       case PNK_CALL:
    6420             :         // We threw above, so nothing to do here.
    6421           0 :         break;
    6422             :       case PNK_ELEM: {
    6423         680 :         JSOp setOp = lhs->as<PropertyByValue>().isSuper() ?
    6424           0 :                        sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER :
    6425         680 :                        sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
    6426         340 :         if (!emit1(setOp))
    6427           0 :             return false;
    6428         340 :         break;
    6429             :       }
    6430             :       case PNK_ARRAY:
    6431             :       case PNK_OBJECT:
    6432           7 :         if (!emitDestructuringOps(lhs, DestructuringAssignment))
    6433           0 :             return false;
    6434           7 :         break;
    6435             :       default:
    6436           0 :         MOZ_ASSERT(0);
    6437             :     }
    6438        3082 :     return true;
    6439             : }
    6440             : 
    6441             : bool
    6442        4773 : ParseNode::getConstantValue(JSContext* cx, AllowConstantObjects allowObjects,
    6443             :                             MutableHandleValue vp, Value* compare, size_t ncompare,
    6444             :                             NewObjectKind newKind)
    6445             : {
    6446        4773 :     MOZ_ASSERT(newKind == TenuredObject || newKind == SingletonObject);
    6447             : 
    6448        4773 :     switch (getKind()) {
    6449             :       case PNK_NUMBER:
    6450         102 :         vp.setNumber(pn_dval);
    6451         102 :         return true;
    6452             :       case PNK_TEMPLATE_STRING:
    6453             :       case PNK_STRING:
    6454        3454 :         vp.setString(pn_atom);
    6455        3454 :         return true;
    6456             :       case PNK_TRUE:
    6457           2 :         vp.setBoolean(true);
    6458           2 :         return true;
    6459             :       case PNK_FALSE:
    6460           2 :         vp.setBoolean(false);
    6461           2 :         return true;
    6462             :       case PNK_NULL:
    6463           6 :         vp.setNull();
    6464           6 :         return true;
    6465             :       case PNK_RAW_UNDEFINED:
    6466           0 :         vp.setUndefined();
    6467           0 :         return true;
    6468             :       case PNK_CALLSITEOBJ:
    6469             :       case PNK_ARRAY: {
    6470             :         unsigned count;
    6471             :         ParseNode* pn;
    6472             : 
    6473         473 :         if (allowObjects == DontAllowObjects) {
    6474           4 :             vp.setMagic(JS_GENERIC_MAGIC);
    6475           4 :             return true;
    6476             :         }
    6477             : 
    6478         469 :         ObjectGroup::NewArrayKind arrayKind = ObjectGroup::NewArrayKind::Normal;
    6479         469 :         if (allowObjects == ForCopyOnWriteArray) {
    6480         452 :             arrayKind = ObjectGroup::NewArrayKind::CopyOnWrite;
    6481         452 :             allowObjects = DontAllowObjects;
    6482             :         }
    6483             : 
    6484         469 :         if (getKind() == PNK_CALLSITEOBJ) {
    6485           1 :             count = pn_count - 1;
    6486           1 :             pn = pn_head->pn_next;
    6487             :         } else {
    6488         468 :             MOZ_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
    6489         468 :             count = pn_count;
    6490         468 :             pn = pn_head;
    6491             :         }
    6492             : 
    6493         939 :         AutoValueVector values(cx);
    6494         469 :         if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), count))
    6495           0 :             return false;
    6496             :         size_t idx;
    6497        2076 :         for (idx = 0; pn; idx++, pn = pn->pn_next) {
    6498        1614 :             if (!pn->getConstantValue(cx, allowObjects, values[idx], values.begin(), idx))
    6499           0 :                 return false;
    6500        1614 :             if (values[idx].isMagic(JS_GENERIC_MAGIC)) {
    6501           7 :                 vp.setMagic(JS_GENERIC_MAGIC);
    6502           7 :                 return true;
    6503             :             }
    6504             :         }
    6505         462 :         MOZ_ASSERT(idx == count);
    6506             : 
    6507         462 :         JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
    6508         462 :                                                     newKind, arrayKind);
    6509         463 :         if (!obj)
    6510           0 :             return false;
    6511             : 
    6512         463 :         if (!CombineArrayElementTypes(cx, obj, compare, ncompare))
    6513           0 :             return false;
    6514             : 
    6515         463 :         vp.setObject(*obj);
    6516         463 :         return true;
    6517             :       }
    6518             :       case PNK_OBJECT: {
    6519         734 :         MOZ_ASSERT(isOp(JSOP_NEWINIT));
    6520         734 :         MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
    6521             : 
    6522         734 :         if (allowObjects == DontAllowObjects) {
    6523           3 :             vp.setMagic(JS_GENERIC_MAGIC);
    6524           3 :             return true;
    6525             :         }
    6526         731 :         MOZ_ASSERT(allowObjects == AllowObjects);
    6527             : 
    6528        1462 :         Rooted<IdValueVector> properties(cx, IdValueVector(cx));
    6529             : 
    6530        1462 :         RootedValue value(cx), idvalue(cx);
    6531        3395 :         for (ParseNode* pn = pn_head; pn; pn = pn->pn_next) {
    6532        2664 :             if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
    6533           0 :                 return false;
    6534        2664 :             if (value.isMagic(JS_GENERIC_MAGIC)) {
    6535           0 :                 vp.setMagic(JS_GENERIC_MAGIC);
    6536           0 :                 return true;
    6537             :             }
    6538             : 
    6539        2664 :             ParseNode* pnid = pn->pn_left;
    6540        2664 :             if (pnid->isKind(PNK_NUMBER)) {
    6541           0 :                 idvalue = NumberValue(pnid->pn_dval);
    6542             :             } else {
    6543        2664 :                 MOZ_ASSERT(pnid->isKind(PNK_OBJECT_PROPERTY_NAME) || pnid->isKind(PNK_STRING));
    6544        2664 :                 MOZ_ASSERT(pnid->pn_atom != cx->names().proto);
    6545        2664 :                 idvalue = StringValue(pnid->pn_atom);
    6546             :             }
    6547             : 
    6548        5328 :             RootedId id(cx);
    6549        2664 :             if (!ValueToId<CanGC>(cx, idvalue, &id))
    6550           0 :                 return false;
    6551             : 
    6552        2664 :             if (!properties.append(IdValuePair(id, value)))
    6553           0 :                 return false;
    6554             :         }
    6555             : 
    6556         731 :         JSObject* obj = ObjectGroup::newPlainObject(cx, properties.begin(), properties.length(),
    6557         731 :                                                     newKind);
    6558         731 :         if (!obj)
    6559           0 :             return false;
    6560             : 
    6561         731 :         if (!CombinePlainObjectPropertyTypes(cx, obj, compare, ncompare))
    6562           0 :             return false;
    6563             : 
    6564         731 :         vp.setObject(*obj);
    6565         731 :         return true;
    6566             :       }
    6567             :       default:
    6568           0 :         MOZ_CRASH("Unexpected node");
    6569             :     }
    6570             :     return false;
    6571             : }
    6572             : 
    6573             : bool
    6574          41 : BytecodeEmitter::emitSingletonInitialiser(ParseNode* pn)
    6575             : {
    6576          41 :     NewObjectKind newKind = (pn->getKind() == PNK_OBJECT) ? SingletonObject : TenuredObject;
    6577             : 
    6578          82 :     RootedValue value(cx);
    6579          41 :     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value, nullptr, 0, newKind))
    6580           0 :         return false;
    6581             : 
    6582          41 :     MOZ_ASSERT_IF(newKind == SingletonObject, value.toObject().isSingleton());
    6583             : 
    6584          41 :     ObjectBox* objbox = parser.newObjectBox(&value.toObject());
    6585          41 :     if (!objbox)
    6586           0 :         return false;
    6587             : 
    6588          41 :     return emitObjectOp(objbox, JSOP_OBJECT);
    6589             : }
    6590             : 
    6591             : bool
    6592           1 : BytecodeEmitter::emitCallSiteObject(ParseNode* pn)
    6593             : {
    6594           2 :     RootedValue value(cx);
    6595           1 :     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value))
    6596           0 :         return false;
    6597             : 
    6598           1 :     MOZ_ASSERT(value.isObject());
    6599             : 
    6600           1 :     ObjectBox* objbox1 = parser.newObjectBox(&value.toObject());
    6601           1 :     if (!objbox1)
    6602           0 :         return false;
    6603             : 
    6604           1 :     if (!pn->as<CallSiteNode>().getRawArrayValue(cx, &value))
    6605           0 :         return false;
    6606             : 
    6607           1 :     MOZ_ASSERT(value.isObject());
    6608             : 
    6609           1 :     ObjectBox* objbox2 = parser.newObjectBox(&value.toObject());
    6610           1 :     if (!objbox2)
    6611           0 :         return false;
    6612             : 
    6613           1 :     return emitObjectPairOp(objbox1, objbox2, JSOP_CALLSITEOBJ);
    6614             : }
    6615             : 
    6616             : /* See the SRC_FOR source note offsetBias comments later in this file. */
    6617             : JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
    6618             : JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
    6619             : 
    6620             : namespace {
    6621             : 
    6622             : class EmitLevelManager
    6623             : {
    6624             :     BytecodeEmitter* bce;
    6625             :   public:
    6626      227349 :     explicit EmitLevelManager(BytecodeEmitter* bce) : bce(bce) { bce->emitLevel++; }
    6627      227361 :     ~EmitLevelManager() { bce->emitLevel--; }
    6628             : };
    6629             : 
    6630             : } /* anonymous namespace */
    6631             : 
    6632             : bool
    6633         467 : BytecodeEmitter::emitCatch(ParseNode* pn)
    6634             : {
    6635             :     // We must be nested under a try-finally statement.
    6636         467 :     TryFinallyControl& controlInfo = innermostNestableControl->as<TryFinallyControl>();
    6637             : 
    6638             :     /* Pick up the pending exception and bind it to the catch variable. */
    6639         467 :     if (!emit1(JSOP_EXCEPTION))
    6640           0 :         return false;
    6641             : 
    6642             :     /*
    6643             :      * Dup the exception object if there is a guard for rethrowing to use
    6644             :      * it later when rethrowing or in other catches.
    6645             :      */
    6646         467 :     if (pn->pn_kid2 && !emit1(JSOP_DUP))
    6647           0 :         return false;
    6648             : 
    6649         467 :     ParseNode* pn2 = pn->pn_kid1;
    6650         467 :     switch (pn2->getKind()) {
    6651             :       case PNK_ARRAY:
    6652             :       case PNK_OBJECT:
    6653           0 :         if (!emitDestructuringOps(pn2, DestructuringDeclaration))
    6654           0 :             return false;
    6655           0 :         if (!emit1(JSOP_POP))
    6656           0 :             return false;
    6657           0 :         break;
    6658             : 
    6659             :       case PNK_NAME:
    6660         467 :         if (!emitLexicalInitialization(pn2))
    6661           0 :             return false;
    6662         467 :         if (!emit1(JSOP_POP))
    6663           0 :             return false;
    6664         467 :         break;
    6665             : 
    6666             :       default:
    6667           0 :         MOZ_ASSERT(0);
    6668             :     }
    6669             : 
    6670             :     // If there is a guard expression, emit it and arrange to jump to the next
    6671             :     // catch block if the guard expression is false.
    6672         467 :     if (pn->pn_kid2) {
    6673           0 :         if (!emitTree(pn->pn_kid2))
    6674           0 :             return false;
    6675             : 
    6676             :         // If the guard expression is false, fall through, pop the block scope,
    6677             :         // and jump to the next catch block.  Otherwise jump over that code and
    6678             :         // pop the dupped exception.
    6679           0 :         JumpList guardCheck;
    6680           0 :         if (!emitJump(JSOP_IFNE, &guardCheck))
    6681           0 :             return false;
    6682             : 
    6683             :         {
    6684           0 :             NonLocalExitControl nle(this, NonLocalExitControl::Throw);
    6685             : 
    6686             :             // Move exception back to cx->exception to prepare for
    6687             :             // the next catch.
    6688           0 :             if (!emit1(JSOP_THROWING))
    6689           0 :                 return false;
    6690             : 
    6691             :             // Leave the scope for this catch block.
    6692           0 :             if (!nle.prepareForNonLocalJump(&controlInfo))
    6693           0 :                 return false;
    6694             : 
    6695             :             // Jump to the next handler added by emitTry.
    6696           0 :             if (!emitJump(JSOP_GOTO, &controlInfo.guardJump))
    6697           0 :                 return false;
    6698             :         }
    6699             : 
    6700             :         // Back to normal control flow.
    6701           0 :         if (!emitJumpTargetAndPatch(guardCheck))
    6702           0 :             return false;
    6703             : 
    6704             :         // Pop duplicated exception object as we no longer need it.
    6705           0 :         if (!emit1(JSOP_POP))
    6706           0 :             return false;
    6707             :     }
    6708             : 
    6709             :     /* Emit the catch body. */
    6710         467 :     return emitTree(pn->pn_kid3);
    6711             : }
    6712             : 
    6713             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
    6714             : // comment on EmitSwitch.
    6715             : MOZ_NEVER_INLINE bool
    6716         489 : BytecodeEmitter::emitTry(ParseNode* pn)
    6717             : {
    6718         489 :     ParseNode* catchList = pn->pn_kid2;
    6719         489 :     ParseNode* finallyNode = pn->pn_kid3;
    6720             : 
    6721             :     TryEmitter::Kind kind;
    6722         489 :     if (catchList) {
    6723         467 :         if (finallyNode)
    6724          19 :             kind = TryEmitter::TryCatchFinally;
    6725             :         else
    6726         448 :             kind = TryEmitter::TryCatch;
    6727             :     } else {
    6728          22 :         MOZ_ASSERT(finallyNode);
    6729          22 :         kind = TryEmitter::TryFinally;
    6730             :     }
    6731         978 :     TryEmitter tryCatch(this, kind);
    6732             : 
    6733         489 :     if (!tryCatch.emitTry())
    6734           0 :         return false;
    6735             : 
    6736         489 :     if (!emitTree(pn->pn_kid1))
    6737           0 :         return false;
    6738             : 
    6739             :     // If this try has a catch block, emit it.
    6740         489 :     if (catchList) {
    6741         467 :         MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
    6742             : 
    6743             :         // The emitted code for a catch block looks like:
    6744             :         //
    6745             :         // [pushlexicalenv]             only if any local aliased
    6746             :         // exception
    6747             :         // if there is a catchguard:
    6748             :         //   dup
    6749             :         // setlocal 0; pop              assign or possibly destructure exception
    6750             :         // if there is a catchguard:
    6751             :         //   < catchguard code >
    6752             :         //   ifne POST
    6753             :         //   debugleaveblock
    6754             :         //   [poplexicalenv]            only if any local aliased
    6755             :         //   throwing                   pop exception to cx->exception
    6756             :         //   goto <next catch block>
    6757             :         //   POST: pop
    6758             :         // < catch block contents >
    6759             :         // debugleaveblock
    6760             :         // [poplexicalenv]              only if any local aliased
    6761             :         // goto <end of catch blocks>   non-local; finally applies
    6762             :         //
    6763             :         // If there's no catch block without a catchguard, the last <next catch
    6764             :         // block> points to rethrow code.  This code will [gosub] to the finally
    6765             :         // code if appropriate, and is also used for the catch-all trynote for
    6766             :         // capturing exceptions thrown from catch{} blocks.
    6767             :         //
    6768         934 :         for (ParseNode* pn3 = catchList->pn_head; pn3; pn3 = pn3->pn_next) {
    6769         467 :             if (!tryCatch.emitCatch())
    6770           0 :                 return false;
    6771             : 
    6772             :             // Emit the lexical scope and catch body.
    6773         467 :             MOZ_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
    6774         467 :             if (!emitTree(pn3))
    6775           0 :                 return false;
    6776             :         }
    6777             :     }
    6778             : 
    6779             :     // Emit the finally handler, if there is one.
    6780         489 :     if (finallyNode) {
    6781          41 :         if (!tryCatch.emitFinally(Some(finallyNode->pn_pos.begin)))
    6782           0 :             return false;
    6783             : 
    6784          41 :         if (!emitTree(finallyNode))
    6785           0 :             return false;
    6786             :     }
    6787             : 
    6788         489 :     if (!tryCatch.emitEnd())
    6789           0 :         return false;
    6790             : 
    6791         489 :     return true;
    6792             : }
    6793             : 
    6794             : bool
    6795        6761 : BytecodeEmitter::emitIf(ParseNode* pn)
    6796             : {
    6797       13523 :     IfThenElseEmitter ifThenElse(this);
    6798             : 
    6799             :   if_again:
    6800             :     /* Emit code for the condition before pushing stmtInfo. */
    6801        7037 :     if (!emitTreeInBranch(pn->pn_kid1))
    6802           0 :         return false;
    6803             : 
    6804        7038 :     ParseNode* elseNode = pn->pn_kid3;
    6805        7038 :     if (elseNode) {
    6806         925 :         if (!ifThenElse.emitIfElse())
    6807           0 :             return false;
    6808             :     } else {
    6809        6113 :         if (!ifThenElse.emitIf())
    6810           0 :             return false;
    6811             :     }
    6812             : 
    6813             :     /* Emit code for the then part. */
    6814        7038 :     if (!emitTreeInBranch(pn->pn_kid2))
    6815           0 :         return false;
    6816             : 
    6817        7038 :     if (elseNode) {
    6818         925 :         if (!ifThenElse.emitElse())
    6819           0 :             return false;
    6820             : 
    6821         925 :         if (elseNode->isKind(PNK_IF)) {
    6822         276 :             pn = elseNode;
    6823         276 :             goto if_again;
    6824             :         }
    6825             : 
    6826             :         /* Emit code for the else part. */
    6827         649 :         if (!emitTreeInBranch(elseNode))
    6828           0 :             return false;
    6829             :     }
    6830             : 
    6831        6762 :     if (!ifThenElse.emitEnd())
    6832           0 :         return false;
    6833             : 
    6834        6762 :     return true;
    6835             : }
    6836             : 
    6837             : bool
    6838          43 : BytecodeEmitter::emitHoistedFunctionsInList(ParseNode* list)
    6839             : {
    6840          43 :     MOZ_ASSERT(list->pn_xflags & PNX_FUNCDEFS);
    6841             : 
    6842         526 :     for (ParseNode* pn = list->pn_head; pn; pn = pn->pn_next) {
    6843         483 :         ParseNode* maybeFun = pn;
    6844             : 
    6845         483 :         if (!sc->strict()) {
    6846         148 :             while (maybeFun->isKind(PNK_LABEL))
    6847           0 :                 maybeFun = maybeFun->as<LabeledStatement>().statement();
    6848             :         }
    6849             : 
    6850         483 :         if (maybeFun->isKind(PNK_FUNCTION) && maybeFun->functionIsHoisted()) {
    6851          68 :             if (!emitTree(maybeFun))
    6852           0 :                 return false;
    6853             :         }
    6854             :     }
    6855             : 
    6856          43 :     return true;
    6857             : }
    6858             : 
    6859             : bool
    6860       12188 : BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote)
    6861             : {
    6862       12188 :     if (body->isKind(PNK_STATEMENTLIST) && body->pn_xflags & PNX_FUNCDEFS) {
    6863             :         // This block contains function statements whose definitions are
    6864             :         // hoisted to the top of the block. Emit these as a separate pass
    6865             :         // before the rest of the block.
    6866          43 :         if (!emitHoistedFunctionsInList(body))
    6867           0 :             return false;
    6868             :     }
    6869             : 
    6870             :     // Line notes were updated by emitLexicalScope.
    6871       12188 :     return emitTree(body, ValueUsage::WantValue, emitLineNote);
    6872             : }
    6873             : 
    6874             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    6875             : // the comment on emitSwitch.
    6876             : MOZ_NEVER_INLINE bool
    6877       12679 : BytecodeEmitter::emitLexicalScope(ParseNode* pn)
    6878             : {
    6879       12679 :     MOZ_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
    6880             : 
    6881       25359 :     TDZCheckCache tdzCache(this);
    6882             : 
    6883       12679 :     ParseNode* body = pn->scopeBody();
    6884       12679 :     if (pn->isEmptyScope())
    6885        9774 :         return emitLexicalScopeBody(body);
    6886             : 
    6887             :     // Update line number notes before emitting TDZ poison in
    6888             :     // EmitterScope::enterLexical to avoid spurious pausing on seemingly
    6889             :     // non-effectful lines in Debugger.
    6890             :     //
    6891             :     // For example, consider the following code.
    6892             :     //
    6893             :     // L1: {
    6894             :     // L2:   let x = 42;
    6895             :     // L3: }
    6896             :     //
    6897             :     // If line number notes were not updated before the TDZ poison, the TDZ
    6898             :     // poison bytecode sequence of 'uninitialized; initlexical' will have line
    6899             :     // number L1, and the Debugger will pause there.
    6900        2905 :     if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
    6901        2414 :         ParseNode* pnForPos = body;
    6902        2414 :         if (body->isKind(PNK_STATEMENTLIST) && body->pn_head)
    6903        1947 :             pnForPos = body->pn_head;
    6904        2414 :         if (!updateLineNumberNotes(pnForPos->pn_pos.begin))
    6905           0 :             return false;
    6906             :     }
    6907             : 
    6908        5811 :     EmitterScope emitterScope(this);
    6909             :     ScopeKind kind;
    6910        2905 :     if (body->isKind(PNK_CATCH))
    6911         467 :         kind = body->pn_kid1->isKind(PNK_NAME) ? ScopeKind::SimpleCatch : ScopeKind::Catch;
    6912             :     else
    6913        2438 :         kind = ScopeKind::Lexical;
    6914             : 
    6915        2905 :     if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
    6916           0 :         return false;
    6917             : 
    6918        2905 :     if (body->isKind(PNK_FOR)) {
    6919             :         // for loops need to emit {FRESHEN,RECREATE}LEXICALENV if there are
    6920             :         // lexical declarations in the head. Signal this by passing a
    6921             :         // non-nullptr lexical scope.
    6922         491 :         if (!emitFor(body, &emitterScope))
    6923           0 :             return false;
    6924             :     } else {
    6925        2414 :         if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE))
    6926           0 :             return false;
    6927             :     }
    6928             : 
    6929        2906 :     return emitterScope.leave(this);
    6930             : }
    6931             : 
    6932             : bool
    6933           0 : BytecodeEmitter::emitWith(ParseNode* pn)
    6934             : {
    6935           0 :     if (!emitTree(pn->pn_left))
    6936           0 :         return false;
    6937             : 
    6938           0 :     EmitterScope emitterScope(this);
    6939           0 :     if (!emitterScope.enterWith(this))
    6940           0 :         return false;
    6941             : 
    6942           0 :     if (!emitTree(pn->pn_right))
    6943           0 :         return false;
    6944             : 
    6945           0 :     return emitterScope.leave(this);
    6946             : }
    6947             : 
    6948             : bool
    6949           0 : BytecodeEmitter::emitCopyDataProperties(CopyOption option)
    6950             : {
    6951           0 :     DebugOnly<int32_t> depth = this->stackDepth;
    6952             : 
    6953             :     uint32_t argc;
    6954           0 :     if (option == CopyOption::Filtered) {
    6955           0 :         MOZ_ASSERT(depth > 2);                 // TARGET SOURCE SET
    6956           0 :         argc = 3;
    6957             : 
    6958           0 :         if (!emitAtomOp(cx->names().CopyDataProperties,
    6959           0 :                         JSOP_GETINTRINSIC))    // TARGET SOURCE SET COPYDATAPROPERTIES
    6960             :         {
    6961           0 :             return false;
    6962             :         }
    6963             :     } else {
    6964           0 :         MOZ_ASSERT(depth > 1);                 // TARGET SOURCE
    6965           0 :         argc = 2;
    6966             : 
    6967           0 :         if (!emitAtomOp(cx->names().CopyDataPropertiesUnfiltered,
    6968           0 :                         JSOP_GETINTRINSIC))    // TARGET SOURCE COPYDATAPROPERTIES
    6969             :         {
    6970           0 :             return false;
    6971             :         }
    6972             :     }
    6973             : 
    6974           0 :     if (!emit1(JSOP_UNDEFINED))                // TARGET SOURCE *SET COPYDATAPROPERTIES UNDEFINED
    6975           0 :         return false;
    6976           0 :     if (!emit2(JSOP_PICK, argc + 1))           // SOURCE *SET COPYDATAPROPERTIES UNDEFINED TARGET
    6977           0 :         return false;
    6978           0 :     if (!emit2(JSOP_PICK, argc + 1))           // *SET COPYDATAPROPERTIES UNDEFINED TARGET SOURCE
    6979           0 :         return false;
    6980           0 :     if (option == CopyOption::Filtered) {
    6981           0 :         if (!emit2(JSOP_PICK, argc + 1))       // COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
    6982           0 :             return false;
    6983             :     }
    6984           0 :     if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
    6985           0 :         return false;
    6986           0 :     checkTypeSet(JSOP_CALL_IGNORES_RV);
    6987             : 
    6988           0 :     if (!emit1(JSOP_POP))                      // -
    6989           0 :         return false;
    6990             : 
    6991           0 :     MOZ_ASSERT(depth - int(argc) == this->stackDepth);
    6992           0 :     return true;
    6993             : }
    6994             : 
    6995             : bool
    6996         472 : BytecodeEmitter::emitIterator()
    6997             : {
    6998             :     // Convert iterable to iterator.
    6999         472 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7000           0 :         return false;
    7001         472 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator)))   // OBJ OBJ @@ITERATOR
    7002           0 :         return false;
    7003         472 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7004           0 :         return false;
    7005         472 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7006           0 :         return false;
    7007         472 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7008           0 :         return false;
    7009         472 :     checkTypeSet(JSOP_CALLITER);
    7010         472 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7011           0 :         return false;
    7012         472 :     return true;
    7013             : }
    7014             : 
    7015             : bool
    7016           0 : BytecodeEmitter::emitAsyncIterator()
    7017             : {
    7018             :     // Convert iterable to iterator.
    7019           0 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7020           0 :         return false;
    7021           0 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::asyncIterator))) // OBJ OBJ @@ASYNCITERATOR
    7022           0 :         return false;
    7023           0 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7024           0 :         return false;
    7025             : 
    7026           0 :     IfThenElseEmitter ifAsyncIterIsUndefined(this);
    7027           0 :     if (!emit1(JSOP_DUP))                                         // OBJ ITERFN ITERFN
    7028           0 :         return false;
    7029           0 :     if (!emit1(JSOP_UNDEFINED))                                   // OBJ ITERFN ITERFN UNDEF
    7030           0 :         return false;
    7031           0 :     if (!emit1(JSOP_EQ))                                          // OBJ ITERFN EQ
    7032           0 :         return false;
    7033           0 :     if (!ifAsyncIterIsUndefined.emitIfElse())                     // OBJ ITERFN
    7034           0 :         return false;
    7035             : 
    7036           0 :     if (!emit1(JSOP_POP))                                         // OBJ
    7037           0 :         return false;
    7038           0 :     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
    7039           0 :         return false;
    7040           0 :     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator)))   // OBJ OBJ @@ITERATOR
    7041           0 :         return false;
    7042           0 :     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
    7043           0 :         return false;
    7044           0 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7045           0 :         return false;
    7046           0 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7047           0 :         return false;
    7048           0 :     checkTypeSet(JSOP_CALLITER);
    7049           0 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7050           0 :         return false;
    7051             : 
    7052           0 :     if (!emit1(JSOP_TOASYNCITER))                                 // ITER
    7053           0 :         return false;
    7054             : 
    7055           0 :     if (!ifAsyncIterIsUndefined.emitElse())                       // OBJ ITERFN
    7056           0 :         return false;
    7057             : 
    7058           0 :     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
    7059           0 :         return false;
    7060           0 :     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
    7061           0 :         return false;
    7062           0 :     checkTypeSet(JSOP_CALLITER);
    7063           0 :     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
    7064           0 :         return false;
    7065             : 
    7066           0 :     if (!ifAsyncIterIsUndefined.emitEnd())                        // ITER
    7067           0 :         return false;
    7068             : 
    7069           0 :     return true;
    7070             : }
    7071             : 
    7072             : bool
    7073          58 : BytecodeEmitter::emitSpread(bool allowSelfHosted)
    7074             : {
    7075         116 :     LoopControl loopInfo(this, StatementKind::Spread);
    7076             : 
    7077             :     // Jump down to the loop condition to minimize overhead assuming at least
    7078             :     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
    7079             :     // find the loop-closing jump.
    7080             :     unsigned noteIndex;
    7081          58 :     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
    7082           0 :         return false;
    7083             : 
    7084             :     // Jump down to the loop condition to minimize overhead, assuming at least
    7085             :     // one iteration.  (This is also what we do for loops; whether this
    7086             :     // assumption holds for spreads is an unanswered question.)
    7087          58 :     JumpList initialJump;
    7088          58 :     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ARR I (during the goto)
    7089           0 :         return false;
    7090             : 
    7091          58 :     JumpTarget top{ -1 };
    7092          58 :     if (!emitLoopHead(nullptr, &top))                     // ITER ARR I
    7093           0 :         return false;
    7094             : 
    7095             :     // When we enter the goto above, we have ITER ARR I on the stack.  But when
    7096             :     // we reach this point on the loop backedge (if spreading produces at least
    7097             :     // one value), we've additionally pushed a RESULT iteration value.
    7098             :     // Increment manually to reflect this.
    7099          58 :     this->stackDepth++;
    7100             : 
    7101          58 :     JumpList beq;
    7102          58 :     JumpTarget breakTarget{ -1 };
    7103             :     {
    7104             : #ifdef DEBUG
    7105          58 :         auto loopDepth = this->stackDepth;
    7106             : #endif
    7107             : 
    7108             :         // Emit code to assign result.value to the iteration variable.
    7109          58 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER ARR I VALUE
    7110           0 :             return false;
    7111          58 :         if (!emit1(JSOP_INITELEM_INC))                    // ITER ARR (I+1)
    7112           0 :             return false;
    7113             : 
    7114          58 :         MOZ_ASSERT(this->stackDepth == loopDepth - 1);
    7115             : 
    7116             :         // Spread operations can't contain |continue|, so don't bother setting loop
    7117             :         // and enclosing "update" offsets, as we do with for-loops.
    7118             : 
    7119             :         // COME FROM the beginning of the loop to here.
    7120          58 :         if (!emitLoopEntry(nullptr, initialJump))         // ITER ARR I
    7121           0 :             return false;
    7122             : 
    7123          58 :         if (!emitDupAt(2))                                // ITER ARR I ITER
    7124           0 :             return false;
    7125          58 :         if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted))  // ITER ARR I RESULT
    7126           0 :             return false;
    7127          58 :         if (!emit1(JSOP_DUP))                             // ITER ARR I RESULT RESULT
    7128           0 :             return false;
    7129          58 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // ITER ARR I RESULT DONE
    7130           0 :             return false;
    7131             : 
    7132          58 :         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget)) // ITER ARR I RESULT
    7133           0 :             return false;
    7134             : 
    7135          58 :         MOZ_ASSERT(this->stackDepth == loopDepth);
    7136             :     }
    7137             : 
    7138             :     // Let Ion know where the closing jump of this loop is.
    7139          58 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7140           0 :         return false;
    7141             : 
    7142             :     // No breaks or continues should occur in spreads.
    7143          58 :     MOZ_ASSERT(loopInfo.breaks.offset == -1);
    7144          58 :     MOZ_ASSERT(loopInfo.continues.offset == -1);
    7145             : 
    7146          58 :     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
    7147           0 :         return false;
    7148             : 
    7149          58 :     if (!emit2(JSOP_PICK, 3))                             // ARR FINAL_INDEX RESULT ITER
    7150           0 :         return false;
    7151             : 
    7152          58 :     return emitPopN(2);                                   // ARR FINAL_INDEX
    7153             : }
    7154             : 
    7155             : bool
    7156         372 : BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
    7157             : {
    7158         372 :     MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
    7159         372 :     MOZ_ASSERT(forHead->isArity(PN_TERNARY));
    7160             : 
    7161         372 :     MOZ_ASSERT(this->stackDepth >= 1,
    7162             :                "must have a per-iteration value for initializing");
    7163             : 
    7164         372 :     ParseNode* target = forHead->pn_kid1;
    7165         372 :     MOZ_ASSERT(!forHead->pn_kid2);
    7166             : 
    7167             :     // If the for-in/of loop didn't have a variable declaration, per-loop
    7168             :     // initialization is just assigning the iteration value to a target
    7169             :     // expression.
    7170         372 :     if (!parser.isDeclarationList(target))
    7171           0 :         return emitAssignment(target, JSOP_NOP, nullptr); // ... ITERVAL
    7172             : 
    7173             :     // Otherwise, per-loop initialization is (possibly) declaration
    7174             :     // initialization.  If the declaration is a lexical declaration, it must be
    7175             :     // initialized.  If the declaration is a variable declaration, an
    7176             :     // assignment to that name (which does *not* necessarily assign to the
    7177             :     // variable!) must be generated.
    7178             : 
    7179         372 :     if (!updateSourceCoordNotes(target->pn_pos.begin))
    7180           0 :         return false;
    7181             : 
    7182         372 :     MOZ_ASSERT(target->isForLoopDeclaration());
    7183         372 :     target = parser.singleBindingFromDeclaration(target);
    7184             : 
    7185         372 :     if (target->isKind(PNK_NAME)) {
    7186             :         auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
    7187         320 :                                       bool emittedBindOp)
    7188             :         {
    7189         320 :             if (emittedBindOp) {
    7190             :                 // Per-iteration initialization in for-in/of loops computes the
    7191             :                 // iteration value *before* initializing.  Thus the
    7192             :                 // initializing value may be buried under a bind-specific value
    7193             :                 // on the stack.  Swap it to the top of the stack.
    7194           0 :                 MOZ_ASSERT(bce->stackDepth >= 2);
    7195           0 :                 return bce->emit1(JSOP_SWAP);
    7196             :             }
    7197             : 
    7198             :             // In cases of emitting a frame slot or environment slot,
    7199             :             // nothing needs be done.
    7200         320 :             MOZ_ASSERT(bce->stackDepth >= 1);
    7201         320 :             return true;
    7202             :         };
    7203             : 
    7204             :         // The caller handles removing the iteration value from the stack.
    7205         320 :         return emitInitializeName(target, emitSwapScopeAndRhs);
    7206             :     }
    7207             : 
    7208          52 :     MOZ_ASSERT(!target->isKind(PNK_ASSIGN),
    7209             :                "for-in/of loop destructuring declarations can't have initializers");
    7210             : 
    7211          52 :     MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
    7212          52 :     return emitDestructuringOps(target, DestructuringDeclaration);
    7213             : }
    7214             : 
    7215             : bool
    7216         336 : BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope)
    7217             : {
    7218         336 :     MOZ_ASSERT(forOfLoop->isKind(PNK_FOR));
    7219         336 :     MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
    7220             : 
    7221         336 :     ParseNode* forOfHead = forOfLoop->pn_left;
    7222         336 :     MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
    7223         336 :     MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
    7224             : 
    7225         336 :     unsigned iflags = forOfLoop->pn_iflags;
    7226         336 :     IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
    7227         336 :                             ? IteratorKind::Async
    7228         336 :                             : IteratorKind::Sync;
    7229         336 :     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
    7230         336 :     MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
    7231             : 
    7232         336 :     ParseNode* forHeadExpr = forOfHead->pn_kid3;
    7233             : 
    7234             :     // Certain builtins (e.g. Array.from) are implemented in self-hosting
    7235             :     // as for-of loops.
    7236         336 :     bool allowSelfHostedIter = false;
    7237         687 :     if (emitterMode == BytecodeEmitter::SelfHosting &&
    7238         351 :         forHeadExpr->isKind(PNK_CALL) &&
    7239          15 :         forHeadExpr->pn_head->name() == cx->names().allowContentIter)
    7240             :     {
    7241          15 :         allowSelfHostedIter = true;
    7242             :     }
    7243             : 
    7244             :     // Evaluate the expression being iterated. The forHeadExpr should use a
    7245             :     // distinct TDZCheckCache to evaluate since (abstractly) it runs in its own
    7246             :     // LexicalEnvironment.
    7247         336 :     if (!emitTreeInBranch(forHeadExpr))                   // ITERABLE
    7248           0 :         return false;
    7249         336 :     if (iterKind == IteratorKind::Async) {
    7250           0 :         if (!emitAsyncIterator())                         // ITER
    7251           0 :             return false;
    7252             :     } else {
    7253         336 :         if (!emitIterator())                              // ITER
    7254           0 :             return false;
    7255             :     }
    7256             : 
    7257         336 :     int32_t iterDepth = stackDepth;
    7258             : 
    7259             :     // For-of loops have both the iterator and the result.value on the stack.
    7260             :     // Push an undefined to balance the stack.
    7261         336 :     if (!emit1(JSOP_UNDEFINED))                           // ITER UNDEF
    7262           0 :         return false;
    7263             : 
    7264         672 :     ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
    7265             : 
    7266             :     // Annotate so IonMonkey can find the loop-closing jump.
    7267             :     unsigned noteIndex;
    7268         336 :     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
    7269           0 :         return false;
    7270             : 
    7271         336 :     JumpList initialJump;
    7272         336 :     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER UNDEF
    7273           0 :         return false;
    7274             : 
    7275         336 :     JumpTarget top{ -1 };
    7276         336 :     if (!emitLoopHead(nullptr, &top))                     // ITER UNDEF
    7277           0 :         return false;
    7278             : 
    7279             :     // If the loop had an escaping lexical declaration, replace the current
    7280             :     // environment with an dead zoned one to implement TDZ semantics.
    7281         336 :     if (headLexicalEmitterScope) {
    7282             :         // The environment chain only includes an environment for the for-of
    7283             :         // loop head *if* a scope binding is captured, thereby requiring
    7284             :         // recreation each iteration. If a lexical scope exists for the head,
    7285             :         // it must be the innermost one. If that scope has closed-over
    7286             :         // bindings inducing an environment, recreate the current environment.
    7287         640 :         DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
    7288         320 :         MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
    7289         320 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
    7290         320 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7291             : 
    7292         320 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7293          50 :             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER UNDEF
    7294           0 :                 return false;
    7295             :         }
    7296             : 
    7297             :         // For uncaptured bindings, put them back in TDZ.
    7298         320 :         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
    7299           0 :             return false;
    7300             :     }
    7301             : 
    7302         336 :     JumpList beq;
    7303         336 :     JumpTarget breakTarget{ -1 };
    7304             :     {
    7305             : #ifdef DEBUG
    7306         336 :         auto loopDepth = this->stackDepth;
    7307             : #endif
    7308             : 
    7309             :         // Make sure this code is attributed to the "for".
    7310         336 :         if (!updateSourceCoordNotes(forOfHead->pn_pos.begin))
    7311           0 :             return false;
    7312             : 
    7313         336 :         if (!emit1(JSOP_POP))                             // ITER
    7314           0 :             return false;
    7315         336 :         if (!emit1(JSOP_DUP))                             // ITER ITER
    7316           0 :             return false;
    7317             : 
    7318         336 :         if (!emitIteratorNext(forOfHead, iterKind, allowSelfHostedIter))
    7319           0 :             return false;                                 // ITER RESULT
    7320             : 
    7321         336 :         if (!emit1(JSOP_DUP))                             // ITER RESULT RESULT
    7322           0 :             return false;
    7323         336 :         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // ITER RESULT DONE
    7324           0 :             return false;
    7325             : 
    7326         672 :         IfThenElseEmitter ifDone(this);
    7327             : 
    7328         336 :         if (!ifDone.emitIf())                             // ITER RESULT
    7329           0 :             return false;
    7330             : 
    7331             :         // Remove RESULT from the stack to release it.
    7332         336 :         if (!emit1(JSOP_POP))                             // ITER
    7333           0 :             return false;
    7334         336 :         if (!emit1(JSOP_UNDEFINED))                       // ITER UNDEF
    7335           0 :             return false;
    7336             : 
    7337             :         // If the iteration is done, leave loop here, instead of the branch at
    7338             :         // the end of the loop.
    7339         336 :         if (!loopInfo.emitSpecialBreakForDone(this))      // ITER UNDEF
    7340           0 :             return false;
    7341             : 
    7342         336 :         if (!ifDone.emitEnd())                            // ITER RESULT
    7343           0 :             return false;
    7344             : 
    7345             :         // Emit code to assign result.value to the iteration variable.
    7346             :         //
    7347             :         // Note that ES 13.7.5.13, step 5.c says getting result.value does not
    7348             :         // call IteratorClose, so start JSTRY_ITERCLOSE after the GETPROP.
    7349         336 :         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER VALUE
    7350           0 :             return false;
    7351             : 
    7352         336 :         if (!loopInfo.emitBeginCodeNeedingIteratorClose(this))
    7353           0 :             return false;
    7354             : 
    7355         336 :         if (!emitInitializeForInOrOfTarget(forOfHead))    // ITER VALUE
    7356           0 :             return false;
    7357             : 
    7358         336 :         MOZ_ASSERT(stackDepth == loopDepth,
    7359             :                    "the stack must be balanced around the initializing "
    7360             :                    "operation");
    7361             : 
    7362             :         // Remove VALUE from the stack to release it.
    7363         336 :         if (!emit1(JSOP_POP))                             // ITER
    7364           0 :             return false;
    7365         336 :         if (!emit1(JSOP_UNDEFINED))                       // ITER UNDEF
    7366           0 :             return false;
    7367             : 
    7368             :         // Perform the loop body.
    7369         336 :         ParseNode* forBody = forOfLoop->pn_right;
    7370         336 :         if (!emitTree(forBody))                           // ITER UNDEF
    7371           0 :             return false;
    7372             : 
    7373         336 :         MOZ_ASSERT(stackDepth == loopDepth,
    7374             :                    "the stack must be balanced around the for-of body");
    7375             : 
    7376         336 :         if (!loopInfo.emitEndCodeNeedingIteratorClose(this))
    7377           0 :             return false;
    7378             : 
    7379             :         // Set offset for continues.
    7380         336 :         loopInfo.continueTarget = { offset() };
    7381             : 
    7382         336 :         if (!emitLoopEntry(forHeadExpr, initialJump))     // ITER UNDEF
    7383           0 :             return false;
    7384             : 
    7385         336 :         if (!emit1(JSOP_FALSE))                           // ITER UNDEF FALSE
    7386           0 :             return false;
    7387         336 :         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    7388           0 :             return false;                                 // ITER UNDEF
    7389             : 
    7390         336 :         MOZ_ASSERT(this->stackDepth == loopDepth);
    7391             :     }
    7392             : 
    7393             :     // Let Ion know where the closing jump of this loop is.
    7394         336 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7395           0 :         return false;
    7396             : 
    7397         336 :     if (!loopInfo.patchBreaksAndContinues(this))
    7398           0 :         return false;
    7399             : 
    7400         336 :     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
    7401           0 :         return false;
    7402             : 
    7403         336 :     return emitPopN(2);                                   //
    7404             : }
    7405             : 
    7406             : bool
    7407          36 : BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
    7408             : {
    7409          36 :     MOZ_ASSERT(forInLoop->isKind(PNK_FOR));
    7410          36 :     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
    7411          36 :     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
    7412             : 
    7413          36 :     ParseNode* forInHead = forInLoop->pn_left;
    7414          36 :     MOZ_ASSERT(forInHead->isKind(PNK_FORIN));
    7415          36 :     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
    7416             : 
    7417             :     // Annex B: Evaluate the var-initializer expression if present.
    7418             :     // |for (var i = initializer in expr) { ... }|
    7419          36 :     ParseNode* forInTarget = forInHead->pn_kid1;
    7420          36 :     if (parser.isDeclarationList(forInTarget)) {
    7421          36 :         ParseNode* decl = parser.singleBindingFromDeclaration(forInTarget);
    7422          36 :         if (decl->isKind(PNK_NAME)) {
    7423          36 :             if (ParseNode* initializer = decl->expr()) {
    7424           0 :                 MOZ_ASSERT(forInTarget->isKind(PNK_VAR),
    7425             :                            "for-in initializers are only permitted for |var| declarations");
    7426             : 
    7427           0 :                 if (!updateSourceCoordNotes(decl->pn_pos.begin))
    7428           0 :                     return false;
    7429             : 
    7430           0 :                 auto emitRhs = [decl, initializer](BytecodeEmitter* bce, const NameLocation&, bool) {
    7431             :                     return bce->emitInitializer(initializer, decl);
    7432           0 :                 };
    7433             : 
    7434           0 :                 if (!emitInitializeName(decl, emitRhs))
    7435           0 :                     return false;
    7436             : 
    7437             :                 // Pop the initializer.
    7438           0 :                 if (!emit1(JSOP_POP))
    7439           0 :                     return false;
    7440             :             }
    7441             :         }
    7442             :     }
    7443             : 
    7444             :     // Evaluate the expression being iterated.
    7445          36 :     ParseNode* expr = forInHead->pn_kid3;
    7446          36 :     if (!emitTreeInBranch(expr))                          // EXPR
    7447           0 :         return false;
    7448             : 
    7449             :     // Convert the value to the appropriate sort of iterator object for the
    7450             :     // loop variant (for-in, for-each-in, or destructuring for-in).
    7451          36 :     unsigned iflags = forInLoop->pn_iflags;
    7452          36 :     MOZ_ASSERT(0 == (iflags & ~(JSITER_FOREACH | JSITER_ENUMERATE)));
    7453          36 :     if (!emit2(JSOP_ITER, AssertedCast<uint8_t>(iflags))) // ITER
    7454           0 :         return false;
    7455             : 
    7456             :     // For-in loops have both the iterator and the value on the stack. Push
    7457             :     // undefined to balance the stack.
    7458          36 :     if (!emit1(JSOP_UNDEFINED))                           // ITER ITERVAL
    7459           0 :         return false;
    7460             : 
    7461          72 :     LoopControl loopInfo(this, StatementKind::ForInLoop);
    7462             : 
    7463             :     /* Annotate so IonMonkey can find the loop-closing jump. */
    7464             :     unsigned noteIndex;
    7465          36 :     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
    7466           0 :         return false;
    7467             : 
    7468             :     // Jump down to the loop condition to minimize overhead (assuming at least
    7469             :     // one iteration, just like the other loop forms).
    7470          36 :     JumpList initialJump;
    7471          36 :     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ITERVAL
    7472           0 :         return false;
    7473             : 
    7474          36 :     JumpTarget top{ -1 };
    7475          36 :     if (!emitLoopHead(nullptr, &top))                     // ITER ITERVAL
    7476           0 :         return false;
    7477             : 
    7478             :     // If the loop had an escaping lexical declaration, replace the current
    7479             :     // environment with an dead zoned one to implement TDZ semantics.
    7480          36 :     if (headLexicalEmitterScope) {
    7481             :         // The environment chain only includes an environment for the for-in
    7482             :         // loop head *if* a scope binding is captured, thereby requiring
    7483             :         // recreation each iteration. If a lexical scope exists for the head,
    7484             :         // it must be the innermost one. If that scope has closed-over
    7485             :         // bindings inducing an environment, recreate the current environment.
    7486          31 :         MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
    7487          31 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
    7488          31 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7489             : 
    7490          31 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7491           3 :             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER ITERVAL
    7492           0 :                 return false;
    7493             :         }
    7494             : 
    7495             :         // For uncaptured bindings, put them back in TDZ.
    7496          31 :         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
    7497           0 :             return false;
    7498             :     }
    7499             : 
    7500             :     {
    7501             : #ifdef DEBUG
    7502          36 :         auto loopDepth = this->stackDepth;
    7503             : #endif
    7504          36 :         MOZ_ASSERT(loopDepth >= 2);
    7505             : 
    7506          36 :         if (!emitInitializeForInOrOfTarget(forInHead))    // ITER ITERVAL
    7507           0 :             return false;
    7508             : 
    7509          36 :         MOZ_ASSERT(this->stackDepth == loopDepth,
    7510             :                    "iterator and iterval must be left on the stack");
    7511             :     }
    7512             : 
    7513             :     // Perform the loop body.
    7514          36 :     ParseNode* forBody = forInLoop->pn_right;
    7515          36 :     if (!emitTree(forBody))                               // ITER ITERVAL
    7516           0 :         return false;
    7517             : 
    7518             :     // Set offset for continues.
    7519          36 :     loopInfo.continueTarget = { offset() };
    7520             : 
    7521             :     // Make sure this code is attributed to the "for".
    7522          36 :     if (!updateSourceCoordNotes(forInHead->pn_pos.begin))
    7523           0 :         return false;
    7524             : 
    7525          36 :     if (!emitLoopEntry(nullptr, initialJump))             // ITER ITERVAL
    7526           0 :         return false;
    7527          36 :     if (!emit1(JSOP_POP))                                 // ITER
    7528           0 :         return false;
    7529          36 :     if (!emit1(JSOP_MOREITER))                            // ITER NEXTITERVAL?
    7530           0 :         return false;
    7531          36 :     if (!emit1(JSOP_ISNOITER))                            // ITER NEXTITERVAL? ISNOITER
    7532           0 :         return false;
    7533             : 
    7534          36 :     JumpList beq;
    7535          36 :     JumpTarget breakTarget{ -1 };
    7536          36 :     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    7537           0 :         return false;                                     // ITER NEXTITERVAL
    7538             : 
    7539             :     // Set the srcnote offset so we can find the closing jump.
    7540          36 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
    7541           0 :         return false;
    7542             : 
    7543          36 :     if (!loopInfo.patchBreaksAndContinues(this))
    7544           0 :         return false;
    7545             : 
    7546             :     // Pop the enumeration value.
    7547          36 :     if (!emit1(JSOP_POP))                                 // ITER
    7548           0 :         return false;
    7549             : 
    7550          36 :     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, offset()))
    7551           0 :         return false;
    7552             : 
    7553          36 :     return emit1(JSOP_ENDITER);                           //
    7554             : }
    7555             : 
    7556             : /* C-style `for (init; cond; update) ...` loop. */
    7557             : bool
    7558         441 : BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
    7559             : {
    7560         882 :     LoopControl loopInfo(this, StatementKind::ForLoop);
    7561             : 
    7562         441 :     ParseNode* forHead = pn->pn_left;
    7563         441 :     ParseNode* forBody = pn->pn_right;
    7564             : 
    7565             :     // If the head of this for-loop declared any lexical variables, the parser
    7566             :     // wrapped this PNK_FOR node in a PNK_LEXICALSCOPE representing the
    7567             :     // implicit scope of those variables. By the time we get here, we have
    7568             :     // already entered that scope. So far, so good.
    7569             :     //
    7570             :     // ### Scope freshening
    7571             :     //
    7572             :     // Each iteration of a `for (let V...)` loop creates a fresh loop variable
    7573             :     // binding for V, even if the loop is a C-style `for(;;)` loop:
    7574             :     //
    7575             :     //     var funcs = [];
    7576             :     //     for (let i = 0; i < 2; i++)
    7577             :     //         funcs.push(function() { return i; });
    7578             :     //     assertEq(funcs[0](), 0);  // the two closures capture...
    7579             :     //     assertEq(funcs[1](), 1);  // ...two different `i` bindings
    7580             :     //
    7581             :     // This is implemented by "freshening" the implicit block -- changing the
    7582             :     // scope chain to a fresh clone of the instantaneous block object -- each
    7583             :     // iteration, just before evaluating the "update" in for(;;) loops.
    7584             :     //
    7585             :     // No freshening occurs in `for (const ...;;)` as there's no point: you
    7586             :     // can't reassign consts. This is observable through the Debugger API. (The
    7587             :     // ES6 spec also skips cloning the environment in this case.)
    7588         441 :     bool forLoopRequiresFreshening = false;
    7589         441 :     if (ParseNode* init = forHead->pn_kid1) {
    7590             :         // Emit the `init` clause, whether it's an expression or a variable
    7591             :         // declaration. (The loop variables were hoisted into an enclosing
    7592             :         // scope, but we still need to emit code for the initializers.)
    7593         394 :         if (!updateSourceCoordNotes(init->pn_pos.begin))
    7594           0 :             return false;
    7595         394 :         if (init->isForLoopDeclaration()) {
    7596         370 :             if (!emitTree(init))
    7597           0 :                 return false;
    7598             :         } else {
    7599             :             // 'init' is an expression, not a declaration. emitTree left its
    7600             :             // value on the stack.
    7601          24 :             if (!emitTree(init, ValueUsage::IgnoreValue))
    7602           0 :                 return false;
    7603          24 :             if (!emit1(JSOP_POP))
    7604           0 :                 return false;
    7605             :         }
    7606             : 
    7607             :         // ES 13.7.4.8 step 2. The initial freshening.
    7608             :         //
    7609             :         // If an initializer let-declaration may be captured during loop iteration,
    7610             :         // the current scope has an environment.  If so, freshen the current
    7611             :         // environment to expose distinct bindings for each loop iteration.
    7612         394 :         forLoopRequiresFreshening = init->isKind(PNK_LET) && headLexicalEmitterScope;
    7613         394 :         if (forLoopRequiresFreshening) {
    7614             :             // The environment chain only includes an environment for the for(;;)
    7615             :             // loop head's let-declaration *if* a scope binding is captured, thus
    7616             :             // requiring a fresh environment each iteration. If a lexical scope
    7617             :             // exists for the head, it must be the innermost one. If that scope
    7618             :             // has closed-over bindings inducing an environment, recreate the
    7619             :             // current environment.
    7620         140 :             MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
    7621         140 :             MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7622             : 
    7623         140 :             if (headLexicalEmitterScope->hasEnvironment()) {
    7624           0 :                 if (!emit1(JSOP_FRESHENLEXICALENV))
    7625           0 :                     return false;
    7626             :             }
    7627             :         }
    7628             :     }
    7629             : 
    7630             :     /*
    7631             :      * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
    7632             :      * Use tmp to hold the biased srcnote "top" offset, which differs
    7633             :      * from the top local variable by the length of the JSOP_GOTO
    7634             :      * emitted in between tmp and top if this loop has a condition.
    7635             :      */
    7636             :     unsigned noteIndex;
    7637         441 :     if (!newSrcNote(SRC_FOR, &noteIndex))
    7638           0 :         return false;
    7639         441 :     if (!emit1(JSOP_NOP))
    7640           0 :         return false;
    7641         441 :     ptrdiff_t tmp = offset();
    7642             : 
    7643         441 :     JumpList jmp;
    7644         441 :     if (forHead->pn_kid2) {
    7645             :         /* Goto the loop condition, which branches back to iterate. */
    7646         432 :         if (!emitJump(JSOP_GOTO, &jmp))
    7647           0 :             return false;
    7648             :     }
    7649             : 
    7650             :     /* Emit code for the loop body. */
    7651         441 :     JumpTarget top{ -1 };
    7652         441 :     if (!emitLoopHead(forBody, &top))
    7653           0 :         return false;
    7654         441 :     if (jmp.offset == -1 && !emitLoopEntry(forBody, jmp))
    7655           0 :         return false;
    7656             : 
    7657         441 :     if (!emitTreeInBranch(forBody))
    7658           0 :         return false;
    7659             : 
    7660             :     // Set loop and enclosing "update" offsets, for continue.  Note that we
    7661             :     // continue to immediately *before* the block-freshening: continuing must
    7662             :     // refresh the block.
    7663         441 :     if (!emitJumpTarget(&loopInfo.continueTarget))
    7664           0 :         return false;
    7665             : 
    7666             :     // ES 13.7.4.8 step 3.e. The per-iteration freshening.
    7667         441 :     if (forLoopRequiresFreshening) {
    7668         140 :         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
    7669         140 :         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
    7670             : 
    7671         140 :         if (headLexicalEmitterScope->hasEnvironment()) {
    7672           0 :             if (!emit1(JSOP_FRESHENLEXICALENV))
    7673           0 :                 return false;
    7674             :         }
    7675             :     }
    7676             : 
    7677             :     // Check for update code to do before the condition (if any).
    7678             :     // The update code may not be executed at all; it needs its own TDZ cache.
    7679         441 :     if (ParseNode* update = forHead->pn_kid3) {
    7680         864 :         TDZCheckCache tdzCache(this);
    7681             : 
    7682         432 :         if (!updateSourceCoordNotes(update->pn_pos.begin))
    7683           0 :             return false;
    7684         432 :         if (!emitTree(update, ValueUsage::IgnoreValue))
    7685           0 :             return false;
    7686         432 :         if (!emit1(JSOP_POP))
    7687           0 :             return false;
    7688             : 
    7689             :         /* Restore the absolute line number for source note readers. */
    7690         432 :         uint32_t lineNum = parser.tokenStream().srcCoords.lineNum(pn->pn_pos.end);
    7691         432 :         if (currentLine() != lineNum) {
    7692         431 :             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum)))
    7693           0 :                 return false;
    7694         431 :             current->currentLine = lineNum;
    7695         431 :             current->lastColumn = 0;
    7696             :         }
    7697             :     }
    7698             : 
    7699         441 :     ptrdiff_t tmp3 = offset();
    7700             : 
    7701         441 :     if (forHead->pn_kid2) {
    7702             :         /* Fix up the goto from top to target the loop condition. */
    7703         432 :         MOZ_ASSERT(jmp.offset >= 0);
    7704         432 :         if (!emitLoopEntry(forHead->pn_kid2, jmp))
    7705           0 :             return false;
    7706             : 
    7707         432 :         if (!emitTree(forHead->pn_kid2))
    7708           0 :             return false;
    7709           9 :     } else if (!forHead->pn_kid3) {
    7710             :         // If there is no condition clause and no update clause, mark
    7711             :         // the loop-ending "goto" with the location of the "for".
    7712             :         // This ensures that the debugger will stop on each loop
    7713             :         // iteration.
    7714           9 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    7715           0 :             return false;
    7716             :     }
    7717             : 
    7718             :     /* Set the first note offset so we can find the loop condition. */
    7719         441 :     if (!setSrcNoteOffset(noteIndex, 0, tmp3 - tmp))
    7720           0 :         return false;
    7721         441 :     if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTarget.offset - tmp))
    7722           0 :         return false;
    7723             : 
    7724             :     /* If no loop condition, just emit a loop-closing jump. */
    7725         441 :     JumpList beq;
    7726         441 :     JumpTarget breakTarget{ -1 };
    7727         441 :     if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
    7728           0 :         return false;
    7729             : 
    7730             :     /* The third note offset helps us find the loop-closing jump. */
    7731         441 :     if (!setSrcNoteOffset(noteIndex, 2, beq.offset - tmp))
    7732           0 :         return false;
    7733             : 
    7734         441 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    7735           0 :         return false;
    7736             : 
    7737         441 :     if (!loopInfo.patchBreaksAndContinues(this))
    7738           0 :         return false;
    7739             : 
    7740         441 :     return true;
    7741             : }
    7742             : 
    7743             : bool
    7744         813 : BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
    7745             : {
    7746         813 :     MOZ_ASSERT(pn->isKind(PNK_FOR));
    7747             : 
    7748         813 :     if (pn->pn_left->isKind(PNK_FORHEAD))
    7749         441 :         return emitCStyleFor(pn, headLexicalEmitterScope);
    7750             : 
    7751         372 :     if (!updateLineNumberNotes(pn->pn_pos.begin))
    7752           0 :         return false;
    7753             : 
    7754         372 :     if (pn->pn_left->isKind(PNK_FORIN))
    7755          36 :         return emitForIn(pn, headLexicalEmitterScope);
    7756             : 
    7757         336 :     MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF));
    7758         336 :     return emitForOf(pn, headLexicalEmitterScope);
    7759             : }
    7760             : 
    7761             : bool
    7762           0 : BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexicalScope)
    7763             : {
    7764             :     // ES6 specifies that lexical for-loop variables get a fresh binding each
    7765             :     // iteration, and that evaluation of the expression looped over occurs with
    7766             :     // these variables dead zoned.  But these rules only apply to *standard*
    7767             :     // for-in/of loops, and we haven't extended these requirements to
    7768             :     // comprehension syntax.
    7769             : 
    7770           0 :     *lexicalScope = pn->isKind(PNK_LEXICALSCOPE);
    7771           0 :     if (*lexicalScope) {
    7772             :         // This is initially-ES7-tracked syntax, now with considerably murkier
    7773             :         // outlook. The scope work is done by the caller by instantiating an
    7774             :         // EmitterScope. There's nothing to do here.
    7775             :     } else {
    7776             :         // This is legacy comprehension syntax.  We'll have PNK_LET here, using
    7777             :         // a lexical scope provided by/for the entire comprehension.  Name
    7778             :         // analysis assumes declarations initialize lets, but as we're handling
    7779             :         // this declaration manually, we must also initialize manually to avoid
    7780             :         // triggering dead zone checks.
    7781           0 :         MOZ_ASSERT(pn->isKind(PNK_LET));
    7782           0 :         MOZ_ASSERT(pn->pn_count == 1);
    7783             : 
    7784           0 :         if (!emitDeclarationList(pn))
    7785           0 :             return false;
    7786             :     }
    7787             : 
    7788           0 :     return true;
    7789             : }
    7790             : 
    7791             : bool
    7792           0 : BytecodeEmitter::emitComprehensionForOf(ParseNode* pn)
    7793             : {
    7794           0 :     MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
    7795             : 
    7796           0 :     ParseNode* forHead = pn->pn_left;
    7797           0 :     MOZ_ASSERT(forHead->isKind(PNK_FOROF));
    7798             : 
    7799           0 :     ParseNode* forHeadExpr = forHead->pn_kid3;
    7800           0 :     ParseNode* forBody = pn->pn_right;
    7801             : 
    7802           0 :     ParseNode* loopDecl = forHead->pn_kid1;
    7803           0 :     bool lexicalScope = false;
    7804           0 :     if (!emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
    7805           0 :         return false;
    7806             : 
    7807             :     // For-of loops run with two values on the stack: the iterator and the
    7808             :     // current result object.
    7809             : 
    7810             :     // Evaluate the expression to the right of 'of'.
    7811           0 :     if (!emitTree(forHeadExpr))                // EXPR
    7812           0 :         return false;
    7813           0 :     if (!emitIterator())                       // ITER
    7814           0 :         return false;
    7815             : 
    7816             :     // Push a dummy result so that we properly enter iteration midstream.
    7817           0 :     if (!emit1(JSOP_UNDEFINED))                // ITER VALUE
    7818           0 :         return false;
    7819             : 
    7820             :     // Enter the block before the loop body, after evaluating the obj.
    7821             :     // Initialize let bindings with undefined when entering, as the name
    7822             :     // assigned to is a plain assignment.
    7823           0 :     TDZCheckCache tdzCache(this);
    7824           0 :     Maybe<EmitterScope> emitterScope;
    7825             :     ParseNode* loopVariableName;
    7826           0 :     if (lexicalScope) {
    7827           0 :         loopVariableName = parser.singleBindingFromDeclaration(loopDecl->pn_expr);
    7828           0 :         emitterScope.emplace(this);
    7829           0 :         if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
    7830           0 :             return false;
    7831             :     } else {
    7832           0 :         loopVariableName = parser.singleBindingFromDeclaration(loopDecl);
    7833             :     }
    7834             : 
    7835           0 :     LoopControl loopInfo(this, StatementKind::ForOfLoop);
    7836             : 
    7837             :     // Jump down to the loop condition to minimize overhead assuming at least
    7838             :     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
    7839             :     // find the loop-closing jump.
    7840             :     unsigned noteIndex;
    7841           0 :     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
    7842           0 :         return false;
    7843           0 :     JumpList jmp;
    7844           0 :     if (!emitJump(JSOP_GOTO, &jmp))
    7845           0 :         return false;
    7846             : 
    7847           0 :     JumpTarget top{ -1 };
    7848           0 :     if (!emitLoopHead(nullptr, &top))
    7849           0 :         return false;
    7850             : 
    7851             : #ifdef DEBUG
    7852           0 :     int loopDepth = this->stackDepth;
    7853             : #endif
    7854             : 
    7855           0 :     if (!emit1(JSOP_POP))                                 // ITER
    7856           0 :         return false;
    7857           0 :     if (!emit1(JSOP_DUP))                                 // ITER ITER
    7858           0 :         return false;
    7859           0 :     if (!emitIteratorNext(forHead))                       // ITER RESULT
    7860           0 :         return false;
    7861           0 :     if (!emit1(JSOP_DUP))                                 // ITER RESULT RESULT
    7862           0 :         return false;
    7863           0 :     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // ITER RESULT DONE
    7864           0 :         return false;
    7865             : 
    7866           0 :     IfThenElseEmitter ifDone(this);
    7867             : 
    7868           0 :     if (!ifDone.emitIf())                                 // ITER RESULT
    7869           0 :         return false;
    7870             : 
    7871             :     // Remove RESULT from the stack to release it.
    7872           0 :     if (!emit1(JSOP_POP))                                 // ITER
    7873           0 :         return false;
    7874           0 :     if (!emit1(JSOP_UNDEFINED))                           // ITER UNDEF
    7875           0 :         return false;
    7876             : 
    7877             :     // If the iteration is done, leave loop here, instead of the branch at
    7878             :     // the end of the loop.
    7879           0 :     if (!loopInfo.emitSpecialBreakForDone(this))          // ITER UNDEF
    7880           0 :         return false;
    7881             : 
    7882           0 :     if (!ifDone.emitEnd())                                // ITER RESULT
    7883           0 :         return false;
    7884             : 
    7885             :     // Emit code to assign result.value to the iteration variable.
    7886           0 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ITER VALUE
    7887           0 :         return false;
    7888             : 
    7889             :     // Notice: Comprehension for-of doesn't perform IteratorClose, since it's
    7890             :     // not in the spec.
    7891           0 :     if (!emitAssignment(loopVariableName, JSOP_NOP, nullptr)) // ITER VALUE
    7892           0 :         return false;
    7893             : 
    7894             :     // Remove VALUE from the stack to release it.
    7895           0 :     if (!emit1(JSOP_POP))                                 // ITER
    7896           0 :         return false;
    7897           0 :     if (!emit1(JSOP_UNDEFINED))                           // ITER UNDEF
    7898           0 :         return false;
    7899             : 
    7900             :     // The stack should be balanced around the assignment opcode sequence.
    7901           0 :     MOZ_ASSERT(this->stackDepth == loopDepth);
    7902             : 
    7903             :     // Emit code for the loop body.
    7904           0 :     if (!emitTree(forBody))                               // ITER UNDEF
    7905           0 :         return false;
    7906             : 
    7907             :     // The stack should be balanced around the assignment opcode sequence.
    7908           0 :     MOZ_ASSERT(this->stackDepth == loopDepth);
    7909             : 
    7910             :     // Set offset for continues.
    7911           0 :     loopInfo.continueTarget = { offset() };
    7912             : 
    7913           0 :     if (!emitLoopEntry(forHeadExpr, jmp))
    7914           0 :         return false;
    7915             : 
    7916           0 :     if (!emit1(JSOP_FALSE))                               // ITER VALUE FALSE
    7917           0 :         return false;
    7918             : 
    7919           0 :     JumpList beq;
    7920           0 :     JumpTarget breakTarget{ -1 };
    7921           0 :     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    7922           0 :         return false;                                     // ITER VALUE
    7923             : 
    7924           0 :     MOZ_ASSERT(this->stackDepth == loopDepth);
    7925             : 
    7926             :     // Let Ion know where the closing jump of this loop is.
    7927           0 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
    7928           0 :         return false;
    7929             : 
    7930           0 :     if (!loopInfo.patchBreaksAndContinues(this))
    7931           0 :         return false;
    7932             : 
    7933           0 :     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
    7934           0 :         return false;
    7935             : 
    7936           0 :     if (emitterScope) {
    7937           0 :         if (!emitterScope->leave(this))
    7938           0 :             return false;
    7939           0 :         emitterScope.reset();
    7940             :     }
    7941             : 
    7942             :     // Pop the result and the iter.
    7943           0 :     return emitPopN(2);                                   //
    7944             : }
    7945             : 
    7946             : bool
    7947           0 : BytecodeEmitter::emitComprehensionForIn(ParseNode* pn)
    7948             : {
    7949           0 :     MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
    7950             : 
    7951           0 :     ParseNode* forHead = pn->pn_left;
    7952           0 :     MOZ_ASSERT(forHead->isKind(PNK_FORIN));
    7953             : 
    7954           0 :     ParseNode* forBody = pn->pn_right;
    7955             : 
    7956           0 :     ParseNode* loopDecl = forHead->pn_kid1;
    7957           0 :     bool lexicalScope = false;
    7958           0 :     if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
    7959           0 :         return false;
    7960             : 
    7961             :     // Evaluate the expression to the right of 'in'.
    7962           0 :     if (!emitTree(forHead->pn_kid3))
    7963           0 :         return false;
    7964             : 
    7965             :     /*
    7966             :      * Emit a bytecode to convert top of stack value to the iterator
    7967             :      * object depending on the loop variant (for-in, for-each-in, or
    7968             :      * destructuring for-in).
    7969             :      */
    7970           0 :     MOZ_ASSERT(pn->isOp(JSOP_ITER));
    7971           0 :     if (!emit2(JSOP_ITER, (uint8_t) pn->pn_iflags))
    7972           0 :         return false;
    7973             : 
    7974             :     // For-in loops have both the iterator and the value on the stack. Push
    7975             :     // undefined to balance the stack.
    7976           0 :     if (!emit1(JSOP_UNDEFINED))
    7977           0 :         return false;
    7978             : 
    7979             :     // Enter the block before the loop body, after evaluating the obj.
    7980             :     // Initialize let bindings with undefined when entering, as the name
    7981             :     // assigned to is a plain assignment.
    7982           0 :     TDZCheckCache tdzCache(this);
    7983           0 :     Maybe<EmitterScope> emitterScope;
    7984           0 :     if (lexicalScope) {
    7985           0 :         emitterScope.emplace(this);
    7986           0 :         if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
    7987           0 :             return false;
    7988             :     }
    7989             : 
    7990           0 :     LoopControl loopInfo(this, StatementKind::ForInLoop);
    7991             : 
    7992             :     /* Annotate so IonMonkey can find the loop-closing jump. */
    7993             :     unsigned noteIndex;
    7994           0 :     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
    7995           0 :         return false;
    7996             : 
    7997             :     /*
    7998             :      * Jump down to the loop condition to minimize overhead assuming at
    7999             :      * least one iteration, as the other loop forms do.
    8000             :      */
    8001           0 :     JumpList jmp;
    8002           0 :     if (!emitJump(JSOP_GOTO, &jmp))
    8003           0 :         return false;
    8004             : 
    8005           0 :     JumpTarget top{ -1 };
    8006           0 :     if (!emitLoopHead(nullptr, &top))
    8007           0 :         return false;
    8008             : 
    8009             : #ifdef DEBUG
    8010           0 :     int loopDepth = this->stackDepth;
    8011             : #endif
    8012             : 
    8013             :     // Emit code to assign the enumeration value to the left hand side, but
    8014             :     // also leave it on the stack.
    8015           0 :     if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr))
    8016           0 :         return false;
    8017             : 
    8018             :     /* The stack should be balanced around the assignment opcode sequence. */
    8019           0 :     MOZ_ASSERT(this->stackDepth == loopDepth);
    8020             : 
    8021             :     /* Emit code for the loop body. */
    8022           0 :     if (!emitTree(forBody))
    8023           0 :         return false;
    8024             : 
    8025             :     // Set offset for continues.
    8026           0 :     loopInfo.continueTarget = { offset() };
    8027             : 
    8028           0 :     if (!emitLoopEntry(nullptr, jmp))
    8029           0 :         return false;
    8030           0 :     if (!emit1(JSOP_POP))
    8031           0 :         return false;
    8032           0 :     if (!emit1(JSOP_MOREITER))
    8033           0 :         return false;
    8034           0 :     if (!emit1(JSOP_ISNOITER))
    8035           0 :         return false;
    8036           0 :     JumpList beq;
    8037           0 :     JumpTarget breakTarget{ -1 };
    8038           0 :     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
    8039           0 :         return false;
    8040             : 
    8041             :     /* Set the srcnote offset so we can find the closing jump. */
    8042           0 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
    8043           0 :         return false;
    8044             : 
    8045           0 :     if (!loopInfo.patchBreaksAndContinues(this))
    8046           0 :         return false;
    8047             : 
    8048             :     // Pop the enumeration value.
    8049           0 :     if (!emit1(JSOP_POP))
    8050           0 :         return false;
    8051             : 
    8052           0 :     JumpTarget endIter{ offset() };
    8053           0 :     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, endIter.offset))
    8054           0 :         return false;
    8055           0 :     if (!emit1(JSOP_ENDITER))
    8056           0 :         return false;
    8057             : 
    8058           0 :     if (emitterScope) {
    8059           0 :         if (!emitterScope->leave(this))
    8060           0 :             return false;
    8061           0 :         emitterScope.reset();
    8062             :     }
    8063             : 
    8064           0 :     return true;
    8065             : }
    8066             : 
    8067             : bool
    8068           0 : BytecodeEmitter::emitComprehensionFor(ParseNode* compFor)
    8069             : {
    8070           0 :     MOZ_ASSERT(compFor->pn_left->isKind(PNK_FORIN) ||
    8071             :                compFor->pn_left->isKind(PNK_FOROF));
    8072             : 
    8073           0 :     if (!updateLineNumberNotes(compFor->pn_pos.begin))
    8074           0 :         return false;
    8075             : 
    8076           0 :     return compFor->pn_left->isKind(PNK_FORIN)
    8077           0 :            ? emitComprehensionForIn(compFor)
    8078           0 :            : emitComprehensionForOf(compFor);
    8079             : }
    8080             : 
    8081             : MOZ_NEVER_INLINE bool
    8082        5861 : BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
    8083             : {
    8084        5861 :     FunctionBox* funbox = pn->pn_funbox;
    8085       11723 :     RootedFunction fun(cx, funbox->function());
    8086       11723 :     RootedAtom name(cx, fun->explicitName());
    8087        5861 :     MOZ_ASSERT_IF(fun->isInterpretedLazy(), fun->lazyScript());
    8088             : 
    8089             :     /*
    8090             :      * Set the |wasEmitted| flag in the funbox once the function has been
    8091             :      * emitted. Function definitions that need hoisting to the top of the
    8092             :      * function will be seen by emitFunction in two places.
    8093             :      */
    8094        5861 :     if (funbox->wasEmitted) {
    8095             :         // Annex B block-scoped functions are hoisted like any other
    8096             :         // block-scoped function to the top of their scope. When their
    8097             :         // definitions are seen for the second time, we need to emit the
    8098             :         // assignment that assigns the function to the outer 'var' binding.
    8099          68 :         if (funbox->isAnnexB) {
    8100           0 :             auto emitRhs = [&name](BytecodeEmitter* bce, const NameLocation&, bool) {
    8101             :                 // The RHS is the value of the lexically bound name in the
    8102             :                 // innermost scope.
    8103           0 :                 return bce->emitGetName(name);
    8104           0 :             };
    8105             : 
    8106             :             // Get the location of the 'var' binding in the body scope. The
    8107             :             // name must be found, else there is a bug in the Annex B handling
    8108             :             // in Parser.
    8109             :             //
    8110             :             // In sloppy eval contexts, this location is dynamic.
    8111           0 :             Maybe<NameLocation> lhsLoc = locationOfNameBoundInScope(name, varEmitterScope);
    8112             : 
    8113             :             // If there are parameter expressions, the var name could be a
    8114             :             // parameter.
    8115           0 :             if (!lhsLoc && sc->isFunctionBox() && sc->asFunctionBox()->hasExtraBodyVarScope())
    8116           0 :                 lhsLoc = locationOfNameBoundInScope(name, varEmitterScope->enclosingInFrame());
    8117             : 
    8118           0 :             if (!lhsLoc) {
    8119           0 :                 lhsLoc = Some(NameLocation::DynamicAnnexBVar());
    8120             :             } else {
    8121           0 :                 MOZ_ASSERT(lhsLoc->bindingKind() == BindingKind::Var ||
    8122             :                            lhsLoc->bindingKind() == BindingKind::FormalParameter ||
    8123             :                            (lhsLoc->bindingKind() == BindingKind::Let &&
    8124             :                             sc->asFunctionBox()->hasParameterExprs));
    8125             :             }
    8126             : 
    8127           0 :             if (!emitSetOrInitializeNameAtLocation(name, *lhsLoc, emitRhs, false))
    8128           0 :                 return false;
    8129           0 :             if (!emit1(JSOP_POP))
    8130           0 :                 return false;
    8131             :         }
    8132             : 
    8133          68 :         MOZ_ASSERT_IF(fun->hasScript(), fun->nonLazyScript());
    8134          68 :         MOZ_ASSERT(pn->functionIsHoisted());
    8135          68 :         return true;
    8136             :     }
    8137             : 
    8138        5793 :     funbox->wasEmitted = true;
    8139             : 
    8140             :     /*
    8141             :      * Mark as singletons any function which will only be executed once, or
    8142             :      * which is inner to a lambda we only expect to run once. In the latter
    8143             :      * case, if the lambda runs multiple times then CloneFunctionObject will
    8144             :      * make a deep clone of its contents.
    8145             :      */
    8146        5793 :     if (fun->isInterpreted()) {
    8147        5793 :         bool singleton = checkRunOnceContext();
    8148        5793 :         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
    8149           0 :             return false;
    8150             : 
    8151        5793 :         SharedContext* outersc = sc;
    8152        5793 :         if (fun->isInterpretedLazy()) {
    8153             :             // We need to update the static scope chain regardless of whether
    8154             :             // the LazyScript has already been initialized, due to the case
    8155             :             // where we previously successfully compiled an inner function's
    8156             :             // lazy script but failed to compile the outer script after the
    8157             :             // fact. If we attempt to compile the outer script again, the
    8158             :             // static scope chain will be newly allocated and will mismatch
    8159             :             // the previously compiled LazyScript's.
    8160        1811 :             ScriptSourceObject* source = &script->sourceObject()->as<ScriptSourceObject>();
    8161        1811 :             fun->lazyScript()->setEnclosingScopeAndSource(innermostScope(), source);
    8162        1811 :             if (emittingRunOnceLambda)
    8163           0 :                 fun->lazyScript()->setTreatAsRunOnce();
    8164             :         } else {
    8165        3982 :             MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
    8166             : 
    8167             :             // Inherit most things (principals, version, etc) from the
    8168             :             // parent.  Use default values for the rest.
    8169        7965 :             Rooted<JSScript*> parent(cx, script);
    8170        3982 :             MOZ_ASSERT(parent->getVersion() == parser.options().version);
    8171        3982 :             MOZ_ASSERT(parent->mutedErrors() == parser.options().mutedErrors());
    8172        3982 :             const TransitiveCompileOptions& transitiveOptions = parser.options();
    8173        7965 :             CompileOptions options(cx, transitiveOptions);
    8174             : 
    8175        7965 :             Rooted<JSObject*> sourceObject(cx, script->sourceObject());
    8176        7964 :             Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
    8177             :                                                           funbox->bufStart, funbox->bufEnd,
    8178             :                                                           funbox->toStringStart,
    8179        7965 :                                                           funbox->toStringEnd));
    8180        3982 :             if (!script)
    8181           0 :                 return false;
    8182             : 
    8183             :             BytecodeEmitter bce2(this, parser, funbox, script, /* lazyScript = */ nullptr,
    8184        7965 :                                  pn->pn_pos, emitterMode);
    8185        3982 :             if (!bce2.init())
    8186           0 :                 return false;
    8187             : 
    8188             :             /* We measured the max scope depth when we parsed the function. */
    8189        3982 :             if (!bce2.emitFunctionScript(pn->pn_body))
    8190           0 :                 return false;
    8191             : 
    8192        3983 :             if (funbox->isLikelyConstructorWrapper())
    8193           0 :                 script->setLikelyConstructorWrapper();
    8194             :         }
    8195             : 
    8196        5794 :         if (outersc->isFunctionBox())
    8197        1120 :             outersc->asFunctionBox()->setHasInnerFunctions();
    8198             :     } else {
    8199           0 :         MOZ_ASSERT(IsAsmJSModule(fun));
    8200             :     }
    8201             : 
    8202             :     /* Make the function object a literal in the outer script's pool. */
    8203        5794 :     unsigned index = objectList.add(pn->pn_funbox);
    8204             : 
    8205             :     /* Non-hoisted functions simply emit their respective op. */
    8206        5794 :     if (!pn->functionIsHoisted()) {
    8207             :         /* JSOP_LAMBDA_ARROW is always preceded by a new.target */
    8208        3975 :         MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW));
    8209        3975 :         if (funbox->isAsync()) {
    8210         108 :             MOZ_ASSERT(!needsProto);
    8211         108 :             return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(),
    8212         216 :                                     fun->isStarGenerator());
    8213             :         }
    8214             : 
    8215        3867 :         if (fun->isArrow()) {
    8216         695 :             if (sc->allowNewTarget()) {
    8217         589 :                 if (!emit1(JSOP_NEWTARGET))
    8218           0 :                     return false;
    8219             :             } else {
    8220         106 :                 if (!emit1(JSOP_NULL))
    8221           0 :                     return false;
    8222             :             }
    8223             :         }
    8224             : 
    8225        3867 :         if (needsProto) {
    8226          15 :             MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA);
    8227          15 :             pn->setOp(JSOP_FUNWITHPROTO);
    8228             :         }
    8229             : 
    8230        3867 :         if (pn->getOp() == JSOP_DEFFUN) {
    8231           0 :             if (!emitIndex32(JSOP_LAMBDA, index))
    8232           0 :                 return false;
    8233           0 :             return emit1(JSOP_DEFFUN);
    8234             :         }
    8235             : 
    8236        3867 :         return emitIndex32(pn->getOp(), index);
    8237             :     }
    8238             : 
    8239        1819 :     MOZ_ASSERT(!needsProto);
    8240             : 
    8241             :     bool topLevelFunction;
    8242        1819 :     if (sc->isFunctionBox() || (sc->isEvalContext() && sc->strict())) {
    8243             :         // No nested functions inside other functions are top-level.
    8244          68 :         topLevelFunction = false;
    8245             :     } else {
    8246             :         // In sloppy eval scripts, top-level functions in are accessed
    8247             :         // dynamically. In global and module scripts, top-level functions are
    8248             :         // those bound in the var scope.
    8249        1751 :         NameLocation loc = lookupName(name);
    8250        3502 :         topLevelFunction = loc.kind() == NameLocation::Kind::Dynamic ||
    8251        1751 :                            loc.bindingKind() == BindingKind::Var;
    8252             :     }
    8253             : 
    8254        1819 :     if (topLevelFunction) {
    8255        1751 :         if (sc->isModuleContext()) {
    8256             :             // For modules, we record the function and instantiate the binding
    8257             :             // during ModuleDeclarationInstantiation(), before the script is run.
    8258             : 
    8259           0 :             RootedModuleObject module(cx, sc->asModuleContext()->module());
    8260           0 :             if (!module->noteFunctionDeclaration(cx, name, fun))
    8261           0 :                 return false;
    8262             :         } else {
    8263        1751 :             MOZ_ASSERT(sc->isGlobalContext() || sc->isEvalContext());
    8264        1751 :             MOZ_ASSERT(pn->getOp() == JSOP_NOP);
    8265        1751 :             switchToPrologue();
    8266        1751 :             if (funbox->isAsync()) {
    8267           2 :                 if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(),
    8268           2 :                                       fun->isStarGenerator()))
    8269             :                 {
    8270           0 :                     return false;
    8271             :                 }
    8272             :             } else {
    8273        1749 :                 if (!emitIndex32(JSOP_LAMBDA, index))
    8274           0 :                     return false;
    8275             :             }
    8276        1751 :             if (!emit1(JSOP_DEFFUN))
    8277           0 :                 return false;
    8278        1751 :             if (!updateSourceCoordNotes(pn->pn_pos.begin))
    8279           0 :                 return false;
    8280        1751 :             switchToMain();
    8281             :         }
    8282             :     } else {
    8283             :         // For functions nested within functions and blocks, make a lambda and
    8284             :         // initialize the binding name of the function in the current scope.
    8285             : 
    8286          68 :         bool isAsync = funbox->isAsync();
    8287          68 :         bool isStarGenerator = funbox->isStarGenerator();
    8288             :         auto emitLambda = [index, isAsync, isStarGenerator](BytecodeEmitter* bce,
    8289         140 :                                                             const NameLocation&, bool) {
    8290          68 :             if (isAsync) {
    8291           4 :                 return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false,
    8292           4 :                                              /* isArrow = */ false, isStarGenerator);
    8293             :             }
    8294          64 :             return bce->emitIndexOp(JSOP_LAMBDA, index);
    8295          68 :         };
    8296             : 
    8297          68 :         if (!emitInitializeName(name, emitLambda))
    8298           0 :             return false;
    8299          68 :         if (!emit1(JSOP_POP))
    8300           0 :             return false;
    8301             :     }
    8302             : 
    8303        1819 :     return true;
    8304             : }
    8305             : 
    8306             : bool
    8307         114 : BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) {
    8308         114 :     if (isArrow) {
    8309          26 :         if (sc->allowNewTarget()) {
    8310          25 :             if (!emit1(JSOP_NEWTARGET))
    8311           0 :                 return false;
    8312             :         } else {
    8313           1 :             if (!emit1(JSOP_NULL))
    8314           0 :                 return false;
    8315             :         }
    8316          26 :         if (!emitIndex32(JSOP_LAMBDA_ARROW, index))
    8317           0 :             return false;
    8318             :     } else {
    8319          88 :         if (!emitIndex32(JSOP_LAMBDA, index))
    8320           0 :             return false;
    8321             :     }
    8322             : 
    8323         114 :     return true;
    8324             : }
    8325             : 
    8326             : bool
    8327         114 : BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
    8328             :                                   bool isStarGenerator)
    8329             : {
    8330             :     // needsHomeObject can be true for propertyList for extended class.
    8331             :     // In that case push both unwrapped and wrapped function, in order to
    8332             :     // initialize home object of unwrapped function, and set wrapped function
    8333             :     // as a property.
    8334             :     //
    8335             :     //   lambda       // unwrapped
    8336             :     //   dup          // unwrapped unwrapped
    8337             :     //   toasync      // unwrapped wrapped
    8338             :     //
    8339             :     // Emitted code is surrounded by the following code.
    8340             :     //
    8341             :     //                    // classObj classCtor classProto
    8342             :     //   (emitted code)   // classObj classCtor classProto unwrapped wrapped
    8343             :     //   swap             // classObj classCtor classProto wrapped unwrapped
    8344             :     //   inithomeobject 1 // classObj classCtor classProto wrapped unwrapped
    8345             :     //                    //   initialize the home object of unwrapped
    8346             :     //                    //   with classProto here
    8347             :     //   pop              // classObj classCtor classProto wrapped
    8348             :     //   inithiddenprop   // classObj classCtor classProto wrapped
    8349             :     //                    //   initialize the property of the classProto
    8350             :     //                    //   with wrapped function here
    8351             :     //   pop              // classObj classCtor classProto
    8352             :     //
    8353             :     // needsHomeObject is false for other cases, push wrapped function only.
    8354         114 :     if (!emitAsyncWrapperLambda(index, isArrow))
    8355           0 :         return false;
    8356         114 :     if (needsHomeObject) {
    8357           0 :         if (!emit1(JSOP_DUP))
    8358           0 :             return false;
    8359             :     }
    8360         114 :     if (isStarGenerator) {
    8361           0 :         if (!emit1(JSOP_TOASYNCGEN))
    8362           0 :             return false;
    8363             :     } else {
    8364         114 :         if (!emit1(JSOP_TOASYNC))
    8365           0 :             return false;
    8366             :     }
    8367         114 :     return true;
    8368             : }
    8369             : 
    8370             : bool
    8371          20 : BytecodeEmitter::emitDo(ParseNode* pn)
    8372             : {
    8373             :     /* Emit an annotated nop so IonBuilder can recognize the 'do' loop. */
    8374             :     unsigned noteIndex;
    8375          20 :     if (!newSrcNote(SRC_WHILE, &noteIndex))
    8376           0 :         return false;
    8377          20 :     if (!emit1(JSOP_NOP))
    8378           0 :         return false;
    8379             : 
    8380             :     unsigned noteIndex2;
    8381          20 :     if (!newSrcNote(SRC_WHILE, &noteIndex2))
    8382           0 :         return false;
    8383             : 
    8384             :     /* Compile the loop body. */
    8385             :     JumpTarget top;
    8386          20 :     if (!emitLoopHead(pn->pn_left, &top))
    8387           0 :         return false;
    8388             : 
    8389          40 :     LoopControl loopInfo(this, StatementKind::DoLoop);
    8390             : 
    8391          20 :     JumpList empty;
    8392          20 :     if (!emitLoopEntry(nullptr, empty))
    8393           0 :         return false;
    8394             : 
    8395          20 :     if (!emitTree(pn->pn_left))
    8396           0 :         return false;
    8397             : 
    8398             :     // Set the offset for continues.
    8399          20 :     if (!emitJumpTarget(&loopInfo.continueTarget))
    8400           0 :         return false;
    8401             : 
    8402             :     /* Compile the loop condition, now that continues know where to go. */
    8403          20 :     if (!emitTree(pn->pn_right))
    8404           0 :         return false;
    8405             : 
    8406          20 :     JumpList beq;
    8407          20 :     JumpTarget breakTarget{ -1 };
    8408          20 :     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
    8409           0 :         return false;
    8410             : 
    8411          20 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    8412           0 :         return false;
    8413             : 
    8414             :     /*
    8415             :      * Update the annotations with the update and back edge positions, for
    8416             :      * IonBuilder.
    8417             :      *
    8418             :      * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
    8419             :      * note gets bigger.
    8420             :      */
    8421          20 :     if (!setSrcNoteOffset(noteIndex2, 0, beq.offset - top.offset))
    8422           0 :         return false;
    8423          20 :     if (!setSrcNoteOffset(noteIndex, 0, 1 + (loopInfo.continueTarget.offset - top.offset)))
    8424           0 :         return false;
    8425             : 
    8426          20 :     if (!loopInfo.patchBreaksAndContinues(this))
    8427           0 :         return false;
    8428             : 
    8429          20 :     return true;
    8430             : }
    8431             : 
    8432             : bool
    8433         183 : BytecodeEmitter::emitWhile(ParseNode* pn)
    8434             : {
    8435             :     /*
    8436             :      * Minimize bytecodes issued for one or more iterations by jumping to
    8437             :      * the condition below the body and closing the loop if the condition
    8438             :      * is true with a backward branch. For iteration count i:
    8439             :      *
    8440             :      *  i    test at the top                 test at the bottom
    8441             :      *  =    ===============                 ==================
    8442             :      *  0    ifeq-pass                       goto; ifne-fail
    8443             :      *  1    ifeq-fail; goto; ifne-pass      goto; ifne-pass; ifne-fail
    8444             :      *  2    2*(ifeq-fail; goto); ifeq-pass  goto; 2*ifne-pass; ifne-fail
    8445             :      *  . . .
    8446             :      *  N    N*(ifeq-fail; goto); ifeq-pass  goto; N*ifne-pass; ifne-fail
    8447             :      */
    8448             : 
    8449             :     // If we have a single-line while, like "while (x) ;", we want to
    8450             :     // emit the line note before the initial goto, so that the
    8451             :     // debugger sees a single entry point.  This way, if there is a
    8452             :     // breakpoint on the line, it will only fire once; and "next"ing
    8453             :     // will skip the whole loop.  However, for the multi-line case we
    8454             :     // want to emit the line note after the initial goto, so that
    8455             :     // "cont" stops on each iteration -- but without a stop before the
    8456             :     // first iteration.
    8457         366 :     if (parser.tokenStream().srcCoords.lineNum(pn->pn_pos.begin) ==
    8458         183 :         parser.tokenStream().srcCoords.lineNum(pn->pn_pos.end))
    8459             :     {
    8460           0 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
    8461           0 :             return false;
    8462             :     }
    8463             : 
    8464         183 :     JumpTarget top{ -1 };
    8465         183 :     if (!emitJumpTarget(&top))
    8466           0 :         return false;
    8467             : 
    8468         366 :     LoopControl loopInfo(this, StatementKind::WhileLoop);
    8469         183 :     loopInfo.continueTarget = top;
    8470             : 
    8471             :     unsigned noteIndex;
    8472         183 :     if (!newSrcNote(SRC_WHILE, &noteIndex))
    8473           0 :         return false;
    8474             : 
    8475         183 :     JumpList jmp;
    8476         183 :     if (!emitJump(JSOP_GOTO, &jmp))
    8477           0 :         return false;
    8478             : 
    8479         183 :     if (!emitLoopHead(pn->pn_right, &top))
    8480           0 :         return false;
    8481             : 
    8482         183 :     if (!emitTreeInBranch(pn->pn_right))
    8483           0 :         return false;
    8484             : 
    8485         183 :     if (!emitLoopEntry(pn->pn_left, jmp))
    8486           0 :         return false;
    8487         183 :     if (!emitTree(pn->pn_left))
    8488           0 :         return false;
    8489             : 
    8490         183 :     JumpList beq;
    8491         183 :     JumpTarget breakTarget{ -1 };
    8492         183 :     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
    8493           0 :         return false;
    8494             : 
    8495         183 :     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
    8496           0 :         return false;
    8497             : 
    8498         183 :     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
    8499           0 :         return false;
    8500             : 
    8501         183 :     if (!loopInfo.patchBreaksAndContinues(this))
    8502           0 :         return false;
    8503             : 
    8504         183 :     return true;
    8505             : }
    8506             : 
    8507             : bool
    8508         479 : BytecodeEmitter::emitBreak(PropertyName* label)
    8509             : {
    8510             :     BreakableControl* target;
    8511             :     SrcNoteType noteType;
    8512         479 :     if (label) {
    8513             :         // Any statement with the matching label may be the break target.
    8514           0 :         auto hasSameLabel = [label](LabelControl* labelControl) {
    8515           0 :             return labelControl->label() == label;
    8516           0 :         };
    8517           0 :         target = findInnermostNestableControl<LabelControl>(hasSameLabel);
    8518           0 :         noteType = SRC_BREAK2LABEL;
    8519             :     } else {
    8520         479 :         auto isNotLabel = [](BreakableControl* control) {
    8521         479 :             return !control->is<LabelControl>();
    8522         479 :         };
    8523         479 :         target = findInnermostNestableControl<BreakableControl>(isNotLabel);
    8524         479 :         noteType = (target->kind() == StatementKind::Switch) ? SRC_SWITCHBREAK : SRC_BREAK;
    8525             :     }
    8526             : 
    8527         479 :     return emitGoto(target, &target->breaks, noteType);
    8528             : }
    8529             : 
    8530             : bool
    8531         121 : BytecodeEmitter::emitContinue(PropertyName* label)
    8532             : {
    8533         121 :     LoopControl* target = nullptr;
    8534         121 :     if (label) {
    8535             :         // Find the loop statement enclosed by the matching label.
    8536           0 :         NestableControl* control = innermostNestableControl;
    8537           0 :         while (!control->is<LabelControl>() || control->as<LabelControl>().label() != label) {
    8538           0 :             if (control->is<LoopControl>())
    8539           0 :                 target = &control->as<LoopControl>();
    8540           0 :             control = control->enclosing();
    8541             :         }
    8542             :     } else {
    8543         121 :         target = findInnermostNestableControl<LoopControl>();
    8544             :     }
    8545         121 :     return emitGoto(target, &target->continues, SRC_CONTINUE);
    8546             : }
    8547             : 
    8548             : bool
    8549        6976 : BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
    8550             : {
    8551        6976 :     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
    8552        6976 :     MOZ_ASSERT(pn->isKind(PNK_NAME));
    8553        6976 :     MOZ_ASSERT(pn->name() == cx->names().dotThis);
    8554             : 
    8555        6976 :     if (!emitTree(pn))
    8556           0 :         return false;
    8557        6976 :     if (sc->needsThisTDZChecks() && !emit1(JSOP_CHECKTHIS))
    8558           0 :         return false;
    8559             : 
    8560        6976 :     return true;
    8561             : }
    8562             : 
    8563             : bool
    8564          13 : BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn)
    8565             : {
    8566          13 :     MOZ_ASSERT(pn->isKind(PNK_SUPERBASE));
    8567          13 :     return emitGetFunctionThis(pn->pn_kid);
    8568             : }
    8569             : 
    8570             : bool
    8571        7700 : BytecodeEmitter::emitThisLiteral(ParseNode* pn)
    8572             : {
    8573        7700 :     MOZ_ASSERT(pn->isKind(PNK_THIS));
    8574             : 
    8575        7700 :     if (ParseNode* thisName = pn->pn_kid)
    8576        6963 :         return emitGetFunctionThis(thisName);
    8577             : 
    8578         737 :     if (sc->thisBinding() == ThisBinding::Module)
    8579           0 :         return emit1(JSOP_UNDEFINED);
    8580             : 
    8581         737 :     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
    8582         737 :     return emit1(JSOP_GLOBALTHIS);
    8583             : }
    8584             : 
    8585             : bool
    8586          14 : BytecodeEmitter::emitCheckDerivedClassConstructorReturn()
    8587             : {
    8588          14 :     MOZ_ASSERT(lookupName(cx->names().dotThis).hasKnownSlot());
    8589          14 :     if (!emitGetName(cx->names().dotThis))
    8590           0 :         return false;
    8591          14 :     if (!emit1(JSOP_CHECKRETURN))
    8592           0 :         return false;
    8593          14 :     return true;
    8594             : }
    8595             : 
    8596             : bool
    8597        6164 : BytecodeEmitter::emitReturn(ParseNode* pn)
    8598             : {
    8599        6164 :     if (!updateSourceCoordNotes(pn->pn_pos.begin))
    8600           0 :         return false;
    8601             : 
    8602        6164 :     bool needsIteratorResult = sc->isFunctionBox() && sc->asFunctionBox()->needsIteratorResult();
    8603        6164 :     if (needsIteratorResult) {
    8604           0 :         if (!emitPrepareIteratorResult())
    8605           0 :             return false;
    8606             :     }
    8607             : 
    8608             :     /* Push a return value */
    8609        6164 :     if (ParseNode* pn2 = pn->pn_kid) {
    8610        5666 :         if (!emitTree(pn2))
    8611           0 :             return false;
    8612             :     } else {
    8613             :         /* No explicit return value provided */
    8614         498 :         if (!emit1(JSOP_UNDEFINED))
    8615           0 :             return false;
    8616             :     }
    8617             : 
    8618        6164 :     if (needsIteratorResult) {
    8619           0 :         if (!emitFinishIteratorResult(true))
    8620           0 :             return false;
    8621             :     }
    8622             : 
    8623             :     // We know functionBodyEndPos is set because "return" is only
    8624             :     // valid in a function, and so we've passed through
    8625             :     // emitFunctionScript.
    8626        6164 :     MOZ_ASSERT(functionBodyEndPosSet);
    8627        6164 :     if (!updateSourceCoordNotes(functionBodyEndPos))
    8628           0 :         return false;
    8629             : 
    8630             :     /*
    8631             :      * EmitNonLocalJumpFixup may add fixup bytecode to close open try
    8632             :      * blocks having finally clauses and to exit intermingled let blocks.
    8633             :      * We can't simply transfer control flow to our caller in that case,
    8634             :      * because we must gosub to those finally clauses from inner to outer,
    8635             :      * with the correct stack pointer (i.e., after popping any with,
    8636             :      * for/in, etc., slots nested inside the finally's try).
    8637             :      *
    8638             :      * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
    8639             :      * extra JSOP_RETRVAL after the fixups.
    8640             :      */
    8641        6164 :     ptrdiff_t top = offset();
    8642             : 
    8643        6164 :     bool needsFinalYield = sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
    8644             :     bool isDerivedClassConstructor =
    8645        6164 :         sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
    8646             : 
    8647        6164 :     if (!emit1((needsFinalYield || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
    8648           0 :         return false;
    8649             : 
    8650             :     // Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
    8651             :     // to ensure that the error is thrown while the scope-chain is still intact.
    8652        6164 :     if (isDerivedClassConstructor) {
    8653           1 :         if (!emitCheckDerivedClassConstructorReturn())
    8654           0 :             return false;
    8655             :     }
    8656             : 
    8657       12328 :     NonLocalExitControl nle(this, NonLocalExitControl::Return);
    8658             : 
    8659        6164 :     if (!nle.prepareForNonLocalJumpToOutermost())
    8660           0 :         return false;
    8661             : 
    8662        6164 :     if (needsFinalYield) {
    8663             :         // We know that .generator is on the function scope, as we just exited
    8664             :         // all nested scopes.
    8665             :         NameLocation loc =
    8666          84 :             *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, varEmitterScope);
    8667          84 :         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
    8668           0 :             return false;
    8669          84 :         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
    8670           0 :             return false;
    8671        6080 :     } else if (isDerivedClassConstructor) {
    8672           1 :         MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
    8673           1 :         if (!emit1(JSOP_RETRVAL))
    8674           0 :             return false;
    8675        6079 :     } else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
    8676        1651 :         code()[top] = JSOP_SETRVAL;
    8677        1651 :         if (!emit1(JSOP_RETRVAL))
    8678           0 :             return false;
    8679             :     }
    8680             : 
    8681        6164 :     return true;
    8682             : }
    8683             : 
    8684             : bool
    8685         380 : BytecodeEmitter::emitGetDotGenerator()
    8686             : {
    8687         380 :     NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator);
    8688         380 :     return emitGetNameAtLocation(cx->names().dotGenerator, loc);
    8689             : }
    8690             : 
    8691             : bool
    8692         127 : BytecodeEmitter::emitInitialYield(ParseNode* pn)
    8693             : {
    8694         127 :     if (!emitTree(pn->pn_kid))
    8695           0 :         return false;
    8696             : 
    8697         127 :     if (!emitYieldOp(JSOP_INITIALYIELD))
    8698           0 :         return false;
    8699             : 
    8700         127 :     if (!emit1(JSOP_POP))
    8701           0 :         return false;
    8702             : 
    8703         127 :     return true;
    8704             : }
    8705             : 
    8706             : bool
    8707          15 : BytecodeEmitter::emitYield(ParseNode* pn)
    8708             : {
    8709          15 :     MOZ_ASSERT(sc->isFunctionBox());
    8710          15 :     MOZ_ASSERT(pn->getOp() == JSOP_YIELD);
    8711             : 
    8712          15 :     bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult();
    8713          15 :     if (needsIteratorResult) {
    8714          15 :         if (!emitPrepareIteratorResult())
    8715           0 :             return false;
    8716             :     }
    8717          15 :     if (pn->pn_kid) {
    8718          15 :         if (!emitTree(pn->pn_kid))
    8719           0 :             return false;
    8720             :     } else {
    8721           0 :         if (!emit1(JSOP_UNDEFINED))
    8722           0 :             return false;
    8723             :     }
    8724          15 :     if (needsIteratorResult) {
    8725          15 :         if (!emitFinishIteratorResult(false))
    8726           0 :             return false;
    8727             :     }
    8728             : 
    8729          15 :     if (!emitGetDotGenerator())
    8730           0 :         return false;
    8731             : 
    8732          15 :     if (!emitYieldOp(JSOP_YIELD))
    8733           0 :         return false;
    8734             : 
    8735          15 :     return true;
    8736             : }
    8737             : 
    8738             : bool
    8739         235 : BytecodeEmitter::emitAwait()
    8740             : {
    8741         235 :     if (!emitGetDotGenerator())
    8742           0 :         return false;
    8743         235 :     if (!emitYieldOp(JSOP_AWAIT))
    8744           0 :         return false;
    8745         235 :     return true;
    8746             : }
    8747             : 
    8748             : bool
    8749         235 : BytecodeEmitter::emitAwait(ParseNode* pn)
    8750             : {
    8751         235 :     MOZ_ASSERT(sc->isFunctionBox());
    8752         235 :     MOZ_ASSERT(pn->getOp() == JSOP_AWAIT);
    8753             : 
    8754         235 :     if (!emitTree(pn->pn_kid))
    8755           0 :         return false;
    8756         235 :     return emitAwait();
    8757             : }
    8758             : 
    8759             : bool
    8760           3 : BytecodeEmitter::emitYieldStar(ParseNode* iter)
    8761             : {
    8762           3 :     MOZ_ASSERT(sc->isFunctionBox());
    8763           3 :     MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator());
    8764             : 
    8765           3 :     bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
    8766             : 
    8767           3 :     if (!emitTree(iter))                                  // ITERABLE
    8768           0 :         return false;
    8769           3 :     if (isAsyncGenerator) {
    8770           0 :         if (!emitAsyncIterator())                         // ITER
    8771           0 :             return false;
    8772             :     } else {
    8773           3 :         if (!emitIterator())                              // ITER
    8774           0 :             return false;
    8775             :     }
    8776             : 
    8777             :     // Initial send value is undefined.
    8778           3 :     if (!emit1(JSOP_UNDEFINED))                           // ITER RECEIVED
    8779           0 :         return false;
    8780             : 
    8781             :     int32_t savedDepthTemp;
    8782           3 :     int32_t startDepth = stackDepth;
    8783           3 :     MOZ_ASSERT(startDepth >= 2);
    8784             : 
    8785             :     TryEmitter tryCatch(this, TryEmitter::TryCatchFinally, TryEmitter::DontUseRetVal,
    8786           6 :                         TryEmitter::DontUseControl);
    8787           3 :     if (!tryCatch.emitJumpOverCatchAndFinally())          // ITER RESULT
    8788           0 :         return false;
    8789             : 
    8790           3 :     JumpTarget tryStart{ offset() };
    8791           3 :     if (!tryCatch.emitTry())                              // ITER RESULT
    8792           0 :         return false;
    8793             : 
    8794           3 :     MOZ_ASSERT(this->stackDepth == startDepth);
    8795             : 
    8796             :     // Load the generator object.
    8797           3 :     if (!emitGetDotGenerator())                           // ITER RESULT GENOBJ
    8798           0 :         return false;
    8799             : 
    8800             :     // Yield RESULT as-is, without re-boxing.
    8801           3 :     if (!emitYieldOp(JSOP_YIELD))                         // ITER RECEIVED
    8802           0 :         return false;
    8803             : 
    8804           3 :     if (!tryCatch.emitCatch())                            // ITER RESULT
    8805           0 :         return false;
    8806             : 
    8807           3 :     stackDepth = startDepth;                              // ITER RESULT
    8808           3 :     if (!emit1(JSOP_EXCEPTION))                           // ITER RESULT EXCEPTION
    8809           0 :         return false;
    8810           3 :     if (!emitDupAt(2))                                    // ITER RESULT EXCEPTION ITER
    8811           0 :         return false;
    8812           3 :     if (!emit1(JSOP_DUP))                                 // ITER RESULT EXCEPTION ITER ITER
    8813           0 :         return false;
    8814           3 :     if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP))   // ITER RESULT EXCEPTION ITER THROW
    8815           0 :         return false;
    8816           3 :     if (!emit1(JSOP_DUP))                                 // ITER RESULT EXCEPTION ITER THROW THROW
    8817           0 :         return false;
    8818           3 :     if (!emit1(JSOP_UNDEFINED))                           // ITER RESULT EXCEPTION ITER THROW THROW UNDEFINED
    8819           0 :         return false;
    8820           3 :     if (!emit1(JSOP_EQ))                                  // ITER RESULT EXCEPTION ITER THROW ?EQL
    8821           0 :         return false;
    8822             : 
    8823           6 :     IfThenElseEmitter ifThrowMethodIsNotDefined(this);
    8824           3 :     if (!ifThrowMethodIsNotDefined.emitIf())              // ITER RESULT EXCEPTION ITER THROW
    8825           0 :         return false;
    8826           3 :     savedDepthTemp = stackDepth;
    8827           3 :     if (!emit1(JSOP_POP))                                 // ITER RESULT EXCEPTION ITER
    8828           0 :         return false;
    8829             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.2
    8830             :     //
    8831             :     // If the iterator does not have a "throw" method, it calls IteratorClose
    8832             :     // and then throws a TypeError.
    8833           3 :     IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync;
    8834           3 :     if (!emitIteratorClose(iterKind))                    // ITER RESULT EXCEPTION
    8835           0 :         return false;
    8836           3 :     if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw
    8837           0 :         return false;
    8838           3 :     stackDepth = savedDepthTemp;
    8839           3 :     if (!ifThrowMethodIsNotDefined.emitEnd())             // ITER OLDRESULT EXCEPTION ITER THROW
    8840           0 :         return false;
    8841             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.4.
    8842             :     // RESULT = ITER.throw(EXCEPTION)                     // ITER OLDRESULT EXCEPTION ITER THROW
    8843           3 :     if (!emit1(JSOP_SWAP))                                // ITER OLDRESULT EXCEPTION THROW ITER
    8844           0 :         return false;
    8845           3 :     if (!emit2(JSOP_PICK, 2))                             // ITER OLDRESULT THROW ITER EXCEPTION
    8846           0 :         return false;
    8847           3 :     if (!emitCall(JSOP_CALL, 1, iter))                    // ITER OLDRESULT RESULT
    8848           0 :         return false;
    8849           3 :     checkTypeSet(JSOP_CALL);
    8850             : 
    8851           3 :     if (isAsyncGenerator) {
    8852           0 :         if (!emitAwait())                                 // ITER OLDRESULT RESULT
    8853           0 :             return false;
    8854             :     }
    8855             : 
    8856           3 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) // ITER OLDRESULT RESULT
    8857           0 :         return false;
    8858           3 :     if (!emit1(JSOP_SWAP))                                // ITER RESULT OLDRESULT
    8859           0 :         return false;
    8860           3 :     if (!emit1(JSOP_POP))                                 // ITER RESULT
    8861           0 :         return false;
    8862           3 :     MOZ_ASSERT(this->stackDepth == startDepth);
    8863           3 :     JumpList checkResult;
    8864             :     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.ii.
    8865             :     //
    8866             :     // Note that there is no GOSUB to the finally block here. If the iterator has a
    8867             :     // "throw" method, it does not perform IteratorClose.
    8868           3 :     if (!emitJump(JSOP_GOTO, &checkResult))               // goto checkResult
    8869           0 :         return false;
    8870             : 
    8871           3 :     if (!tryCatch.emitFinally())
    8872           0 :          return false;
    8873             : 
    8874             :     // ES 14.4.13, yield * AssignmentExpression, step 5.c
    8875             :     //
    8876             :     // Call iterator.return() for receiving a "forced return" completion from
    8877             :     // the generator.
    8878             : 
    8879           6 :     IfThenElseEmitter ifGeneratorClosing(this);
    8880           3 :     if (!emit1(JSOP_ISGENCLOSING))                        // ITER RESULT FTYPE FVALUE CLOSING
    8881           0 :         return false;
    8882           3 :     if (!ifGeneratorClosing.emitIf())                     // ITER RESULT FTYPE FVALUE
    8883           0 :         return false;
    8884             : 
    8885             :     // Step ii.
    8886             :     //
    8887             :     // Get the "return" method.
    8888           3 :     if (!emitDupAt(3))                                    // ITER RESULT FTYPE FVALUE ITER
    8889           0 :         return false;
    8890           3 :     if (!emit1(JSOP_DUP))                                 // ITER RESULT FTYPE FVALUE ITER ITER
    8891           0 :         return false;
    8892           3 :     if (!emitAtomOp(cx->names().return_, JSOP_CALLPROP))  // ITER RESULT FTYPE FVALUE ITER RET
    8893           0 :         return false;
    8894             : 
    8895             :     // Step iii.
    8896             :     //
    8897             :     // Do nothing if "return" is undefined.
    8898           6 :     IfThenElseEmitter ifReturnMethodIsDefined(this);
    8899           3 :     if (!emit1(JSOP_DUP))                                 // ITER RESULT FTYPE FVALUE ITER RET RET
    8900           0 :         return false;
    8901           3 :     if (!emit1(JSOP_UNDEFINED))                           // ITER RESULT FTYPE FVALUE ITER RET RET UNDEFINED
    8902           0 :         return false;
    8903           3 :     if (!emit1(JSOP_NE))                                  // ITER RESULT FTYPE FVALUE ITER RET ?NEQL
    8904           0 :         return false;
    8905             : 
    8906             :     // Step iv.
    8907             :     //
    8908             :     // Call "return" with the argument passed to Generator.prototype.return,
    8909             :     // which is currently in rval.value.
    8910           3 :     if (!ifReturnMethodIsDefined.emitIfElse())            // ITER OLDRESULT FTYPE FVALUE ITER RET
    8911           0 :         return false;
    8912           3 :     if (!emit1(JSOP_SWAP))                                // ITER OLDRESULT FTYPE FVALUE RET ITER
    8913           0 :         return false;
    8914           3 :     if (!emit1(JSOP_GETRVAL))                             // ITER OLDRESULT FTYPE FVALUE RET ITER RVAL
    8915           0 :         return false;
    8916           3 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ITER OLDRESULT FTYPE FVALUE RET ITER VALUE
    8917           0 :         return false;
    8918           3 :     if (!emitCall(JSOP_CALL, 1))                          // ITER OLDRESULT FTYPE FVALUE RESULT
    8919           0 :         return false;
    8920           3 :     checkTypeSet(JSOP_CALL);
    8921             : 
    8922           3 :     if (iterKind == IteratorKind::Async) {
    8923           0 :         if (!emitAwait())                                 // ... FTYPE FVALUE RESULT
    8924           0 :             return false;
    8925             :     }
    8926             : 
    8927             :     // Step v.
    8928           3 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) // ITER OLDRESULT FTYPE FVALUE RESULT
    8929           0 :         return false;
    8930             : 
    8931             :     // Steps vi-viii.
    8932             :     //
    8933             :     // Check if the returned object from iterator.return() is done. If not,
    8934             :     // continuing yielding.
    8935           6 :     IfThenElseEmitter ifReturnDone(this);
    8936           3 :     if (!emit1(JSOP_DUP))                                 // ITER OLDRESULT FTYPE FVALUE RESULT RESULT
    8937           0 :         return false;
    8938           3 :     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // ITER OLDRESULT FTYPE FVALUE RESULT DONE
    8939           0 :         return false;
    8940           3 :     if (!ifReturnDone.emitIfElse())                       // ITER OLDRESULT FTYPE FVALUE RESULT
    8941           0 :         return false;
    8942           3 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ITER OLDRESULT FTYPE FVALUE VALUE
    8943           0 :         return false;
    8944             : 
    8945           3 :     if (isAsyncGenerator) {
    8946           0 :         if (!emitAwait())                                 // ITER OLDRESULT FTYPE FVALUE VALUE
    8947           0 :             return false;
    8948             :     }
    8949             : 
    8950           3 :     if (!emitPrepareIteratorResult())                     // ITER OLDRESULT FTYPE FVALUE VALUE RESULT
    8951           0 :         return false;
    8952           3 :     if (!emit1(JSOP_SWAP))                                // ITER OLDRESULT FTYPE FVALUE RESULT VALUE
    8953           0 :         return false;
    8954           3 :     if (!emitFinishIteratorResult(true))                  // ITER OLDRESULT FTYPE FVALUE RESULT
    8955           0 :         return false;
    8956           3 :     if (!emit1(JSOP_SETRVAL))                             // ITER OLDRESULT FTYPE FVALUE
    8957           0 :         return false;
    8958           3 :     savedDepthTemp = this->stackDepth;
    8959           3 :     if (!ifReturnDone.emitElse())                         // ITER OLDRESULT FTYPE FVALUE RESULT
    8960           0 :         return false;
    8961           3 :     if (!emit2(JSOP_UNPICK, 3))                           // ITER RESULT OLDRESULT FTYPE FVALUE
    8962           0 :         return false;
    8963           3 :     if (!emitPopN(3))                                     // ITER RESULT
    8964           0 :         return false;
    8965             :     {
    8966             :         // goto tryStart;
    8967           3 :         JumpList beq;
    8968           3 :         JumpTarget breakTarget{ -1 };
    8969           3 :         if (!emitBackwardJump(JSOP_GOTO, tryStart, &beq, &breakTarget)) // ITER RESULT
    8970           0 :             return false;
    8971             :     }
    8972           3 :     this->stackDepth = savedDepthTemp;
    8973           3 :     if (!ifReturnDone.emitEnd())
    8974           0 :         return false;
    8975             : 
    8976           3 :     if (!ifReturnMethodIsDefined.emitElse())              // ITER RESULT FTYPE FVALUE ITER RET
    8977           0 :         return false;
    8978           3 :     if (!emitPopN(2))                                     // ITER RESULT FTYPE FVALUE
    8979           0 :         return false;
    8980           3 :     if (!ifReturnMethodIsDefined.emitEnd())
    8981           0 :         return false;
    8982             : 
    8983           3 :     if (!ifGeneratorClosing.emitEnd())
    8984           0 :         return false;
    8985             : 
    8986           3 :     if (!tryCatch.emitEnd())
    8987           0 :         return false;
    8988             : 
    8989             :     // After the try-catch-finally block: send the received value to the iterator.
    8990             :     // result = iter.next(received)                              // ITER RECEIVED
    8991           3 :     if (!emit1(JSOP_SWAP))                                       // RECEIVED ITER
    8992           0 :         return false;
    8993           3 :     if (!emit1(JSOP_DUP))                                        // RECEIVED ITER ITER
    8994           0 :         return false;
    8995           3 :     if (!emit1(JSOP_DUP))                                        // RECEIVED ITER ITER ITER
    8996           0 :         return false;
    8997           3 :     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))            // RECEIVED ITER ITER NEXT
    8998           0 :         return false;
    8999           3 :     if (!emit1(JSOP_SWAP))                                       // RECEIVED ITER NEXT ITER
    9000           0 :         return false;
    9001           3 :     if (!emit2(JSOP_PICK, 3))                                    // ITER NEXT ITER RECEIVED
    9002           0 :         return false;
    9003           3 :     if (!emitCall(JSOP_CALL, 1, iter))                           // ITER RESULT
    9004           0 :         return false;
    9005           3 :     checkTypeSet(JSOP_CALL);
    9006             : 
    9007           3 :     if (isAsyncGenerator) {
    9008           0 :         if (!emitAwait())                                        // ITER RESULT RESULT
    9009           0 :             return false;
    9010             :     }
    9011             : 
    9012           3 :     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext))        // ITER RESULT
    9013           0 :         return false;
    9014           3 :     MOZ_ASSERT(this->stackDepth == startDepth);
    9015             : 
    9016           3 :     if (!emitJumpTargetAndPatch(checkResult))                    // checkResult:
    9017           0 :         return false;
    9018             : 
    9019             :     // if (!result.done) goto tryStart;                          // ITER RESULT
    9020           3 :     if (!emit1(JSOP_DUP))                                        // ITER RESULT RESULT
    9021           0 :         return false;
    9022           3 :     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))             // ITER RESULT DONE
    9023           0 :         return false;
    9024             :     // if (!DONE) goto tryStart;
    9025             :     {
    9026           3 :         JumpList beq;
    9027           3 :         JumpTarget breakTarget{ -1 };
    9028           3 :         if (!emitBackwardJump(JSOP_IFEQ, tryStart, &beq, &breakTarget)) // ITER RESULT
    9029           0 :             return false;
    9030             :     }
    9031             : 
    9032             :     // result.value
    9033           3 :     if (!emit1(JSOP_SWAP))                                       // RESULT ITER
    9034           0 :         return false;
    9035           3 :     if (!emit1(JSOP_POP))                                        // RESULT
    9036           0 :         return false;
    9037           3 :     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))            // VALUE
    9038           0 :         return false;
    9039             : 
    9040           3 :     if (isAsyncGenerator) {
    9041           0 :         if (!emitAwait())                                        // VALUE
    9042           0 :             return false;
    9043             :     }
    9044             : 
    9045           3 :     MOZ_ASSERT(this->stackDepth == startDepth - 1);
    9046             : 
    9047           3 :     return true;
    9048             : }
    9049             : 
    9050             : bool
    9051       12756 : BytecodeEmitter::emitStatementList(ParseNode* pn)
    9052             : {
    9053       12756 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9054       50148 :     for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
    9055       37390 :         if (!emitTree(pn2))
    9056           0 :             return false;
    9057             :     }
    9058       12758 :     return true;
    9059             : }
    9060             : 
    9061             : bool
    9062       14318 : BytecodeEmitter::emitStatement(ParseNode* pn)
    9063             : {
    9064       14318 :     MOZ_ASSERT(pn->isKind(PNK_SEMI));
    9065             : 
    9066       14318 :     ParseNode* pn2 = pn->pn_kid;
    9067       14318 :     if (!pn2)
    9068          11 :         return true;
    9069             : 
    9070       14307 :     if (!updateSourceCoordNotes(pn->pn_pos.begin))
    9071           0 :         return false;
    9072             : 
    9073             :     /*
    9074             :      * Top-level or called-from-a-native JS_Execute/EvaluateScript,
    9075             :      * debugger, and eval frames may need the value of the ultimate
    9076             :      * expression statement as the script's result, despite the fact
    9077             :      * that it appears useless to the compiler.
    9078             :      *
    9079             :      * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
    9080             :      * calling JS_Compile* to suppress JSOP_SETRVAL.
    9081             :      */
    9082       14307 :     bool wantval = false;
    9083       14307 :     bool useful = false;
    9084       14307 :     if (sc->isFunctionBox())
    9085       12413 :         MOZ_ASSERT(!script->noScriptRval());
    9086             :     else
    9087        1894 :         useful = wantval = !script->noScriptRval();
    9088             : 
    9089             :     /* Don't eliminate expressions with side effects. */
    9090       14307 :     if (!useful) {
    9091       14024 :         if (!checkSideEffects(pn2, &useful))
    9092           0 :             return false;
    9093             : 
    9094             :         /*
    9095             :          * Don't eliminate apparently useless expressions if they are labeled
    9096             :          * expression statements. The startOffset() test catches the case
    9097             :          * where we are nesting in emitTree for a labeled compound statement.
    9098             :          */
    9099       31746 :         if (innermostNestableControl &&
    9100       14024 :             innermostNestableControl->is<LabelControl>() &&
    9101           0 :             innermostNestableControl->as<LabelControl>().startOffset() >= offset())
    9102             :         {
    9103           0 :             useful = true;
    9104             :         }
    9105             :     }
    9106             : 
    9107       14307 :     if (useful) {
    9108       14200 :         JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
    9109       14200 :         ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
    9110       14200 :         MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
    9111       14200 :         if (!emitTree(pn2, valueUsage))
    9112           0 :             return false;
    9113       14200 :         if (!emit1(op))
    9114           0 :             return false;
    9115         107 :     } else if (pn->isDirectivePrologueMember()) {
    9116             :         // Don't complain about directive prologue members; just don't emit
    9117             :         // their code.
    9118             :     } else {
    9119           0 :         if (JSAtom* atom = pn->isStringExprStatement()) {
    9120             :             // Warn if encountering a non-directive prologue member string
    9121             :             // expression statement, that is inconsistent with the current
    9122             :             // directive prologue.  That is, a script *not* starting with
    9123             :             // "use strict" should warn for any "use strict" statements seen
    9124             :             // later in the script, because such statements are misleading.
    9125           0 :             const char* directive = nullptr;
    9126           0 :             if (atom == cx->names().useStrict) {
    9127           0 :                 if (!sc->strictScript)
    9128           0 :                     directive = js_useStrict_str;
    9129           0 :             } else if (atom == cx->names().useAsm) {
    9130           0 :                 if (sc->isFunctionBox()) {
    9131           0 :                     if (IsAsmJSModule(sc->asFunctionBox()->function()))
    9132           0 :                         directive = js_useAsm_str;
    9133             :                 }
    9134             :             }
    9135             : 
    9136           0 :             if (directive) {
    9137           0 :                 if (!reportExtraWarning(pn2, JSMSG_CONTRARY_NONDIRECTIVE, directive))
    9138           0 :                     return false;
    9139             :             }
    9140             :         } else {
    9141           0 :             if (!reportExtraWarning(pn2, JSMSG_USELESS_EXPR))
    9142           0 :                 return false;
    9143             :         }
    9144             :     }
    9145             : 
    9146       14307 :     return true;
    9147             : }
    9148             : 
    9149             : bool
    9150           0 : BytecodeEmitter::emitDeleteName(ParseNode* node)
    9151             : {
    9152           0 :     MOZ_ASSERT(node->isKind(PNK_DELETENAME));
    9153           0 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9154             : 
    9155           0 :     ParseNode* nameExpr = node->pn_kid;
    9156           0 :     MOZ_ASSERT(nameExpr->isKind(PNK_NAME));
    9157             : 
    9158           0 :     return emitAtomOp(nameExpr, JSOP_DELNAME);
    9159             : }
    9160             : 
    9161             : bool
    9162          52 : BytecodeEmitter::emitDeleteProperty(ParseNode* node)
    9163             : {
    9164          52 :     MOZ_ASSERT(node->isKind(PNK_DELETEPROP));
    9165          52 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9166             : 
    9167          52 :     ParseNode* propExpr = node->pn_kid;
    9168          52 :     MOZ_ASSERT(propExpr->isKind(PNK_DOT));
    9169             : 
    9170          52 :     if (propExpr->as<PropertyAccess>().isSuper()) {
    9171             :         // Still have to calculate the base, even though we are are going
    9172             :         // to throw unconditionally, as calculating the base could also
    9173             :         // throw.
    9174           0 :         if (!emit1(JSOP_SUPERBASE))
    9175           0 :             return false;
    9176             : 
    9177           0 :         return emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER);
    9178             :     }
    9179             : 
    9180          52 :     JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
    9181          52 :     return emitPropOp(propExpr, delOp);
    9182             : }
    9183             : 
    9184             : bool
    9185          30 : BytecodeEmitter::emitDeleteElement(ParseNode* node)
    9186             : {
    9187          30 :     MOZ_ASSERT(node->isKind(PNK_DELETEELEM));
    9188          30 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9189             : 
    9190          30 :     ParseNode* elemExpr = node->pn_kid;
    9191          30 :     MOZ_ASSERT(elemExpr->isKind(PNK_ELEM));
    9192             : 
    9193          30 :     if (elemExpr->as<PropertyByValue>().isSuper()) {
    9194             :         // Still have to calculate everything, even though we're gonna throw
    9195             :         // since it may have side effects
    9196           0 :         if (!emitTree(elemExpr->pn_right))
    9197           0 :             return false;
    9198             : 
    9199           0 :         if (!emit1(JSOP_SUPERBASE))
    9200           0 :             return false;
    9201           0 :         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER))
    9202           0 :             return false;
    9203             : 
    9204             :         // Another wrinkle: Balance the stack from the emitter's point of view.
    9205             :         // Execution will not reach here, as the last bytecode threw.
    9206           0 :         return emit1(JSOP_POP);
    9207             :     }
    9208             : 
    9209          30 :     JSOp delOp = sc->strict() ? JSOP_STRICTDELELEM : JSOP_DELELEM;
    9210          30 :     return emitElemOp(elemExpr, delOp);
    9211             : }
    9212             : 
    9213             : bool
    9214           0 : BytecodeEmitter::emitDeleteExpression(ParseNode* node)
    9215             : {
    9216           0 :     MOZ_ASSERT(node->isKind(PNK_DELETEEXPR));
    9217           0 :     MOZ_ASSERT(node->isArity(PN_UNARY));
    9218             : 
    9219           0 :     ParseNode* expression = node->pn_kid;
    9220             : 
    9221             :     // If useless, just emit JSOP_TRUE; otherwise convert |delete <expr>| to
    9222             :     // effectively |<expr>, true|.
    9223           0 :     bool useful = false;
    9224           0 :     if (!checkSideEffects(expression, &useful))
    9225           0 :         return false;
    9226             : 
    9227           0 :     if (useful) {
    9228           0 :         if (!emitTree(expression))
    9229           0 :             return false;
    9230           0 :         if (!emit1(JSOP_POP))
    9231           0 :             return false;
    9232             :     }
    9233             : 
    9234           0 :     return emit1(JSOP_TRUE);
    9235             : }
    9236             : 
    9237             : static const char *
    9238        1326 : SelfHostedCallFunctionName(JSAtom* name, JSContext* cx)
    9239             : {
    9240        1326 :     if (name == cx->names().callFunction)
    9241         978 :         return "callFunction";
    9242         348 :     if (name == cx->names().callContentFunction)
    9243         219 :         return "callContentFunction";
    9244         129 :     if (name == cx->names().constructContentFunction)
    9245         129 :         return "constructContentFunction";
    9246             : 
    9247           0 :     MOZ_CRASH("Unknown self-hosted call function name");
    9248             : }
    9249             : 
    9250             : bool
    9251        1326 : BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
    9252             : {
    9253             :     // Special-casing of callFunction to emit bytecode that directly
    9254             :     // invokes the callee with the correct |this| object and arguments.
    9255             :     // callFunction(fun, thisArg, arg0, arg1) thus becomes:
    9256             :     // - emit lookup for fun
    9257             :     // - emit lookup for thisArg
    9258             :     // - emit lookups for arg0, arg1
    9259             :     //
    9260             :     // argc is set to the amount of actually emitted args and the
    9261             :     // emitting of args below is disabled by setting emitArgs to false.
    9262        1326 :     ParseNode* pn2 = pn->pn_head;
    9263        1326 :     const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
    9264             : 
    9265        1326 :     if (pn->pn_count < 3) {
    9266           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
    9267           0 :         return false;
    9268             :     }
    9269             : 
    9270        1326 :     JSOp callOp = pn->getOp();
    9271        1326 :     if (callOp != JSOP_CALL) {
    9272           0 :         reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
    9273           0 :         return false;
    9274             :     }
    9275             : 
    9276        1326 :     bool constructing = pn2->name() == cx->names().constructContentFunction;
    9277        1326 :     ParseNode* funNode = pn2->pn_next;
    9278        1326 :     if (constructing)
    9279         129 :         callOp = JSOP_NEW;
    9280        1197 :     else if (funNode->getKind() == PNK_NAME && funNode->name() == cx->names().std_Function_apply)
    9281          60 :         callOp = JSOP_FUNAPPLY;
    9282             : 
    9283        1326 :     if (!emitTree(funNode))
    9284           0 :         return false;
    9285             : 
    9286             : #ifdef DEBUG
    9287        2652 :     if (emitterMode == BytecodeEmitter::SelfHosting &&
    9288        1326 :         pn2->name() == cx->names().callFunction)
    9289             :     {
    9290         978 :         if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
    9291           0 :             return false;
    9292             :     }
    9293             : #endif
    9294             : 
    9295        1326 :     ParseNode* thisOrNewTarget = funNode->pn_next;
    9296        1326 :     if (constructing) {
    9297             :         // Save off the new.target value, but here emit a proper |this| for a
    9298             :         // constructing call.
    9299         129 :         if (!emit1(JSOP_IS_CONSTRUCTING))
    9300           0 :             return false;
    9301             :     } else {
    9302             :         // It's |this|, emit it.
    9303        1197 :         if (!emitTree(thisOrNewTarget))
    9304           0 :             return false;
    9305             :     }
    9306             : 
    9307        4038 :     for (ParseNode* argpn = thisOrNewTarget->pn_next; argpn; argpn = argpn->pn_next) {
    9308        2712 :         if (!emitTree(argpn))
    9309           0 :             return false;
    9310             :     }
    9311             : 
    9312        1326 :     if (constructing) {
    9313         129 :         if (!emitTree(thisOrNewTarget))
    9314           0 :             return false;
    9315             :     }
    9316             : 
    9317        1326 :     uint32_t argc = pn->pn_count - 3;
    9318        1326 :     if (!emitCall(callOp, argc))
    9319           0 :         return false;
    9320             : 
    9321        1326 :     checkTypeSet(callOp);
    9322        1326 :     return true;
    9323             : }
    9324             : 
    9325             : bool
    9326          27 : BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
    9327             : {
    9328             :     // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close')
    9329          27 :     if (pn->pn_count != 4) {
    9330           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
    9331           0 :         return false;
    9332             :     }
    9333             : 
    9334          27 :     ParseNode* funNode = pn->pn_head;  // The resumeGenerator node.
    9335             : 
    9336          27 :     ParseNode* genNode = funNode->pn_next;
    9337          27 :     if (!emitTree(genNode))
    9338           0 :         return false;
    9339             : 
    9340          27 :     ParseNode* valNode = genNode->pn_next;
    9341          27 :     if (!emitTree(valNode))
    9342           0 :         return false;
    9343             : 
    9344          27 :     ParseNode* kindNode = valNode->pn_next;
    9345          27 :     MOZ_ASSERT(kindNode->isKind(PNK_STRING));
    9346          27 :     uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
    9347          27 :     MOZ_ASSERT(!kindNode->pn_next);
    9348             : 
    9349          27 :     if (!emitCall(JSOP_RESUME, operand))
    9350           0 :         return false;
    9351             : 
    9352          27 :     return true;
    9353             : }
    9354             : 
    9355             : bool
    9356           3 : BytecodeEmitter::emitSelfHostedForceInterpreter(ParseNode* pn)
    9357             : {
    9358           3 :     if (!emit1(JSOP_FORCEINTERPRETER))
    9359           0 :         return false;
    9360           3 :     if (!emit1(JSOP_UNDEFINED))
    9361           0 :         return false;
    9362           3 :     return true;
    9363             : }
    9364             : 
    9365             : bool
    9366          21 : BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn)
    9367             : {
    9368          21 :     if (pn->pn_count != 2) {
    9369           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", "");
    9370           0 :         return false;
    9371             :     }
    9372             : 
    9373             :     // We're just here as a sentinel. Pass the value through directly.
    9374          21 :     return emitTree(pn->pn_head->pn_next);
    9375             : }
    9376             : 
    9377             : bool
    9378         183 : BytecodeEmitter::emitSelfHostedDefineDataProperty(ParseNode* pn)
    9379             : {
    9380             :     // Only optimize when 3 arguments are passed (we use 4 to include |this|).
    9381         183 :     MOZ_ASSERT(pn->pn_count == 4);
    9382             : 
    9383         183 :     ParseNode* funNode = pn->pn_head;  // The _DefineDataProperty node.
    9384             : 
    9385         183 :     ParseNode* objNode = funNode->pn_next;
    9386         183 :     if (!emitTree(objNode))
    9387           0 :         return false;
    9388             : 
    9389         183 :     ParseNode* idNode = objNode->pn_next;
    9390         183 :     if (!emitTree(idNode))
    9391           0 :         return false;
    9392             : 
    9393         183 :     ParseNode* valNode = idNode->pn_next;
    9394         183 :     if (!emitTree(valNode))
    9395           0 :         return false;
    9396             : 
    9397             :     // This will leave the object on the stack instead of pushing |undefined|,
    9398             :     // but that's fine because the self-hosted code doesn't use the return
    9399             :     // value.
    9400         183 :     return emit1(JSOP_INITELEM);
    9401             : }
    9402             : 
    9403             : bool
    9404          51 : BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
    9405             : {
    9406          51 :     if (pn->pn_count != 3) {
    9407           0 :         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "hasOwn", "2", "");
    9408           0 :         return false;
    9409             :     }
    9410             : 
    9411          51 :     ParseNode* funNode = pn->pn_head;  // The hasOwn node.
    9412             : 
    9413          51 :     ParseNode* idNode = funNode->pn_next;
    9414          51 :     if (!emitTree(idNode))
    9415           0 :         return false;
    9416             : 
    9417          51 :     ParseNode* objNode = idNode->pn_next;
    9418          51 :     if (!emitTree(objNode))
    9419           0 :         return false;
    9420             : 
    9421          51 :     return emit1(JSOP_HASOWN);
    9422             : }
    9423             : 
    9424             : bool
    9425          31 : BytecodeEmitter::isRestParameter(ParseNode* pn)
    9426             : {
    9427          31 :     if (!sc->isFunctionBox())
    9428           0 :         return false;
    9429             : 
    9430          31 :     FunctionBox* funbox = sc->asFunctionBox();
    9431          62 :     RootedFunction fun(cx, funbox->function());
    9432          31 :     if (!funbox->hasRest())
    9433          13 :         return false;
    9434             : 
    9435          18 :     if (!pn->isKind(PNK_NAME)) {
    9436           3 :         if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) {
    9437           3 :             ParseNode* pn2 = pn->pn_head;
    9438           3 :             if (pn2->getKind() == PNK_NAME && pn2->name() == cx->names().allowContentIter)
    9439           3 :                 return isRestParameter(pn2->pn_next);
    9440             :         }
    9441           0 :         return false;
    9442             :     }
    9443             : 
    9444          15 :     JSAtom* name = pn->name();
    9445          30 :     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
    9446          15 :     if (paramLoc && lookupName(name) == *paramLoc) {
    9447          15 :         FunctionScope::Data* bindings = funbox->functionScopeBindings();
    9448          15 :         if (bindings->nonPositionalFormalStart > 0) {
    9449             :             // |paramName| can be nullptr when the rest destructuring syntax is
    9450             :             // used: `function f(...[]) {}`.
    9451          15 :             JSAtom* paramName = bindings->names[bindings->nonPositionalFormalStart - 1].name();
    9452          15 :             return paramName && name == paramName;
    9453             :         }
    9454             :     }
    9455             : 
    9456           0 :     return false;
    9457             : }
    9458             : 
    9459             : bool
    9460       22220 : BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9461             : {
    9462       22220 :     bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
    9463             :     /*
    9464             :      * Emit callable invocation or operator new (constructor call) code.
    9465             :      * First, emit code for the left operand to evaluate the callable or
    9466             :      * constructable object expression.
    9467             :      *
    9468             :      * For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
    9469             :      * This is necessary to interpose the lambda-initialized method read
    9470             :      * barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
    9471             :      * JSOP_{SET,INIT}PROP.
    9472             :      *
    9473             :      * Then (or in a call case that has no explicit reference-base
    9474             :      * object) we emit JSOP_UNDEFINED to produce the undefined |this|
    9475             :      * value required for calls (which non-strict mode functions
    9476             :      * will box into the global object).
    9477             :      */
    9478       22220 :     uint32_t argc = pn->pn_count - 1;
    9479             : 
    9480       22220 :     if (argc >= ARGC_LIMIT) {
    9481           0 :         parser.reportError(callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
    9482           0 :         return false;
    9483             :     }
    9484             : 
    9485       22220 :     ParseNode* pn2 = pn->pn_head;
    9486       22220 :     bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
    9487       22220 :     switch (pn2->getKind()) {
    9488             :       case PNK_NAME:
    9489       11039 :         if (emitterMode == BytecodeEmitter::SelfHosting && !spread) {
    9490             :             // Calls to "forceInterpreter", "callFunction",
    9491             :             // "callContentFunction", or "resumeGenerator" in self-hosted
    9492             :             // code generate inline bytecode.
    9493       25347 :             if (pn2->name() == cx->names().callFunction ||
    9494       16353 :                 pn2->name() == cx->names().callContentFunction ||
    9495        7578 :                 pn2->name() == cx->names().constructContentFunction)
    9496             :             {
    9497        1326 :                 return emitSelfHostedCallFunction(pn);
    9498             :             }
    9499        7449 :             if (pn2->name() == cx->names().resumeGenerator)
    9500          27 :                 return emitSelfHostedResumeGenerator(pn);
    9501        7422 :             if (pn2->name() == cx->names().forceInterpreter)
    9502           3 :                 return emitSelfHostedForceInterpreter(pn);
    9503        7419 :             if (pn2->name() == cx->names().allowContentIter)
    9504          21 :                 return emitSelfHostedAllowContentIter(pn);
    9505        7398 :             if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
    9506         183 :                 return emitSelfHostedDefineDataProperty(pn);
    9507        7215 :             if (pn2->name() == cx->names().hasOwn)
    9508          51 :                 return emitSelfHostedHasOwn(pn);
    9509             :             // Fall through.
    9510             :         }
    9511        9428 :         if (!emitGetName(pn2, callop))
    9512           0 :             return false;
    9513        9428 :         break;
    9514             :       case PNK_DOT:
    9515       11110 :         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
    9516       11110 :         if (pn2->as<PropertyAccess>().isSuper()) {
    9517          13 :             if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
    9518           0 :                 return false;
    9519             :         } else {
    9520       11097 :             if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
    9521           0 :                 return false;
    9522             :         }
    9523             : 
    9524       11111 :         break;
    9525             :       case PNK_ELEM:
    9526           8 :         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
    9527           8 :         if (pn2->as<PropertyByValue>().isSuper()) {
    9528           0 :             if (!emitSuperElemOp(pn2, JSOP_GETELEM_SUPER, /* isCall = */ callop))
    9529           0 :                 return false;
    9530             :         } else {
    9531           8 :             if (!emitElemOp(pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM))
    9532           0 :                 return false;
    9533           8 :             if (callop) {
    9534           8 :                 if (!emit1(JSOP_SWAP))
    9535           0 :                     return false;
    9536             :             }
    9537             :         }
    9538             : 
    9539           8 :         break;
    9540             :       case PNK_FUNCTION:
    9541             :         /*
    9542             :          * Top level lambdas which are immediately invoked should be
    9543             :          * treated as only running once. Every time they execute we will
    9544             :          * create new types and scripts for their contents, to increase
    9545             :          * the quality of type information within them and enable more
    9546             :          * backend optimizations. Note that this does not depend on the
    9547             :          * lambda being invoked at most once (it may be named or be
    9548             :          * accessed via foo.caller indirection), as multiple executions
    9549             :          * will just cause the inner scripts to be repeatedly cloned.
    9550             :          */
    9551          49 :         MOZ_ASSERT(!emittingRunOnceLambda);
    9552          49 :         if (checkRunOnceContext()) {
    9553          10 :             emittingRunOnceLambda = true;
    9554          10 :             if (!emitTree(pn2))
    9555           0 :                 return false;
    9556          10 :             emittingRunOnceLambda = false;
    9557             :         } else {
    9558          39 :             if (!emitTree(pn2))
    9559           0 :                 return false;
    9560             :         }
    9561          49 :         callop = false;
    9562          49 :         break;
    9563             :       case PNK_SUPERBASE:
    9564          13 :         MOZ_ASSERT(pn->isKind(PNK_SUPERCALL));
    9565          13 :         MOZ_ASSERT(parser.isSuperBase(pn2));
    9566          13 :         if (!emit1(JSOP_SUPERFUN))
    9567           0 :             return false;
    9568          13 :         break;
    9569             :       default:
    9570           1 :         if (!emitTree(pn2))
    9571           0 :             return false;
    9572           1 :         callop = false;             /* trigger JSOP_UNDEFINED after */
    9573           1 :         break;
    9574             :     }
    9575             : 
    9576       59858 :     bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
    9577       59848 :                    pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
    9578             : 
    9579             : 
    9580             :     // Emit room for |this|.
    9581       20610 :     if (!callop) {
    9582        1046 :         if (isNewOp) {
    9583         999 :             if (!emit1(JSOP_IS_CONSTRUCTING))
    9584           0 :                 return false;
    9585             :         } else {
    9586          47 :             if (!emit1(JSOP_UNDEFINED))
    9587           0 :                 return false;
    9588             :         }
    9589             :     }
    9590             : 
    9591             :     /*
    9592             :      * Emit code for each argument in order, then emit the JSOP_*CALL or
    9593             :      * JSOP_NEW bytecode with a two-byte immediate telling how many args
    9594             :      * were pushed on the operand stack.
    9595             :      */
    9596       20610 :     if (!spread) {
    9597       51265 :         for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
    9598       30702 :             if (!emitTree(pn3))
    9599           0 :                 return false;
    9600             :         }
    9601             : 
    9602       20563 :         if (isNewOp) {
    9603         996 :             if (pn->isKind(PNK_SUPERCALL)) {
    9604          10 :                 if (!emit1(JSOP_NEWTARGET))
    9605           0 :                     return false;
    9606             :             } else {
    9607             :                 // Repush the callee as new.target
    9608         986 :                 if (!emitDupAt(argc + 1))
    9609           0 :                     return false;
    9610             :             }
    9611             :         }
    9612             :     } else {
    9613          47 :         ParseNode* args = pn2->pn_next;
    9614          47 :         bool emitOptCode = (argc == 1) && isRestParameter(args->pn_kid);
    9615          94 :         IfThenElseEmitter ifNotOptimizable(this);
    9616             : 
    9617          47 :         if (emitOptCode) {
    9618             :             // Emit a preparation code to optimize the spread call with a rest
    9619             :             // parameter:
    9620             :             //
    9621             :             //   function f(...args) {
    9622             :             //     g(...args);
    9623             :             //   }
    9624             :             //
    9625             :             // If the spread operand is a rest parameter and it's optimizable
    9626             :             // array, skip spread operation and pass it directly to spread call
    9627             :             // operation.  See the comment in OptimizeSpreadCall in
    9628             :             // Interpreter.cpp for the optimizable conditons.
    9629             : 
    9630          15 :             if (!emitTree(args->pn_kid))
    9631           0 :                 return false;
    9632             : 
    9633          15 :             if (!emit1(JSOP_OPTIMIZE_SPREADCALL))
    9634           0 :                 return false;
    9635             : 
    9636          15 :             if (!emit1(JSOP_NOT))
    9637           0 :                 return false;
    9638             : 
    9639          15 :             if (!ifNotOptimizable.emitIf())
    9640           0 :                 return false;
    9641             : 
    9642          15 :             if (!emit1(JSOP_POP))
    9643           0 :                 return false;
    9644             :         }
    9645             : 
    9646          47 :         if (!emitArray(args, argc, JSOP_SPREADCALLARRAY))
    9647           0 :             return false;
    9648             : 
    9649          47 :         if (emitOptCode) {
    9650          15 :             if (!ifNotOptimizable.emitEnd())
    9651           0 :                 return false;
    9652             :         }
    9653             : 
    9654          47 :         if (isNewOp) {
    9655           3 :             if (pn->isKind(PNK_SUPERCALL)) {
    9656           3 :                 if (!emit1(JSOP_NEWTARGET))
    9657           0 :                     return false;
    9658             :             } else {
    9659           0 :                 if (!emitDupAt(2))
    9660           0 :                     return false;
    9661             :             }
    9662             :         }
    9663             :     }
    9664             : 
    9665       20610 :     if (!spread) {
    9666       20563 :         if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
    9667        7760 :             if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
    9668           0 :                 return false;
    9669        7760 :             checkTypeSet(JSOP_CALL_IGNORES_RV);
    9670             :         } else {
    9671       12803 :             if (!emitCall(pn->getOp(), argc, pn))
    9672           0 :                 return false;
    9673       12803 :             checkTypeSet(pn->getOp());
    9674             :         }
    9675             :     } else {
    9676          47 :         if (!emit1(pn->getOp()))
    9677           0 :             return false;
    9678          47 :         checkTypeSet(pn->getOp());
    9679             :     }
    9680       61828 :     if (pn->isOp(JSOP_EVAL) ||
    9681       41216 :         pn->isOp(JSOP_STRICTEVAL) ||
    9682       61826 :         pn->isOp(JSOP_SPREADEVAL) ||
    9683       20608 :         pn->isOp(JSOP_STRICTSPREADEVAL))
    9684             :     {
    9685           2 :         uint32_t lineNum = parser.tokenStream().srcCoords.lineNum(pn->pn_pos.begin);
    9686           2 :         if (!emitUint32Operand(JSOP_LINENO, lineNum))
    9687           0 :             return false;
    9688             :     }
    9689             : 
    9690       20610 :     return true;
    9691             : }
    9692             : 
    9693             : bool
    9694           0 : BytecodeEmitter::emitRightAssociative(ParseNode* pn)
    9695             : {
    9696             :     // ** is the only right-associative operator.
    9697           0 :     MOZ_ASSERT(pn->isKind(PNK_POW));
    9698           0 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9699             : 
    9700             :     // Right-associative operator chain.
    9701           0 :     for (ParseNode* subexpr = pn->pn_head; subexpr; subexpr = subexpr->pn_next) {
    9702           0 :         if (!emitTree(subexpr))
    9703           0 :             return false;
    9704             :     }
    9705           0 :     for (uint32_t i = 0; i < pn->pn_count - 1; i++) {
    9706           0 :         if (!emit1(JSOP_POW))
    9707           0 :             return false;
    9708             :     }
    9709           0 :     return true;
    9710             : }
    9711             : 
    9712             : bool
    9713        8175 : BytecodeEmitter::emitLeftAssociative(ParseNode* pn)
    9714             : {
    9715        8175 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9716             : 
    9717             :     // Left-associative operator chain.
    9718        8175 :     if (!emitTree(pn->pn_head))
    9719           0 :         return false;
    9720        8175 :     JSOp op = pn->getOp();
    9721        8175 :     ParseNode* nextExpr = pn->pn_head->pn_next;
    9722        8989 :     do {
    9723        8989 :         if (!emitTree(nextExpr))
    9724           0 :             return false;
    9725        8989 :         if (!emit1(op))
    9726           0 :             return false;
    9727        8989 :     } while ((nextExpr = nextExpr->pn_next));
    9728        8175 :     return true;
    9729             : }
    9730             : 
    9731             : bool
    9732        2022 : BytecodeEmitter::emitLogical(ParseNode* pn)
    9733             : {
    9734        2022 :     MOZ_ASSERT(pn->isArity(PN_LIST));
    9735             : 
    9736             :     /*
    9737             :      * JSOP_OR converts the operand on the stack to boolean, leaves the original
    9738             :      * value on the stack and jumps if true; otherwise it falls into the next
    9739             :      * bytecode, which pops the left operand and then evaluates the right operand.
    9740             :      * The jump goes around the right operand evaluation.
    9741             :      *
    9742             :      * JSOP_AND converts the operand on the stack to boolean and jumps if false;
    9743             :      * otherwise it falls into the right operand's bytecode.
    9744             :      */
    9745             : 
    9746        4045 :     TDZCheckCache tdzCache(this);
    9747             : 
    9748             :     /* Left-associative operator chain: avoid too much recursion. */
    9749        2022 :     ParseNode* pn2 = pn->pn_head;
    9750        2022 :     if (!emitTree(pn2))
    9751           0 :         return false;
    9752        2023 :     JSOp op = pn->getOp();
    9753        2023 :     JumpList jump;
    9754        2023 :     if (!emitJump(op, &jump))
    9755           0 :         return false;
    9756        2023 :     if (!emit1(JSOP_POP))
    9757           0 :         return false;
    9758             : 
    9759             :     /* Emit nodes between the head and the tail. */
    9760        2745 :     while ((pn2 = pn2->pn_next)->pn_next) {
    9761         361 :         if (!emitTree(pn2))
    9762           0 :             return false;
    9763         361 :         if (!emitJump(op, &jump))
    9764           0 :             return false;
    9765         361 :         if (!emit1(JSOP_POP))
    9766           0 :             return false;
    9767             :     }
    9768        2023 :     if (!emitTree(pn2))
    9769           0 :         return false;
    9770             : 
    9771        2023 :     if (!emitJumpTargetAndPatch(jump))
    9772           0 :         return false;
    9773        2023 :     return true;
    9774             : }
    9775             : 
    9776             : bool
    9777          10 : BytecodeEmitter::emitSequenceExpr(ParseNode* pn,
    9778             :                                   ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9779             : {
    9780          23 :     for (ParseNode* child = pn->pn_head; ; child = child->pn_next) {
    9781          36 :         if (!updateSourceCoordNotes(child->pn_pos.begin))
    9782           0 :             return false;
    9783          23 :         if (!emitTree(child, child->pn_next ? ValueUsage::IgnoreValue : valueUsage))
    9784           0 :             return false;
    9785          23 :         if (!child->pn_next)
    9786          10 :             break;
    9787          13 :         if (!emit1(JSOP_POP))
    9788           0 :             return false;
    9789             :     }
    9790          10 :     return true;
    9791             : }
    9792             : 
    9793             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    9794             : // the comment on emitSwitch.
    9795             : MOZ_NEVER_INLINE bool
    9796         705 : BytecodeEmitter::emitIncOrDec(ParseNode* pn)
    9797             : {
    9798         705 :     switch (pn->pn_kid->getKind()) {
    9799             :       case PNK_DOT:
    9800          19 :         return emitPropIncDec(pn);
    9801             :       case PNK_ELEM:
    9802          12 :         return emitElemIncDec(pn);
    9803             :       case PNK_CALL:
    9804           0 :         return emitCallIncDec(pn);
    9805             :       default:
    9806         674 :         return emitNameIncDec(pn);
    9807             :     }
    9808             : 
    9809             :     return true;
    9810             : }
    9811             : 
    9812             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
    9813             : // the comment on emitSwitch.
    9814             : MOZ_NEVER_INLINE bool
    9815           0 : BytecodeEmitter::emitLabeledStatement(const LabeledStatement* pn)
    9816             : {
    9817             :     /*
    9818             :      * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
    9819             :      * following the labeled statement.
    9820             :      */
    9821             :     uint32_t index;
    9822           0 :     if (!makeAtomIndex(pn->label(), &index))
    9823           0 :         return false;
    9824             : 
    9825           0 :     JumpList top;
    9826           0 :     if (!emitJump(JSOP_LABEL, &top))
    9827           0 :         return false;
    9828             : 
    9829             :     /* Emit code for the labeled statement. */
    9830           0 :     LabelControl controlInfo(this, pn->label(), offset());
    9831             : 
    9832           0 :     if (!emitTree(pn->statement()))
    9833           0 :         return false;
    9834             : 
    9835             :     /* Patch the JSOP_LABEL offset. */
    9836           0 :     JumpTarget brk{ lastNonJumpTargetOffset() };
    9837           0 :     patchJumpsToTarget(top, brk);
    9838             : 
    9839           0 :     if (!controlInfo.patchBreaks(this))
    9840           0 :         return false;
    9841             : 
    9842           0 :     return true;
    9843             : }
    9844             : 
    9845             : bool
    9846         657 : BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional,
    9847             :                                            ValueUsage valueUsage /* = ValueUsage::WantValue */)
    9848             : {
    9849             :     /* Emit the condition, then branch if false to the else part. */
    9850         657 :     if (!emitTree(&conditional.condition()))
    9851           0 :         return false;
    9852             : 
    9853        1314 :     IfThenElseEmitter ifThenElse(this);
    9854         657 :     if (!ifThenElse.emitCond())
    9855           0 :         return false;
    9856             : 
    9857         657 :     if (!emitTreeInBranch(&conditional.thenExpression(), valueUsage))
    9858           0 :         return false;
    9859             : 
    9860         657 :     if (!ifThenElse.emitElse())
    9861           0 :         return false;
    9862             : 
    9863         657 :     if (!emitTreeInBranch(&conditional.elseExpression(), valueUsage))
    9864           0 :         return false;
    9865             : 
    9866         657 :     if (!ifThenElse.emitEnd())
    9867           0 :         return false;
    9868         657 :     MOZ_ASSERT(ifThenElse.pushed() == 1);
    9869             : 
    9870         657 :     return true;
    9871             : }
    9872             : 
    9873             : bool
    9874        1672 : BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type)
    9875             : {
    9876        7891 :     for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
    9877        6218 :         if (!updateSourceCoordNotes(propdef->pn_pos.begin))
    9878           0 :             return false;
    9879             : 
    9880             :         // Handle __proto__: v specially because *only* this form, and no other
    9881             :         // involving "__proto__", performs [[Prototype]] mutation.
    9882        6218 :         if (propdef->isKind(PNK_MUTATEPROTO)) {
    9883          38 :             MOZ_ASSERT(type == ObjectLiteral);
    9884          38 :             if (!emitTree(propdef->pn_kid))
    9885           0 :                 return false;
    9886          38 :             objp.set(nullptr);
    9887          38 :             if (!emit1(JSOP_MUTATEPROTO))
    9888           0 :                 return false;
    9889          38 :             continue;
    9890             :         }
    9891             : 
    9892        6180 :         if (propdef->isKind(PNK_SPREAD)) {
    9893           0 :             MOZ_ASSERT(type == ObjectLiteral);
    9894             : 
    9895           0 :             if (!emit1(JSOP_DUP))
    9896           0 :                 return false;
    9897             : 
    9898           0 :             if (!emitTree(propdef->pn_kid))
    9899           0 :                 return false;
    9900             : 
    9901           0 :             if (!emitCopyDataProperties(CopyOption::Unfiltered))
    9902           0 :                 return false;
    9903             : 
    9904           0 :             objp.set(nullptr);
    9905           0 :             continue;
    9906             :         }
    9907             : 
    9908        6180 :         bool extraPop = false;
    9909        6180 :         if (type == ClassBody && propdef->as<ClassMethod>().isStatic()) {
    9910           4 :             extraPop = true;
    9911           4 :             if (!emit1(JSOP_DUP2))
    9912           0 :                 return false;
    9913           4 :             if (!emit1(JSOP_POP))
    9914           0 :                 return false;
    9915             :         }
    9916             : 
    9917             :         /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
    9918        6180 :         ParseNode* key = propdef->pn_left;
    9919        6180 :         bool isIndex = false;
    9920        6180 :         if (key->isKind(PNK_NUMBER)) {
    9921          26 :             if (!emitNumberOp(key->pn_dval))
    9922           0 :                 return false;
    9923          26 :             isIndex = true;
    9924        6154 :         } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
    9925             :             // EmitClass took care of constructor already.
    9926        6180 :             if (type == ClassBody && key->pn_atom == cx->names().constructor &&
    9927          31 :                 !propdef->as<ClassMethod>().isStatic())
    9928             :             {
    9929          31 :                 continue;
    9930             :             }
    9931             :         } else {
    9932           5 :             if (!emitComputedPropertyName(key))
    9933           0 :                 return false;
    9934           5 :             isIndex = true;
    9935             :         }
    9936             : 
    9937             :         /* Emit code for the property initializer. */
    9938        6149 :         if (!emitTree(propdef->pn_right))
    9939           0 :             return false;
    9940             : 
    9941        6150 :         JSOp op = propdef->getOp();
    9942        6150 :         MOZ_ASSERT(op == JSOP_INITPROP ||
    9943             :                    op == JSOP_INITPROP_GETTER ||
    9944             :                    op == JSOP_INITPROP_SETTER);
    9945             : 
    9946       11992 :         FunctionPrefixKind prefixKind = op == JSOP_INITPROP_GETTER ? FunctionPrefixKind::Get
    9947        5842 :                                         : op == JSOP_INITPROP_SETTER ? FunctionPrefixKind::Set
    9948        6150 :                                         : FunctionPrefixKind::None;
    9949             : 
    9950        6150 :         if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
    9951         350 :             objp.set(nullptr);
    9952             : 
    9953        8975 :         if (propdef->pn_right->isKind(PNK_FUNCTION) &&
    9954        2825 :             propdef->pn_right->pn_funbox->needsHomeObject())
    9955             :         {
    9956           7 :             MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty());
    9957           7 :             bool isAsync = propdef->pn_right->pn_funbox->isAsync();
    9958           7 :             if (isAsync) {
    9959           0 :                 if (!emit1(JSOP_SWAP))
    9960           0 :                     return false;
    9961             :             }
    9962           7 :             if (!emit2(JSOP_INITHOMEOBJECT, isIndex + isAsync))
    9963           0 :                 return false;
    9964           7 :             if (isAsync) {
    9965           0 :                 if (!emit1(JSOP_POP))
    9966           0 :                     return false;
    9967             :             }
    9968             :         }
    9969             : 
    9970             :         // Class methods are not enumerable.
    9971        6150 :         if (type == ClassBody) {
    9972         125 :             switch (op) {
    9973         111 :               case JSOP_INITPROP:        op = JSOP_INITHIDDENPROP;          break;
    9974          13 :               case JSOP_INITPROP_GETTER: op = JSOP_INITHIDDENPROP_GETTER;   break;
    9975           1 :               case JSOP_INITPROP_SETTER: op = JSOP_INITHIDDENPROP_SETTER;   break;
    9976           0 :               default: MOZ_CRASH("Invalid op");
    9977             :             }
    9978             :         }
    9979             : 
    9980        6150 :         if (isIndex) {
    9981          31 :             objp.set(nullptr);
    9982          31 :             switch (op) {
    9983          31 :               case JSOP_INITPROP:               op = JSOP_INITELEM;              break;
    9984           0 :               case JSOP_INITHIDDENPROP:         op = JSOP_INITHIDDENELEM;        break;
    9985           0 :               case JSOP_INITPROP_GETTER:        op = JSOP_INITELEM_GETTER;       break;
    9986           0 :               case JSOP_INITHIDDENPROP_GETTER:  op = JSOP_INITHIDDENELEM_GETTER; break;
    9987           0 :               case JSOP_INITPROP_SETTER:        op = JSOP_INITELEM_SETTER;       break;
    9988           0 :               case JSOP_INITHIDDENPROP_SETTER:  op = JSOP_INITHIDDENELEM_SETTER; break;
    9989           0 :               default: MOZ_CRASH("Invalid op");
    9990             :             }
    9991          31 :             if (propdef->pn_right->isDirectRHSAnonFunction()) {
    9992           0 :                 if (!emitDupAt(1))
    9993           0 :                     return false;
    9994           0 :                 if (!emit2(JSOP_SETFUNNAME, uint8_t(prefixKind)))
    9995           0 :                     return false;
    9996             :             }
    9997          31 :             if (!emit1(op))
    9998           0 :                 return false;
    9999             :         } else {
   10000        6119 :             MOZ_ASSERT(key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING));
   10001             : 
   10002             :             uint32_t index;
   10003        6119 :             if (!makeAtomIndex(key->pn_atom, &index))
   10004           0 :                 return false;
   10005             : 
   10006        6119 :             if (objp) {
   10007        4600 :                 MOZ_ASSERT(type == ObjectLiteral);
   10008        4600 :                 MOZ_ASSERT(!IsHiddenInitOp(op));
   10009        4600 :                 MOZ_ASSERT(!objp->inDictionaryMode());
   10010        9200 :                 Rooted<jsid> id(cx, AtomToId(key->pn_atom));
   10011        4600 :                 if (!NativeDefineProperty(cx, objp, id, UndefinedHandleValue, nullptr, nullptr,
   10012             :                                           JSPROP_ENUMERATE))
   10013             :                 {
   10014           0 :                     return false;
   10015             :                 }
   10016        4600 :                 if (objp->inDictionaryMode())
   10017           0 :                     objp.set(nullptr);
   10018             :             }
   10019             : 
   10020        6119 :             if (propdef->pn_right->isDirectRHSAnonFunction()) {
   10021         510 :                 RootedAtom keyName(cx, key->pn_atom);
   10022         255 :                 if (!setOrEmitSetFunName(propdef->pn_right, keyName, prefixKind))
   10023           0 :                     return false;
   10024             :             }
   10025        6119 :             if (!emitIndex32(op, index))
   10026           0 :                 return false;
   10027             :         }
   10028             : 
   10029        6150 :         if (extraPop) {
   10030           4 :             if (!emit1(JSOP_POP))
   10031           0 :                 return false;
   10032             :         }
   10033             :     }
   10034        1673 :     return true;
   10035             : }
   10036             : 
   10037             : // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
   10038             : // the comment on emitSwitch.
   10039             : MOZ_NEVER_INLINE bool
   10040        1669 : BytecodeEmitter::emitObject(ParseNode* pn)
   10041             : {
   10042        1669 :     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && checkSingletonContext())
   10043          29 :         return emitSingletonInitialiser(pn);
   10044             : 
   10045             :     /*
   10046             :      * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
   10047             :      * a new object and defining (in source order) each property on the object
   10048             :      * (or mutating the object's [[Prototype]], in the case of __proto__).
   10049             :      */
   10050        1640 :     ptrdiff_t offset = this->offset();
   10051        1640 :     if (!emitNewInit(JSProto_Object))
   10052           0 :         return false;
   10053             : 
   10054             :     // Try to construct the shape of the object as we go, so we can emit a
   10055             :     // JSOP_NEWOBJECT with the final shape instead.
   10056             :     // In the case of computed property names and indices, we cannot fix the
   10057             :     // shape at bytecode compile time. When the shape cannot be determined,
   10058             :     // |obj| is nulled out.
   10059             : 
   10060             :     // No need to do any guessing for the object kind, since we know the upper
   10061             :     // bound of how many properties we plan to have.
   10062        1640 :     gc::AllocKind kind = gc::GetGCObjectKind(pn->pn_count);
   10063        3281 :     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
   10064        1640 :     if (!obj)
   10065           0 :         return false;
   10066             : 
   10067        1640 :     if (!emitPropertyList(pn, &obj, ObjectLiteral))
   10068           0 :         return false;
   10069             : 
   10070        1641 :     if (obj) {
   10071             :         // The object survived and has a predictable shape: update the original
   10072             :         // bytecode.
   10073        1487 :         if (!replaceNewInitWithNewObject(obj, offset))
   10074           0 :             return false;
   10075             :     }
   10076             : 
   10077        1641 :     return true;
   10078             : }
   10079             : 
   10080             : bool
   10081        1487 : BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
   10082             : {
   10083        1487 :     ObjectBox* objbox = parser.newObjectBox(obj);
   10084        1487 :     if (!objbox)
   10085           0 :         return false;
   10086             : 
   10087             :     static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
   10088             :                   "newinit and newobject must have equal length to edit in-place");
   10089             : 
   10090        1487 :     uint32_t index = objectList.add(objbox);
   10091        1487 :     jsbytecode* code = this->code(offset);
   10092             : 
   10093        1487 :     MOZ_ASSERT(code[0] == JSOP_NEWINIT);
   10094        1487 :     code[0] = JSOP_NEWOBJECT;
   10095        1487 :     code[1] = jsbytecode(index >> 24);
   10096        1487 :     code[2] = jsbytecode(index >> 16);
   10097        1487 :     code[3] = jsbytecode(index >> 8);
   10098        1487 :     code[4] = jsbytecode(index);
   10099             : 
   10100        1487 :     return true;
   10101             : }
   10102             : 
   10103             : bool
   10104           0 : BytecodeEmitter::emitArrayComp(ParseNode* pn)
   10105             : {
   10106           0 :     if (!emitNewInit(JSProto_Array))
   10107           0 :         return false;
   10108             : 
   10109             :     /*
   10110             :      * Pass the new array's stack index to the PNK_ARRAYPUSH case via
   10111             :      * arrayCompDepth, then simply traverse the PNK_FOR node and
   10112             :      * its kids under pn2 to generate this comprehension.
   10113             :      */
   10114           0 :     MOZ_ASSERT(stackDepth > 0);
   10115           0 :     uint32_t saveDepth = arrayCompDepth;
   10116           0 :     arrayCompDepth = (uint32_t) (stackDepth - 1);
   10117           0 :     if (!emitTree(pn->pn_head))
   10118           0 :         return false;
   10119           0 :     arrayCompDepth = saveDepth;
   10120             : 
   10121           0 :     return true;
   10122             : }
   10123             : 
   10124             : bool
   10125        1212 : BytecodeEmitter::emitArrayLiteral(ParseNode* pn)
   10126             : {
   10127        1212 :     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head) {
   10128         557 :         if (checkSingletonContext()) {
   10129             :             // Bake in the object entirely if it will only be created once.
   10130          12 :             return emitSingletonInitialiser(pn);
   10131             :         }
   10132             : 
   10133             :         // If the array consists entirely of primitive values, make a
   10134             :         // template object with copy on write elements that can be reused
   10135             :         // every time the initializer executes.
   10136         545 :         if (emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
   10137         459 :             RootedValue value(cx);
   10138         452 :             if (!pn->getConstantValue(cx, ParseNode::ForCopyOnWriteArray, &value))
   10139           0 :                 return false;
   10140         453 :             if (!value.isMagic(JS_GENERIC_MAGIC)) {
   10141             :                 // Note: the group of the template object might not yet reflect
   10142             :                 // that the object has copy on write elements. When the
   10143             :                 // interpreter or JIT compiler fetches the template, it should
   10144             :                 // use ObjectGroup::getOrFixupCopyOnWriteObject to make sure the
   10145             :                 // group for the template is accurate. We don't do this here as we
   10146             :                 // want to use ObjectGroup::allocationSiteGroup, which requires a
   10147             :                 // finished script.
   10148         446 :                 JSObject* obj = &value.toObject();
   10149         446 :                 MOZ_ASSERT(obj->is<ArrayObject>() &&
   10150             :                            obj->as<ArrayObject>().denseElementsAreCopyOnWrite());
   10151             : 
   10152         446 :                 ObjectBox* objbox = parser.newObjectBox(obj);
   10153         446 :                 if (!objbox)
   10154           0 :                     return false;
   10155             : 
   10156         446 :                 return emitObjectOp(objbox, JSOP_NEWARRAY_COPYONWRITE);
   10157             :             }
   10158             :         }
   10159             :     }
   10160             : 
   10161         755 :     return emitArray(pn->pn_head, pn->pn_count, JSOP_NEWARRAY);
   10162             : }
   10163             : 
   10164             : bool
   10165         802 : BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
   10166             : {
   10167             : 
   10168             :     /*
   10169             :      * Emit code for [a, b, c] that is equivalent to constructing a new
   10170             :      * array and in source order evaluating each element value and adding
   10171             :      * it to the array, without invoking latent setters.  We use the
   10172             :      * JSOP_NEWINIT and JSOP_INITELEM_ARRAY bytecodes to ignore setters and
   10173             :      * to avoid dup'ing and popping the array as each element is added, as
   10174             :      * JSOP_SETELEM/JSOP_SETPROP would do.
   10175             :      */
   10176         802 :     MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
   10177             : 
   10178         802 :     uint32_t nspread = 0;
   10179        2182 :     for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
   10180        1380 :         if (elt->isKind(PNK_SPREAD))
   10181          58 :             nspread++;
   10182             :     }
   10183             : 
   10184             :     // Array literal's length is limited to NELEMENTS_LIMIT in parser.
   10185             :     static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
   10186             :                   "array literals' maximum length must not exceed limits "
   10187             :                   "required by BaselineCompiler::emit_JSOP_NEWARRAY, "
   10188             :                   "BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
   10189             :                   "and DoSetElemFallback's handling of JSOP_INITELEM_ARRAY");
   10190         802 :     MOZ_ASSERT(count >= nspread);
   10191         802 :     MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,
   10192             :                "the parser must throw an error if the array exceeds maximum "
   10193             :                "length");
   10194             : 
   10195             :     // For arrays with spread, this is a very pessimistic allocation, the
   10196             :     // minimum possible final size.
   10197         802 :     if (!emitUint32Operand(op, count - nspread))                    // ARRAY
   10198           0 :         return false;
   10199             : 
   10200         802 :     ParseNode* pn2 = pn;
   10201             :     uint32_t index;
   10202         802 :     bool afterSpread = false;
   10203        2182 :     for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
   10204        1380 :         if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
   10205          56 :             afterSpread = true;
   10206          56 :             if (!emitNumberOp(index))                               // ARRAY INDEX
   10207           0 :                 return false;
   10208             :         }
   10209        1380 :         if (!updateSourceCoordNotes(pn2->pn_pos.begin))
   10210           0 :             return false;
   10211             : 
   10212        1380 :         bool allowSelfHostedIter = false;
   10213        1380 :         if (pn2->isKind(PNK_ELISION)) {
   10214           0 :             if (!emit1(JSOP_HOLE))
   10215           0 :                 return false;
   10216             :         } else {
   10217             :             ParseNode* expr;
   10218        1380 :             if (pn2->isKind(PNK_SPREAD)) {
   10219          58 :                 expr = pn2->pn_kid;
   10220             : 
   10221         119 :                 if (emitterMode == BytecodeEmitter::SelfHosting &&
   10222          61 :                     expr->isKind(PNK_CALL) &&
   10223           3 :                     expr->pn_head->name() == cx->names().allowContentIter)
   10224             :                 {
   10225           3 :                     allowSelfHostedIter = true;
   10226             :                 }
   10227             :             } else {
   10228        1322 :                 expr = pn2;
   10229             :             }
   10230        1380 :             if (!emitTree(expr))                                         // ARRAY INDEX? VALUE
   10231           0 :                 return false;
   10232             :         }
   10233        1380 :         if (pn2->isKind(PNK_SPREAD)) {
   10234          58 :             if (!emitIterator())                                         // ARRAY INDEX ITER
   10235           0 :                 return false;
   10236          58 :             if (!emit2(JSOP_PICK, 2))                                    // INDEX ITER ARRAY
   10237           0 :                 return false;
   10238          58 :             if (!emit2(JSOP_PICK, 2))                                    // ITER ARRAY INDEX
   10239           0 :                 return false;
   10240          58 :             if (!emitSpread(allowSelfHostedIter))                        // ARRAY INDEX
   10241           0 :                 return false;
   10242        1322 :         } else if (afterSpread) {
   10243           2 :             if (!emit1(JSOP_INITELEM_INC))
   10244           0 :                 return false;
   10245             :         } else {
   10246        1320 :             if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index))
   10247           0 :                 return false;
   10248             :         }
   10249             :     }
   10250         802 :     MOZ_ASSERT(index == count);
   10251         802 :     if (afterSpread) {
   10252          56 :         if (!emit1(JSOP_POP))                                            // ARRAY
   10253           0 :             return false;
   10254             :     }
   10255         802 :     return true;
   10256             : }
   10257             : 
   10258             : bool
   10259        3393 : BytecodeEmitter::emitUnary(ParseNode* pn)
   10260             : {
   10261        3393 :     if (!updateSourceCoordNotes(pn->pn_pos.begin))
   10262           0 :         return false;
   10263             : 
   10264             :     /* Unary op, including unary +/-. */
   10265        3393 :     JSOp op = pn->getOp();
   10266        3393 :     ParseNode* pn2 = pn->pn_kid;
   10267             : 
   10268        3393 :     if (!emitTree(pn2))
   10269           0 :         return false;
   10270             : 
   10271        3394 :     return emit1(op);
   10272             : }
   10273             : 
   10274             : bool
   10275         502 : BytecodeEmitter::emitTypeof(ParseNode* node, JSOp op)
   10276             : {
   10277         502 :     MOZ_ASSERT(op == JSOP_TYPEOF || op == JSOP_TYPEOFEXPR);
   10278             : 
   10279         502 :     if (!updateSourceCoordNotes(node->pn_pos.begin))
   10280           0 :         return false;
   10281             : 
   10282         502 :     if (!emitTree(node->pn_kid))
   10283           0 :         return false;
   10284             : 
   10285         502 :     return emit1(op);
   10286             : }
   10287             : 
   10288             : bool
   10289        5404 : BytecodeEmitter::emitFunctionFormalParametersAndBody(ParseNode *pn)
   10290             : {
   10291        5404 :     MOZ_ASSERT(pn->isKind(PNK_PARAMSBODY));
   10292             : 
   10293        5404 :     ParseNode* funBody = pn->last();
   10294        5404 :     FunctionBox* funbox = sc->asFunctionBox();
   10295             : 
   10296       10809 :     TDZCheckCache tdzCache(this);
   10297             : 
   10298        5404 :     if (funbox->hasParameterExprs) {
   10299         366 :         EmitterScope funEmitterScope(this);
   10300         183 :         if (!funEmitterScope.enterFunction(this, funbox))
   10301           0 :             return false;
   10302             : 
   10303         183 :         if (!emitInitializeFunctionSpecialNames())
   10304           0 :             return false;
   10305             : 
   10306         183 :         if (!emitFunctionFormalParameters(pn))
   10307           0 :             return false;
   10308             : 
   10309             :         {
   10310         366 :             Maybe<EmitterScope> extraVarEmitterScope;
   10311             : 
   10312         183 :             if (funbox->hasExtraBodyVarScope()) {
   10313         104 :                 extraVarEmitterScope.emplace(this);
   10314         104 :                 if (!extraVarEmitterScope->enterFunctionExtraBodyVar(this, funbox))
   10315           0 :                     return false;
   10316             : 
   10317             :                 // After emitting expressions for all parameters, copy over any
   10318             :                 // formal parameters which have been redeclared as vars. For
   10319             :                 // example, in the following, the var y in the body scope is 42:
   10320             :                 //
   10321             :                 //   function f(x, y = 42) { var y; }
   10322             :                 //
   10323         208 :                 RootedAtom name(cx);
   10324         104 :                 if (funbox->extraVarScopeBindings() && funbox->functionScopeBindings()) {
   10325         445 :                     for (BindingIter bi(*funbox->functionScopeBindings(), true); bi; bi++) {
   10326         341 :                         name = bi.name();
   10327             : 
   10328             :                         // There may not be a var binding of the same name.
   10329         341 :                         if (!locationOfNameBoundInScope(name, extraVarEmitterScope.ptr()))
   10330         341 :                             continue;
   10331             : 
   10332             :                         // The '.this' and '.generator' function special
   10333             :                         // bindings should never appear in the extra var
   10334             :                         // scope. 'arguments', however, may.
   10335           0 :                         MOZ_ASSERT(name != cx->names().dotThis &&
   10336             :                                    name != cx->names().dotGenerator);
   10337             : 
   10338           0 :                         NameLocation paramLoc = *locationOfNameBoundInScope(name, &funEmitterScope);
   10339             :                         auto emitRhs = [&name, &paramLoc](BytecodeEmitter* bce,
   10340           0 :                                                           const NameLocation&, bool)
   10341           0 :                         {
   10342           0 :                             return bce->emitGetNameAtLocation(name, paramLoc);
   10343           0 :                         };
   10344             : 
   10345           0 :                         if (!emitInitializeName(name, emitRhs))
   10346           0 :                             return false;
   10347           0 :                         if (!emit1(JSOP_POP))
   10348           0 :                             return false;
   10349             :                     }
   10350             :                 }
   10351             :             }
   10352             : 
   10353         183 :             if (!emitFunctionBody(funBody))
   10354           0 :                 return false;
   10355             : 
   10356         183 :             if (extraVarEmitterScope && !extraVarEmitterScope->leave(this))
   10357           0 :                 return false;
   10358             :         }
   10359             : 
   10360         183 :         return funEmitterScope.leave(this);
   10361             :     }
   10362             : 
   10363             :     // No parameter expressions. Enter the function body scope and emit
   10364             :     // everything.
   10365             :     //
   10366             :     // One caveat is that Debugger considers ops in the prologue to be
   10367             :     // unreachable (i.e. cannot set a breakpoint on it). If there are no
   10368             :     // parameter exprs, any unobservable environment ops (like pushing the
   10369             :     // call object, setting '.this', etc) need to go in the prologue, else it
   10370             :     // messes up breakpoint tests.
   10371       10443 :     EmitterScope emitterScope(this);
   10372             : 
   10373        5221 :     switchToPrologue();
   10374        5221 :     if (!emitterScope.enterFunction(this, funbox))
   10375           0 :         return false;
   10376             : 
   10377        5221 :     if (!emitInitializeFunctionSpecialNames())
   10378           0 :         return false;
   10379        5221 :     switchToMain();
   10380             : 
   10381        5221 :     if (!emitFunctionFormalParameters(pn))
   10382           0 :         return false;
   10383             : 
   10384        5221 :     if (!emitFunctionBody(funBody))
   10385           0 :         return false;
   10386             : 
   10387        5222 :     return emitterScope.leave(this);
   10388             : }
   10389             : 
   10390             : bool
   10391        5404 : BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
   10392             : {
   10393        5404 :     ParseNode* funBody = pn->last();
   10394        5404 :     FunctionBox* funbox = sc->asFunctionBox();
   10395        5404 :     EmitterScope* funScope = innermostEmitterScope;
   10396             : 
   10397        5404 :     bool hasParameterExprs = funbox->hasParameterExprs;
   10398        5404 :     bool hasRest = funbox->hasRest();
   10399             : 
   10400        5404 :     uint16_t argSlot = 0;
   10401       11799 :     for (ParseNode* arg = pn->pn_head; arg != funBody; arg = arg->pn_next, argSlot++) {
   10402        6395 :         ParseNode* bindingElement = arg;
   10403        6395 :         ParseNode* initializer = nullptr;
   10404        6395 :         if (arg->isKind(PNK_ASSIGN)) {
   10405         213 :             bindingElement = arg->pn_left;
   10406         213 :             initializer = arg->pn_right;
   10407             :         }
   10408             : 
   10409             :         // Left-hand sides are either simple names or destructuring patterns.
   10410        6395 :         MOZ_ASSERT(bindingElement->isKind(PNK_NAME) ||
   10411             :                    bindingElement->isKind(PNK_ARRAY) ||
   10412             :                    bindingElement->isKind(PNK_ARRAYCOMP) ||
   10413             :                    bindingElement->isKind(PNK_OBJECT));
   10414             : 
   10415             :         // The rest parameter doesn't have an initializer.
   10416        6395 :         bool isRest = hasRest && arg->pn_next == funBody;
   10417        6395 :         MOZ_ASSERT_IF(isRest, !initializer);
   10418             : 
   10419        6395 :         bool isDestructuring = !bindingElement->isKind(PNK_NAME);
   10420             : 
   10421             :         // ES 14.1.19 says if BindingElement contains an expression in the
   10422             :         // production FormalParameter : BindingElement, it is evaluated in a
   10423             :         // new var environment. This is needed to prevent vars from escaping
   10424             :         // direct eval in parameter expressions.
   10425       12790 :         Maybe<EmitterScope> paramExprVarScope;
   10426        6395 :         if (funbox->hasDirectEvalInParameterExpr && (isDestructuring || initializer)) {
   10427           0 :             paramExprVarScope.emplace(this);
   10428           0 :             if (!paramExprVarScope->enterParameterExpressionVar(this))
   10429           0 :                 return false;
   10430             :         }
   10431             : 
   10432             :         // First push the RHS if there is a default expression or if it is
   10433             :         // rest.
   10434             : 
   10435        6395 :         if (initializer) {
   10436             :             // If we have an initializer, emit the initializer and assign it
   10437             :             // to the argument slot. TDZ is taken care of afterwards.
   10438         213 :             MOZ_ASSERT(hasParameterExprs);
   10439         213 :             if (!emitArgOp(JSOP_GETARG, argSlot))
   10440           0 :                 return false;
   10441         213 :             if (!emit1(JSOP_DUP))
   10442           0 :                 return false;
   10443         213 :             if (!emit1(JSOP_UNDEFINED))
   10444           0 :                 return false;
   10445         213 :             if (!emit1(JSOP_STRICTEQ))
   10446           0 :                 return false;
   10447             :             // Emit source note to enable Ion compilation.
   10448         213 :             if (!newSrcNote(SRC_IF))
   10449           0 :                 return false;
   10450         213 :             JumpList jump;
   10451         213 :             if (!emitJump(JSOP_IFEQ, &jump))
   10452           0 :                 return false;
   10453         213 :             if (!emit1(JSOP_POP))
   10454           0 :                 return false;
   10455         213 :             if (!emitInitializerInBranch(initializer, bindingElement))
   10456           0 :                 return false;
   10457         213 :             if (!emitJumpTargetAndPatch(jump))
   10458           0 :                 return false;
   10459        6182 :         } else if (isRest) {
   10460          62 :             if (!emit1(JSOP_REST))
   10461           0 :                 return false;
   10462          62 :             checkTypeSet(JSOP_REST);
   10463             :         }
   10464             : 
   10465             :         // Initialize the parameter name.
   10466             : 
   10467        6395 :         if (isDestructuring) {
   10468             :             // If we had an initializer or the rest parameter, the value is
   10469             :             // already on the stack.
   10470          42 :             if (!initializer && !isRest && !emitArgOp(JSOP_GETARG, argSlot))
   10471           0 :                 return false;
   10472             : 
   10473             :             // If there's an parameter expression var scope, the destructuring
   10474             :             // declaration needs to initialize the name in the function scope,
   10475             :             // which is not the innermost scope.
   10476          42 :             if (!emitDestructuringOps(bindingElement,
   10477             :                                       paramExprVarScope
   10478             :                                       ? DestructuringFormalParameterInVarScope
   10479          42 :                                       : DestructuringDeclaration))
   10480             :             {
   10481           0 :                 return false;
   10482             :             }
   10483             : 
   10484          42 :             if (!emit1(JSOP_POP))
   10485           0 :                 return false;
   10486             :         } else {
   10487       12706 :             RootedAtom paramName(cx, bindingElement->name());
   10488        6353 :             NameLocation paramLoc = *locationOfNameBoundInScope(paramName, funScope);
   10489             : 
   10490        6353 :             if (hasParameterExprs) {
   10491             :                 auto emitRhs = [argSlot, initializer, isRest](BytecodeEmitter* bce,
   10492         430 :                                                               const NameLocation&, bool)
   10493         864 :                 {
   10494             :                     // If we had an initializer or a rest parameter, the value is
   10495             :                     // already on the stack.
   10496         647 :                     if (!initializer && !isRest)
   10497         217 :                         return bce->emitArgOp(JSOP_GETARG, argSlot);
   10498         213 :                     return true;
   10499         430 :                 };
   10500             : 
   10501         430 :                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, emitRhs, true))
   10502           0 :                     return false;
   10503         430 :                 if (!emit1(JSOP_POP))
   10504           0 :                     return false;
   10505        5923 :             } else if (isRest) {
   10506             :                 // The rest value is already on top of the stack.
   10507          62 :                 auto nop = [](BytecodeEmitter*, const NameLocation&, bool) {
   10508             :                     return true;
   10509          62 :                 };
   10510             : 
   10511          62 :                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, nop, true))
   10512           0 :                     return false;
   10513          62 :                 if (!emit1(JSOP_POP))
   10514           0 :                     return false;
   10515             :             }
   10516             :         }
   10517             : 
   10518        6395 :         if (paramExprVarScope) {
   10519           0 :             if (!paramExprVarScope->leave(this))
   10520           0 :                 return false;
   10521             :         }
   10522             :     }
   10523             : 
   10524        5404 :     return true;
   10525             : }
   10526             : 
   10527             : bool
   10528        5404 : BytecodeEmitter::emitInitializeFunctionSpecialNames()
   10529             : {
   10530        5404 :     FunctionBox* funbox = sc->asFunctionBox();
   10531             : 
   10532             :     auto emitInitializeFunctionSpecialName = [](BytecodeEmitter* bce, HandlePropertyName name,
   10533        2498 :                                                 JSOp op)
   10534             :     {
   10535             :         // A special name must be slotful, either on the frame or on the
   10536             :         // call environment.
   10537        2498 :         MOZ_ASSERT(bce->lookupName(name).hasKnownSlot());
   10538             : 
   10539        2498 :         auto emitInitial = [op](BytecodeEmitter* bce, const NameLocation&, bool) {
   10540             :             return bce->emit1(op);
   10541        4996 :         };
   10542             : 
   10543        2498 :         if (!bce->emitInitializeName(name, emitInitial))
   10544           0 :             return false;
   10545        2498 :         if (!bce->emit1(JSOP_POP))
   10546           0 :             return false;
   10547             : 
   10548        2498 :         return true;
   10549             :     };
   10550             : 
   10551             :     // Do nothing if the function doesn't have an arguments binding.
   10552        5404 :     if (funbox->argumentsHasLocalBinding()) {
   10553         264 :         if (!emitInitializeFunctionSpecialName(this, cx->names().arguments, JSOP_ARGUMENTS))
   10554           0 :             return false;
   10555             :     }
   10556             : 
   10557             :     // Do nothing if the function doesn't have a this-binding (this
   10558             :     // happens for instance if it doesn't use this/eval or if it's an
   10559             :     // arrow function).
   10560        5404 :     if (funbox->hasThisBinding()) {
   10561        2234 :         if (!emitInitializeFunctionSpecialName(this, cx->names().dotThis, JSOP_FUNCTIONTHIS))
   10562           0 :             return false;
   10563             :     }
   10564             : 
   10565        5404 :     return true;
   10566             : }
   10567             : 
   10568             : bool
   10569        5404 : BytecodeEmitter::emitFunctionBody(ParseNode* funBody)
   10570             : {
   10571        5404 :     FunctionBox* funbox = sc->asFunctionBox();
   10572             : 
   10573        5404 :     if (!emitTree(funBody))
   10574           0 :         return false;
   10575             : 
   10576        5405 :     if (funbox->needsFinalYield()) {
   10577             :         // If we fall off the end of a generator, do a final yield.
   10578         127 :         bool needsIteratorResult = funbox->needsIteratorResult();
   10579         127 :         if (needsIteratorResult) {
   10580          15 :             if (!emitPrepareIteratorResult())
   10581           0 :                 return false;
   10582             :         }
   10583             : 
   10584         127 :         if (!emit1(JSOP_UNDEFINED))
   10585           0 :             return false;
   10586             : 
   10587         127 :         if (needsIteratorResult) {
   10588          15 :             if (!emitFinishIteratorResult(true))
   10589           0 :                 return false;
   10590             :         }
   10591             : 
   10592         127 :         if (!emit1(JSOP_SETRVAL))
   10593           0 :             return false;
   10594             : 
   10595         127 :         if (!emitGetDotGenerator())
   10596           0 :             return false;
   10597             : 
   10598             :         // No need to check for finally blocks, etc as in EmitReturn.
   10599         127 :         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
   10600           0 :             return false;
   10601             :     } else {
   10602             :         // Non-generator functions just return |undefined|. The
   10603             :         // JSOP_RETRVAL emitted below will do that, except if the
   10604             :         // script has a finally block: there can be a non-undefined
   10605             :         // value in the return value slot. Make sure the return value
   10606             :         // is |undefined|.
   10607        5278 :         if (hasTryFinally) {
   10608          23 :             if (!emit1(JSOP_UNDEFINED))
   10609           0 :                 return false;
   10610          23 :             if (!emit1(JSOP_SETRVAL))
   10611           0 :                 return false;
   10612             :         }
   10613             :     }
   10614             : 
   10615        5405 :     if (funbox->isDerivedClassConstructor()) {
   10616          13 :         if (!emitCheckDerivedClassConstructorReturn())
   10617           0 :             return false;
   10618             :     }
   10619             : 
   10620        5405 :     return true;
   10621             : }
   10622             : 
   10623             : bool
   10624         519 : BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
   10625             : {
   10626             :     // The caller has pushed the RHS to the top of the stack. Assert that the
   10627             :     // name is lexical and no BIND[G]NAME ops were emitted.
   10628         519 :     auto assertLexical = [](BytecodeEmitter*, const NameLocation& loc, bool emittedBindOp) {
   10629         519 :         MOZ_ASSERT(loc.isLexical());
   10630         519 :         MOZ_ASSERT(!emittedBindOp);
   10631         519 :         return true;
   10632             :     };
   10633         519 :     return emitInitializeName(pn, assertLexical);
   10634             : }
   10635             : 
   10636             : // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
   10637             : // (BindingClassDeclarationEvaluation).
   10638             : bool
   10639          32 : BytecodeEmitter::emitClass(ParseNode* pn)
   10640             : {
   10641          32 :     ClassNode& classNode = pn->as<ClassNode>();
   10642             : 
   10643          32 :     ClassNames* names = classNode.names();
   10644             : 
   10645          32 :     ParseNode* heritageExpression = classNode.heritage();
   10646             : 
   10647          32 :     ParseNode* classMethods = classNode.methodList();
   10648          32 :     ParseNode* constructor = nullptr;
   10649          32 :     for (ParseNode* mn = classMethods->pn_head; mn; mn = mn->pn_next) {
   10650          31 :         ClassMethod& method = mn->as<ClassMethod>();
   10651          31 :         ParseNode& methodName = method.name();
   10652          93 :         if (!method.isStatic() &&
   10653          62 :             (methodName.isKind(PNK_OBJECT_PROPERTY_NAME) || methodName.isKind(PNK_STRING)) &&
   10654          31 :             methodName.pn_atom == cx->names().constructor)
   10655             :         {
   10656          31 :             constructor = &method.method();
   10657          31 :             break;
   10658             :         }
   10659             :     }
   10660             : 
   10661          32 :     bool savedStrictness = sc->setLocalStrictMode(true);
   10662             : 
   10663          64 :     Maybe<TDZCheckCache> tdzCache;
   10664          64 :     Maybe<EmitterScope> emitterScope;
   10665          32 :     if (names) {
   10666          26 :         tdzCache.emplace(this);
   10667          26 :         emitterScope.emplace(this);
   10668          26 :         if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode.scopeBindings()))
   10669           0 :             return false;
   10670             :     }
   10671             : 
   10672             :     // Pseudocode for class declarations:
   10673             :     //
   10674             :     //     class extends BaseExpression {
   10675             :     //       constructor() { ... }
   10676             :     //       ...
   10677             :     //       }
   10678             :     //
   10679             :     //
   10680             :     //   if defined <BaseExpression> {
   10681             :     //     let heritage = BaseExpression;
   10682             :     //
   10683             :     //     if (heritage !== null) {
   10684             :     //       funProto = heritage;
   10685             :     //       objProto = heritage.prototype;
   10686             :     //     } else {
   10687             :     //       funProto = %FunctionPrototype%;
   10688             :     //       objProto = null;
   10689             :     //     }
   10690             :     //   } else {
   10691             :     //     objProto = %ObjectPrototype%;
   10692             :     //   }
   10693             :     //
   10694             :     //   let homeObject = ObjectCreate(objProto);
   10695             :     //
   10696             :     //   if defined <constructor> {
   10697             :     //     if defined <BaseExpression> {
   10698             :     //       cons = DefineMethod(<constructor>, proto=homeObject, funProto=funProto);
   10699             :     //     } else {
   10700             :     //       cons = DefineMethod(<constructor>, proto=homeObject);
   10701             :     //     }
   10702             :     //   } else {
   10703             :     //     if defined <BaseExpression> {
   10704             :     //       cons = DefaultDerivedConstructor(proto=homeObject, funProto=funProto);
   10705             :     //     } else {
   10706             :     //       cons = DefaultConstructor(proto=homeObject);
   10707             :     //     }
   10708             :     //   }
   10709             :     //
   10710             :     //   cons.prototype = homeObject;
   10711             :     //   homeObject.constructor = cons;
   10712             :     //
   10713             :     //   EmitPropertyList(...)
   10714             : 
   10715             :     // This is kind of silly. In order to the get the home object defined on
   10716             :     // the constructor, we have to make it second, but we want the prototype
   10717             :     // on top for EmitPropertyList, because we expect static properties to be
   10718             :     // rarer. The result is a few more swaps than we would like. Such is life.
   10719          32 :     if (heritageExpression) {
   10720          32 :         IfThenElseEmitter ifThenElse(this);
   10721             : 
   10722          16 :         if (!emitTree(heritageExpression))                      // ... HERITAGE
   10723           0 :             return false;
   10724             : 
   10725             :         // Heritage must be null or a non-generator constructor
   10726          16 :         if (!emit1(JSOP_CHECKCLASSHERITAGE))                    // ... HERITAGE
   10727           0 :             return false;
   10728             : 
   10729             :         // [IF] (heritage !== null)
   10730          16 :         if (!emit1(JSOP_DUP))                                   // ... HERITAGE HERITAGE
   10731           0 :             return false;
   10732          16 :         if (!emit1(JSOP_NULL))                                  // ... HERITAGE HERITAGE NULL
   10733           0 :             return false;
   10734          16 :         if (!emit1(JSOP_STRICTNE))                              // ... HERITAGE NE
   10735           0 :             return false;
   10736             : 
   10737             :         // [THEN] funProto = heritage, objProto = heritage.prototype
   10738          16 :         if (!ifThenElse.emitIfElse())
   10739           0 :             return false;
   10740          16 :         if (!emit1(JSOP_DUP))                                   // ... HERITAGE HERITAGE
   10741           0 :             return false;
   10742          16 :         if (!emitAtomOp(cx->names().prototype, JSOP_GETPROP))   // ... HERITAGE PROTO
   10743           0 :             return false;
   10744             : 
   10745             :         // [ELSE] funProto = %FunctionPrototype%, objProto = null
   10746          16 :         if (!ifThenElse.emitElse())
   10747           0 :             return false;
   10748          16 :         if (!emit1(JSOP_POP))                                   // ...
   10749           0 :             return false;
   10750          16 :         if (!emit2(JSOP_BUILTINPROTO, JSProto_Function))        // ... PROTO
   10751           0 :             return false;
   10752          16 :         if (!emit1(JSOP_NULL))                                  // ... PROTO NULL
   10753           0 :             return false;
   10754             : 
   10755             :         // [ENDIF]
   10756          16 :         if (!ifThenElse.emitEnd())
   10757           0 :             return false;
   10758             : 
   10759          16 :         if (!emit1(JSOP_OBJWITHPROTO))                          // ... HERITAGE HOMEOBJ
   10760           0 :             return false;
   10761          16 :         if (!emit1(JSOP_SWAP))                                  // ... HOMEOBJ HERITAGE
   10762           0 :             return false;
   10763             :     } else {
   10764          16 :         if (!emitNewInit(JSProto_Object))                       // ... HOMEOBJ
   10765           0 :             return false;
   10766             :     }
   10767             : 
   10768             :     // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
   10769             :     // is not used, an implicit value of %FunctionPrototype% is implied.
   10770             : 
   10771          32 :     if (constructor) {
   10772          31 :         if (!emitFunction(constructor, !!heritageExpression))   // ... HOMEOBJ CONSTRUCTOR
   10773           0 :             return false;
   10774          31 :         if (constructor->pn_funbox->needsHomeObject()) {
   10775           0 :             if (!emit2(JSOP_INITHOMEOBJECT, 0))                 // ... HOMEOBJ CONSTRUCTOR
   10776           0 :                 return false;
   10777             :         }
   10778             :     } else {
   10779             :         // In the case of default class constructors, emit the start and end
   10780             :         // offsets in the source buffer as source notes so that when we
   10781             :         // actually make the constructor during execution, we can give it the
   10782             :         // correct toString output.
   10783             :         //
   10784             :         // Token positions are already offset from the start column. Since
   10785             :         // toString offsets are absolute offsets into the ScriptSource,
   10786             :         // de-offset from the starting column.
   10787           1 :         ptrdiff_t classStart = ptrdiff_t(pn->pn_pos.begin) -
   10788           1 :                                tokenStream().options().sourceStartColumn;
   10789           1 :         ptrdiff_t classEnd = ptrdiff_t(pn->pn_pos.end) -
   10790           1 :                              tokenStream().options().sourceStartColumn;
   10791           1 :         if (!newSrcNote3(SRC_CLASS_SPAN, classStart, classEnd))
   10792           0 :             return false;
   10793             : 
   10794           1 :         JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;
   10795           1 :         if (heritageExpression) {
   10796           1 :             if (!emitAtomOp(name, JSOP_DERIVEDCONSTRUCTOR))     // ... HOMEOBJ CONSTRUCTOR
   10797           0 :                 return false;
   10798             :         } else {
   10799           0 :             if (!emitAtomOp(name, JSOP_CLASSCONSTRUCTOR))       // ... HOMEOBJ CONSTRUCTOR
   10800           0 :                 return false;
   10801             :         }
   10802             :     }
   10803             : 
   10804          32 :     if (!emit1(JSOP_SWAP))                                      // ... CONSTRUCTOR HOMEOBJ
   10805           0 :         return false;
   10806             : 
   10807          32 :     if (!emit1(JSOP_DUP2))                                          // ... CONSTRUCTOR HOMEOBJ CONSTRUCTOR HOMEOBJ
   10808           0 :         return false;
   10809          32 :     if (!emitAtomOp(cx->names().prototype, JSOP_INITLOCKEDPROP))    // ... CONSTRUCTOR HOMEOBJ CONSTRUCTOR
   10810           0 :         return false;
   10811          32 :     if (!emitAtomOp(cx->names().constructor, JSOP_INITHIDDENPROP))  // ... CONSTRUCTOR HOMEOBJ
   10812           0 :         return false;
   10813             : 
   10814          64 :     RootedPlainObject obj(cx);
   10815          32 :     if (!emitPropertyList(classMethods, &obj, ClassBody))       // ... CONSTRUCTOR HOMEOBJ
   10816           0 :         return false;
   10817             : 
   10818          32 :     if (!emit1(JSOP_POP))                                       // ... CONSTRUCTOR
   10819           0 :         return false;
   10820             : 
   10821          32 :     if (names) {
   10822          26 :         ParseNode* innerName = names->innerBinding();
   10823          26 :         if (!emitLexicalInitialization(innerName))              // ... CONSTRUCTOR
   10824           0 :             return false;
   10825             : 
   10826             :         // Pop the inner scope.
   10827          26 :         if (!emitterScope->leave(this))
   10828           0 :             return false;
   10829          26 :         emitterScope.reset();
   10830             : 
   10831          26 :         ParseNode* outerName = names->outerBinding();
   10832          26 :         if (outerName) {
   10833          26 :             if (!emitLexicalInitialization(outerName))          // ... CONSTRUCTOR
   10834           0 :                 return false;
   10835             :             // Only class statements make outer bindings, and they do not leave
   10836             :             // themselves on the stack.
   10837          26 :             if (!emit1(JSOP_POP))                               // ...
   10838           0 :                 return false;
   10839             :         }
   10840             :     }
   10841             : 
   10842             :     // The CONSTRUCTOR is left on stack if this is an expression.
   10843             : 
   10844          32 :     MOZ_ALWAYS_TRUE(sc->setLocalStrictMode(savedStrictness));
   10845             : 
   10846          32 :     return true;
   10847             : }
   10848             : 
   10849             : bool
   10850      227349 : BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
   10851             :                           EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */)
   10852             : {
   10853      227349 :     if (!CheckRecursionLimit(cx))
   10854           0 :         return false;
   10855             : 
   10856      454710 :     EmitLevelManager elm(this);
   10857             : 
   10858             :     /* Emit notes to tell the current bytecode's source line number.
   10859             :        However, a couple trees require special treatment; see the
   10860             :        relevant emitter functions for details. */
   10861      227349 :     if (emitLineNote == EMIT_LINENOTE && !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
   10862      224002 :         if (!updateLineNumberNotes(pn->pn_pos.begin))
   10863           0 :             return false;
   10864             :     }
   10865             : 
   10866      227349 :     switch (pn->getKind()) {
   10867             :       case PNK_FUNCTION:
   10868        5830 :         if (!emitFunction(pn))
   10869           0 :             return false;
   10870        5831 :         break;
   10871             : 
   10872             :       case PNK_PARAMSBODY:
   10873        5404 :         if (!emitFunctionFormalParametersAndBody(pn))
   10874           0 :             return false;
   10875        5405 :         break;
   10876             : 
   10877             :       case PNK_IF:
   10878        6761 :         if (!emitIf(pn))
   10879           0 :             return false;
   10880        6762 :         break;
   10881             : 
   10882             :       case PNK_SWITCH:
   10883         210 :         if (!emitSwitch(pn))
   10884           0 :             return false;
   10885         210 :         break;
   10886             : 
   10887             :       case PNK_WHILE:
   10888         183 :         if (!emitWhile(pn))
   10889           0 :             return false;
   10890         183 :         break;
   10891             : 
   10892             :       case PNK_DOWHILE:
   10893          20 :         if (!emitDo(pn))
   10894           0 :             return false;
   10895          20 :         break;
   10896             : 
   10897             :       case PNK_FOR:
   10898         322 :         if (!emitFor(pn))
   10899           0 :             return false;
   10900         322 :         break;
   10901             : 
   10902             :       case PNK_COMPREHENSIONFOR:
   10903           0 :         if (!emitComprehensionFor(pn))
   10904           0 :             return false;
   10905           0 :         break;
   10906             : 
   10907             :       case PNK_BREAK:
   10908         479 :         if (!emitBreak(pn->as<BreakStatement>().label()))
   10909           0 :             return false;
   10910         479 :         break;
   10911             : 
   10912             :       case PNK_CONTINUE:
   10913         121 :         if (!emitContinue(pn->as<ContinueStatement>().label()))
   10914           0 :             return false;
   10915         121 :         break;
   10916             : 
   10917             :       case PNK_WITH:
   10918           0 :         if (!emitWith(pn))
   10919           0 :             return false;
   10920           0 :         break;
   10921             : 
   10922             :       case PNK_TRY:
   10923         489 :         if (!emitTry(pn))
   10924           0 :             return false;
   10925         489 :         break;
   10926             : 
   10927             :       case PNK_CATCH:
   10928         467 :         if (!emitCatch(pn))
   10929           0 :             return false;
   10930         467 :         break;
   10931             : 
   10932             :       case PNK_VAR:
   10933        4836 :         if (!emitDeclarationList(pn))
   10934           0 :             return false;
   10935        4836 :         break;
   10936             : 
   10937             :       case PNK_RETURN:
   10938        6164 :         if (!emitReturn(pn))
   10939           0 :             return false;
   10940        6164 :         break;
   10941             : 
   10942             :       case PNK_YIELD_STAR:
   10943           3 :         if (!emitYieldStar(pn->pn_kid))
   10944           0 :             return false;
   10945           3 :         break;
   10946             : 
   10947             :       case PNK_GENERATOR:
   10948         127 :         if (!emit1(JSOP_GENERATOR))
   10949           0 :             return false;
   10950         127 :         break;
   10951             : 
   10952             :       case PNK_INITIALYIELD:
   10953         127 :         if (!emitInitialYield(pn))
   10954           0 :             return false;
   10955         127 :         break;
   10956             : 
   10957             :       case PNK_YIELD:
   10958          15 :         if (!emitYield(pn))
   10959           0 :             return false;
   10960          15 :         break;
   10961             : 
   10962             :       case PNK_AWAIT:
   10963         235 :         if (!emitAwait(pn))
   10964           0 :             return false;
   10965         235 :         break;
   10966             : 
   10967             :       case PNK_STATEMENTLIST:
   10968       12756 :         if (!emitStatementList(pn))
   10969           0 :             return false;
   10970       12758 :         break;
   10971             : 
   10972             :       case PNK_SEMI:
   10973       14318 :         if (!emitStatement(pn))
   10974           0 :             return false;
   10975       14318 :         break;
   10976             : 
   10977             :       case PNK_LABEL:
   10978           0 :         if (!emitLabeledStatement(&pn->as<LabeledStatement>()))
   10979           0 :             return false;
   10980           0 :         break;
   10981             : 
   10982             :       case PNK_COMMA:
   10983          10 :         if (!emitSequenceExpr(pn, valueUsage))
   10984           0 :             return false;
   10985          10 :         break;
   10986             : 
   10987             :       case PNK_ASSIGN:
   10988             :       case PNK_ADDASSIGN:
   10989             :       case PNK_SUBASSIGN:
   10990             :       case PNK_BITORASSIGN:
   10991             :       case PNK_BITXORASSIGN:
   10992             :       case PNK_BITANDASSIGN:
   10993             :       case PNK_LSHASSIGN:
   10994             :       case PNK_RSHASSIGN:
   10995             :       case PNK_URSHASSIGN:
   10996             :       case PNK_MULASSIGN:
   10997             :       case PNK_DIVASSIGN:
   10998             :       case PNK_MODASSIGN:
   10999             :       case PNK_POWASSIGN:
   11000        5736 :         if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
   11001           0 :             return false;
   11002        5736 :         break;
   11003             : 
   11004             :       case PNK_CONDITIONAL:
   11005         657 :         if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
   11006           0 :             return false;
   11007         657 :         break;
   11008             : 
   11009             :       case PNK_OR:
   11010             :       case PNK_AND:
   11011        2022 :         if (!emitLogical(pn))
   11012           0 :             return false;
   11013        2023 :         break;
   11014             : 
   11015             :       case PNK_ADD:
   11016             :       case PNK_SUB:
   11017             :       case PNK_BITOR:
   11018             :       case PNK_BITXOR:
   11019             :       case PNK_BITAND:
   11020             :       case PNK_STRICTEQ:
   11021             :       case PNK_EQ:
   11022             :       case PNK_STRICTNE:
   11023             :       case PNK_NE:
   11024             :       case PNK_LT:
   11025             :       case PNK_LE:
   11026             :       case PNK_GT:
   11027             :       case PNK_GE:
   11028             :       case PNK_IN:
   11029             :       case PNK_INSTANCEOF:
   11030             :       case PNK_LSH:
   11031             :       case PNK_RSH:
   11032             :       case PNK_URSH:
   11033             :       case PNK_STAR:
   11034             :       case PNK_DIV:
   11035             :       case PNK_MOD:
   11036        8175 :         if (!emitLeftAssociative(pn))
   11037           0 :             return false;
   11038        8175 :         break;
   11039             : 
   11040             :       case PNK_POW:
   11041           0 :         if (!emitRightAssociative(pn))
   11042           0 :             return false;
   11043           0 :         break;
   11044             : 
   11045             :       case PNK_TYPEOFNAME:
   11046         437 :         if (!emitTypeof(pn, JSOP_TYPEOF))
   11047           0 :             return false;
   11048         437 :         break;
   11049             : 
   11050             :       case PNK_TYPEOFEXPR:
   11051          65 :         if (!emitTypeof(pn, JSOP_TYPEOFEXPR))
   11052           0 :             return false;
   11053          65 :         break;
   11054             : 
   11055             :       case PNK_THROW:
   11056             :       case PNK_VOID:
   11057             :       case PNK_NOT:
   11058             :       case PNK_BITNOT:
   11059             :       case PNK_POS:
   11060             :       case PNK_NEG:
   11061        3393 :         if (!emitUnary(pn))
   11062           0 :             return false;
   11063        3394 :         break;
   11064             : 
   11065             :       case PNK_PREINCREMENT:
   11066             :       case PNK_PREDECREMENT:
   11067             :       case PNK_POSTINCREMENT:
   11068             :       case PNK_POSTDECREMENT:
   11069         705 :         if (!emitIncOrDec(pn))
   11070           0 :             return false;
   11071         705 :         break;
   11072             : 
   11073             :       case PNK_DELETENAME:
   11074           0 :         if (!emitDeleteName(pn))
   11075           0 :             return false;
   11076           0 :         break;
   11077             : 
   11078             :       case PNK_DELETEPROP:
   11079          52 :         if (!emitDeleteProperty(pn))
   11080           0 :             return false;
   11081          52 :         break;
   11082             : 
   11083             :       case PNK_DELETEELEM:
   11084          30 :         if (!emitDeleteElement(pn))
   11085           0 :             return false;
   11086          30 :         break;
   11087             : 
   11088             :       case PNK_DELETEEXPR:
   11089           0 :         if (!emitDeleteExpression(pn))
   11090           0 :             return false;
   11091           0 :         break;
   11092             : 
   11093             :       case PNK_DOT:
   11094       10563 :         if (pn->as<PropertyAccess>().isSuper()) {
   11095           0 :             if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
   11096           0 :                 return false;
   11097             :         } else {
   11098       10563 :             if (!emitPropOp(pn, JSOP_GETPROP))
   11099           0 :                 return false;
   11100             :         }
   11101       10563 :         break;
   11102             : 
   11103             :       case PNK_ELEM:
   11104        2431 :         if (pn->as<PropertyByValue>().isSuper()) {
   11105           0 :             if (!emitSuperElemOp(pn, JSOP_GETELEM_SUPER))
   11106           0 :                 return false;
   11107             :         } else {
   11108        2431 :             if (!emitElemOp(pn, JSOP_GETELEM))
   11109           0 :                 return false;
   11110             :         }
   11111        2431 :         break;
   11112             : 
   11113             :       case PNK_NEW:
   11114             :       case PNK_TAGGED_TEMPLATE:
   11115             :       case PNK_CALL:
   11116             :       case PNK_GENEXP:
   11117             :       case PNK_SUPERCALL:
   11118       22220 :         if (!emitCallOrNew(pn, valueUsage))
   11119           0 :             return false;
   11120       22221 :         break;
   11121             : 
   11122             :       case PNK_LEXICALSCOPE:
   11123       12679 :         if (!emitLexicalScope(pn))
   11124           0 :             return false;
   11125       12680 :         break;
   11126             : 
   11127             :       case PNK_CONST:
   11128             :       case PNK_LET:
   11129        4720 :         if (!emitDeclarationList(pn))
   11130           0 :             return false;
   11131        4721 :         break;
   11132             : 
   11133             :       case PNK_IMPORT:
   11134           0 :         MOZ_ASSERT(sc->isModuleContext());
   11135           0 :         break;
   11136             : 
   11137             :       case PNK_EXPORT:
   11138           0 :         MOZ_ASSERT(sc->isModuleContext());
   11139           0 :         if (pn->pn_kid->getKind() != PNK_EXPORT_SPEC_LIST) {
   11140           0 :             if (!emitTree(pn->pn_kid))
   11141           0 :                 return false;
   11142             :         }
   11143           0 :         break;
   11144             : 
   11145             :       case PNK_EXPORT_DEFAULT:
   11146           0 :         MOZ_ASSERT(sc->isModuleContext());
   11147           0 :         if (!emitTree(pn->pn_kid))
   11148           0 :             return false;
   11149           0 :         if (pn->pn_right) {
   11150           0 :             if (!emitLexicalInitialization(pn->pn_right))
   11151           0 :                 return false;
   11152           0 :             if (!emit1(JSOP_POP))
   11153           0 :                 return false;
   11154             :         }
   11155           0 :         break;
   11156             : 
   11157             :       case PNK_EXPORT_FROM:
   11158           0 :         MOZ_ASSERT(sc->isModuleContext());
   11159           0 :         break;
   11160             : 
   11161             :       case PNK_ARRAYPUSH:
   11162             :         /*
   11163             :          * The array object's stack index is in arrayCompDepth. See below
   11164             :          * under the array initialiser code generator for array comprehension
   11165             :          * special casing.
   11166             :          */
   11167           0 :         if (!emitTree(pn->pn_kid))
   11168           0 :             return false;
   11169           0 :         if (!emitDupAt(this->stackDepth - 1 - arrayCompDepth))
   11170           0 :             return false;
   11171           0 :         if (!emit1(JSOP_ARRAYPUSH))
   11172           0 :             return false;
   11173           0 :         break;
   11174             : 
   11175             :       case PNK_CALLSITEOBJ:
   11176           1 :         if (!emitCallSiteObject(pn))
   11177           0 :             return false;
   11178           1 :         break;
   11179             : 
   11180             :       case PNK_ARRAY:
   11181        1212 :         if (!emitArrayLiteral(pn))
   11182           0 :             return false;
   11183        1213 :         break;
   11184             : 
   11185             :       case PNK_ARRAYCOMP:
   11186           0 :         if (!emitArrayComp(pn))
   11187           0 :             return false;
   11188           0 :         break;
   11189             : 
   11190             :       case PNK_OBJECT:
   11191        1669 :         if (!emitObject(pn))
   11192           0 :             return false;
   11193        1670 :         break;
   11194             : 
   11195             :       case PNK_NAME:
   11196       59721 :         if (!emitGetName(pn))
   11197           0 :             return false;
   11198       59721 :         break;
   11199             : 
   11200             :       case PNK_TEMPLATE_STRING_LIST:
   11201         252 :         if (!emitTemplateString(pn))
   11202           0 :             return false;
   11203         252 :         break;
   11204             : 
   11205             :       case PNK_TEMPLATE_STRING:
   11206             :       case PNK_STRING:
   11207       11718 :         if (!emitAtomOp(pn, JSOP_STRING))
   11208           0 :             return false;
   11209       11718 :         break;
   11210             : 
   11211             :       case PNK_NUMBER:
   11212        7997 :         if (!emitNumberOp(pn->pn_dval))
   11213           0 :             return false;
   11214        7997 :         break;
   11215             : 
   11216             :       case PNK_REGEXP:
   11217         172 :         if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox())))
   11218           0 :             return false;
   11219         172 :         break;
   11220             : 
   11221             :       case PNK_TRUE:
   11222             :       case PNK_FALSE:
   11223             :       case PNK_NULL:
   11224             :       case PNK_RAW_UNDEFINED:
   11225        4088 :         if (!emit1(pn->getOp()))
   11226           0 :             return false;
   11227        4088 :         break;
   11228             : 
   11229             :       case PNK_THIS:
   11230        7700 :         if (!emitThisLiteral(pn))
   11231           0 :             return false;
   11232        7700 :         break;
   11233             : 
   11234             :       case PNK_DEBUGGER:
   11235           0 :         if (!updateSourceCoordNotes(pn->pn_pos.begin))
   11236           0 :             return false;
   11237           0 :         if (!emit1(JSOP_DEBUGGER))
   11238           0 :             return false;
   11239           0 :         break;
   11240             : 
   11241             :       case PNK_NOP:
   11242           0 :         MOZ_ASSERT(pn->getArity() == PN_NULLARY);
   11243           0 :         break;
   11244             : 
   11245             :       case PNK_CLASS:
   11246          32 :         if (!emitClass(pn))
   11247           0 :             return false;
   11248          32 :         break;
   11249             : 
   11250             :       case PNK_NEWTARGET:
   11251          12 :         if (!emit1(JSOP_NEWTARGET))
   11252           0 :             return false;
   11253          12 :         break;
   11254             : 
   11255             :       case PNK_SETTHIS:
   11256          13 :         if (!emitSetThis(pn))
   11257           0 :             return false;
   11258          13 :         break;
   11259             : 
   11260             :       case PNK_POSHOLDER:
   11261           0 :         MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER");
   11262             : 
   11263             :       default:
   11264           0 :         MOZ_ASSERT(0);
   11265             :     }
   11266             : 
   11267             :     /* bce->emitLevel == 1 means we're last on the stack, so finish up. */
   11268      227361 :     if (emitLevel == 1) {
   11269        5674 :         if (!updateSourceCoordNotes(pn->pn_pos.end))
   11270           0 :             return false;
   11271             :     }
   11272      227361 :     return true;
   11273             : }
   11274             : 
   11275             : bool
   11276       17034 : BytecodeEmitter::emitTreeInBranch(ParseNode* pn,
   11277             :                                   ValueUsage valueUsage /* = ValueUsage::WantValue */)
   11278             : {
   11279             :     // Code that may be conditionally executed always need their own TDZ
   11280             :     // cache.
   11281       34069 :     TDZCheckCache tdzCache(this);
   11282       34069 :     return emitTree(pn, valueUsage);
   11283             : }
   11284             : 
   11285             : static bool
   11286      304593 : AllocSrcNote(JSContext* cx, SrcNotesVector& notes, unsigned* index)
   11287             : {
   11288             :     // Start it off moderately large to avoid repeated resizings early on.
   11289             :     // ~99% of cases fit within 256 bytes.
   11290      304593 :     if (notes.capacity() == 0 && !notes.reserve(256))
   11291           0 :         return false;
   11292             : 
   11293      304593 :     if (!notes.growBy(1)) {
   11294           0 :         ReportOutOfMemory(cx);
   11295           0 :         return false;
   11296             :     }
   11297             : 
   11298      304593 :     *index = notes.length() - 1;
   11299      304593 :     return true;
   11300             : }
   11301             : 
   11302             : bool
   11303      248558 : BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp)
   11304             : {
   11305      248558 :     SrcNotesVector& notes = this->notes();
   11306             :     unsigned index;
   11307      248558 :     if (!AllocSrcNote(cx, notes, &index))
   11308           0 :         return false;
   11309             : 
   11310             :     /*
   11311             :      * Compute delta from the last annotated bytecode's offset.  If it's too
   11312             :      * big to fit in sn, allocate one or more xdelta notes and reset sn.
   11313             :      */
   11314      248558 :     ptrdiff_t offset = this->offset();
   11315      248558 :     ptrdiff_t delta = offset - lastNoteOffset();
   11316      248558 :     current->lastNoteOffset = offset;
   11317      248558 :     if (delta >= SN_DELTA_LIMIT) {
   11318          92 :         do {
   11319       56035 :             ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
   11320       56035 :             SN_MAKE_XDELTA(&notes[index], xdelta);
   11321       56035 :             delta -= xdelta;
   11322       56035 :             if (!AllocSrcNote(cx, notes, &index))
   11323           0 :                 return false;
   11324       56035 :         } while (delta >= SN_DELTA_LIMIT);
   11325             :     }
   11326             : 
   11327             :     /*
   11328             :      * Initialize type and delta, then allocate the minimum number of notes
   11329             :      * needed for type's arity.  Usually, we won't need more, but if an offset
   11330             :      * does take two bytes, setSrcNoteOffset will grow notes.
   11331             :      */
   11332      248558 :     SN_MAKE_NOTE(&notes[index], type, delta);
   11333      339051 :     for (int n = (int)js_SrcNoteSpec[type].arity; n > 0; n--) {
   11334       90493 :         if (!newSrcNote(SRC_NULL))
   11335           0 :             return false;
   11336             :     }
   11337             : 
   11338      248558 :     if (indexp)
   11339       96304 :         *indexp = index;
   11340      248558 :     return true;
   11341             : }
   11342             : 
   11343             : bool
   11344       84698 : BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp)
   11345             : {
   11346             :     unsigned index;
   11347       84698 :     if (!newSrcNote(type, &index))
   11348           0 :         return false;
   11349       84698 :     if (!setSrcNoteOffset(index, 0, offset))
   11350           0 :         return false;
   11351       84698 :     if (indexp)
   11352         586 :         *indexp = index;
   11353       84698 :     return true;
   11354             : }
   11355             : 
   11356             : bool
   11357         133 : BytecodeEmitter::newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
   11358             :                              unsigned* indexp)
   11359             : {
   11360             :     unsigned index;
   11361         133 :     if (!newSrcNote(type, &index))
   11362           0 :         return false;
   11363         133 :     if (!setSrcNoteOffset(index, 0, offset1))
   11364           0 :         return false;
   11365         133 :     if (!setSrcNoteOffset(index, 1, offset2))
   11366           0 :         return false;
   11367         133 :     if (indexp)
   11368         132 :         *indexp = index;
   11369         133 :     return true;
   11370             : }
   11371             : 
   11372             : bool
   11373        2545 : BytecodeEmitter::addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta)
   11374             : {
   11375             :     /*
   11376             :      * Called only from finishTakingSrcNotes to add to main script note
   11377             :      * deltas, and only by a small positive amount.
   11378             :      */
   11379        2545 :     MOZ_ASSERT(current == &main);
   11380        2545 :     MOZ_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT);
   11381             : 
   11382        2545 :     ptrdiff_t base = SN_DELTA(sn);
   11383        2545 :     ptrdiff_t limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
   11384        2545 :     ptrdiff_t newdelta = base + delta;
   11385        2545 :     if (newdelta < limit) {
   11386        2340 :         SN_SET_DELTA(sn, newdelta);
   11387             :     } else {
   11388             :         jssrcnote xdelta;
   11389         205 :         SN_MAKE_XDELTA(&xdelta, delta);
   11390         205 :         if (!main.notes.insert(sn, xdelta))
   11391           0 :             return false;
   11392             :     }
   11393        2545 :     return true;
   11394             : }
   11395             : 
   11396             : bool
   11397       91343 : BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset)
   11398             : {
   11399       91343 :     if (!SN_REPRESENTABLE_OFFSET(offset)) {
   11400           0 :         parser.reportError(JSMSG_NEED_DIET, js_script_str);
   11401           0 :         return false;
   11402             :     }
   11403             : 
   11404       91343 :     SrcNotesVector& notes = this->notes();
   11405             : 
   11406             :     /* Find the offset numbered which (i.e., skip exactly which offsets). */
   11407       91343 :     jssrcnote* sn = &notes[index];
   11408       91343 :     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
   11409       91343 :     MOZ_ASSERT((int) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
   11410       92931 :     for (sn++; which; sn++, which--) {
   11411        1588 :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11412         265 :             sn += 3;
   11413             :     }
   11414             : 
   11415             :     /*
   11416             :      * See if the new offset requires four bytes either by being too big or if
   11417             :      * the offset has already been inflated (in which case, we need to stay big
   11418             :      * to not break the srcnote encoding if this isn't the last srcnote).
   11419             :      */
   11420       91343 :     if (offset > (ptrdiff_t)SN_4BYTE_OFFSET_MASK || (*sn & SN_4BYTE_OFFSET_FLAG)) {
   11421             :         /* Maybe this offset was already set to a four-byte value. */
   11422       18287 :         if (!(*sn & SN_4BYTE_OFFSET_FLAG)) {
   11423             :             /* Insert three dummy bytes that will be overwritten shortly. */
   11424       18287 :             jssrcnote dummy = 0;
   11425       36574 :             if (!(sn = notes.insert(sn, dummy)) ||
   11426       36574 :                 !(sn = notes.insert(sn, dummy)) ||
   11427             :                 !(sn = notes.insert(sn, dummy)))
   11428             :             {
   11429           0 :                 ReportOutOfMemory(cx);
   11430           0 :                 return false;
   11431             :             }
   11432             :         }
   11433       18287 :         *sn++ = (jssrcnote)(SN_4BYTE_OFFSET_FLAG | (offset >> 24));
   11434       18287 :         *sn++ = (jssrcnote)(offset >> 16);
   11435       18287 :         *sn++ = (jssrcnote)(offset >> 8);
   11436             :     }
   11437       91343 :     *sn = (jssrcnote)offset;
   11438       91343 :     return true;
   11439             : }
   11440             : 
   11441             : bool
   11442        5674 : BytecodeEmitter::finishTakingSrcNotes(uint32_t* out)
   11443             : {
   11444        5674 :     MOZ_ASSERT(current == &main);
   11445             : 
   11446        5674 :     unsigned prologueCount = prologue.notes.length();
   11447        5674 :     if (prologueCount && prologue.currentLine != firstLine) {
   11448          95 :         switchToPrologue();
   11449          95 :         if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(firstLine)))
   11450           0 :             return false;
   11451          95 :         switchToMain();
   11452             :     } else {
   11453             :         /*
   11454             :          * Either no prologue srcnotes, or no line number change over prologue.
   11455             :          * We don't need a SRC_SETLINE, but we may need to adjust the offset
   11456             :          * of the first main note, by adding to its delta and possibly even
   11457             :          * prepending SRC_XDELTA notes to it to account for prologue bytecodes
   11458             :          * that came at and after the last annotated bytecode.
   11459             :          */
   11460        5579 :         ptrdiff_t offset = prologueOffset() - prologue.lastNoteOffset;
   11461        5579 :         MOZ_ASSERT(offset >= 0);
   11462        5579 :         if (offset > 0 && main.notes.length() != 0) {
   11463             :             /* NB: Use as much of the first main note's delta as we can. */
   11464        2340 :             jssrcnote* sn = main.notes.begin();
   11465        2340 :             ptrdiff_t delta = SN_IS_XDELTA(sn)
   11466        4661 :                             ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK)
   11467        4661 :                             : SN_DELTA_MASK - (*sn & SN_DELTA_MASK);
   11468        2340 :             if (offset < delta)
   11469        1971 :                 delta = offset;
   11470             :             for (;;) {
   11471        2750 :                 if (!addToSrcNoteDelta(sn, delta))
   11472           0 :                     return false;
   11473        2545 :                 offset -= delta;
   11474        2545 :                 if (offset == 0)
   11475        2340 :                     break;
   11476         205 :                 delta = Min(offset, SN_XDELTA_MASK);
   11477         205 :                 sn = main.notes.begin();
   11478             :             }
   11479             :         }
   11480             :     }
   11481             : 
   11482             :     // The prologue count might have changed, so we can't reuse prologueCount.
   11483             :     // The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
   11484             :     // when the notes are copied to their final destination by CopySrcNotes.
   11485        5674 :     *out = prologue.notes.length() + main.notes.length() + 1;
   11486        5674 :     return true;
   11487             : }
   11488             : 
   11489             : void
   11490        5674 : BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes)
   11491             : {
   11492        5674 :     unsigned prologueCount = prologue.notes.length();
   11493        5674 :     unsigned mainCount = main.notes.length();
   11494        5674 :     unsigned totalCount = prologueCount + mainCount;
   11495        5674 :     MOZ_ASSERT(totalCount == nsrcnotes - 1);
   11496        5674 :     if (prologueCount)
   11497          95 :         PodCopy(destination, prologue.notes.begin(), prologueCount);
   11498        5674 :     PodCopy(destination + prologueCount, main.notes.begin(), mainCount);
   11499        5674 :     SN_MAKE_TERMINATOR(&destination[totalCount]);
   11500        5674 : }
   11501             : 
   11502             : void
   11503          38 : CGConstList::finish(ConstArray* array)
   11504             : {
   11505          38 :     MOZ_ASSERT(length() == array->length);
   11506             : 
   11507          90 :     for (unsigned i = 0; i < length(); i++)
   11508          52 :         array->vector[i] = list[i];
   11509          38 : }
   11510             : 
   11511             : /*
   11512             :  * Find the index of the given object for code generator.
   11513             :  *
   11514             :  * Since the emitter refers to each parsed object only once, for the index we
   11515             :  * use the number of already indexed objects. We also add the object to a list
   11516             :  * to convert the list to a fixed-size array when we complete code generation,
   11517             :  * see js::CGObjectList::finish below.
   11518             :  */
   11519             : unsigned
   11520        7975 : CGObjectList::add(ObjectBox* objbox)
   11521             : {
   11522        7975 :     MOZ_ASSERT(!objbox->emitLink);
   11523        7975 :     objbox->emitLink = lastbox;
   11524        7975 :     lastbox = objbox;
   11525        7975 :     return length++;
   11526             : }
   11527             : 
   11528             : unsigned
   11529           0 : CGObjectList::indexOf(JSObject* obj)
   11530             : {
   11531           0 :     MOZ_ASSERT(length > 0);
   11532           0 :     unsigned index = length - 1;
   11533           0 :     for (ObjectBox* box = lastbox; box->object != obj; box = box->emitLink)
   11534           0 :         index--;
   11535           0 :     return index;
   11536             : }
   11537             : 
   11538             : void
   11539        1381 : CGObjectList::finish(ObjectArray* array)
   11540             : {
   11541        1381 :     MOZ_ASSERT(length <= INDEX_LIMIT);
   11542        1381 :     MOZ_ASSERT(length == array->length);
   11543             : 
   11544        1381 :     js::GCPtrObject* cursor = array->vector + array->length;
   11545        1381 :     ObjectBox* objbox = lastbox;
   11546        7995 :     do {
   11547        7995 :         --cursor;
   11548        7995 :         MOZ_ASSERT(!*cursor);
   11549        7995 :         MOZ_ASSERT(objbox->object->isTenured());
   11550        7995 :         *cursor = objbox->object;
   11551        7995 :     } while ((objbox = objbox->emitLink) != nullptr);
   11552        1381 :     MOZ_ASSERT(cursor == array->vector);
   11553        1381 : }
   11554             : 
   11555             : ObjectBox*
   11556           0 : CGObjectList::find(uint32_t index)
   11557             : {
   11558           0 :     MOZ_ASSERT(index < length);
   11559           0 :     ObjectBox* box = lastbox;
   11560           0 :     for (unsigned n = length - 1; n > index; n--)
   11561           0 :         box = box->emitLink;
   11562           0 :     return box;
   11563             : }
   11564             : 
   11565             : void
   11566        5674 : CGScopeList::finish(ScopeArray* array)
   11567             : {
   11568        5674 :     MOZ_ASSERT(length() <= INDEX_LIMIT);
   11569        5674 :     MOZ_ASSERT(length() == array->length);
   11570       14787 :     for (uint32_t i = 0; i < length(); i++)
   11571        9113 :         array->vector[i].init(vector[i]);
   11572        5674 : }
   11573             : 
   11574             : bool
   11575        2844 : CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end)
   11576             : {
   11577        2844 :     MOZ_ASSERT(start <= end);
   11578        2844 :     MOZ_ASSERT(size_t(uint32_t(start)) == start);
   11579        2844 :     MOZ_ASSERT(size_t(uint32_t(end)) == end);
   11580             : 
   11581             :     JSTryNote note;
   11582        2844 :     note.kind = kind;
   11583        2844 :     note.stackDepth = stackDepth;
   11584        2844 :     note.start = uint32_t(start);
   11585        2844 :     note.length = uint32_t(end - start);
   11586             : 
   11587        2844 :     return list.append(note);
   11588             : }
   11589             : 
   11590             : void
   11591        1074 : CGTryNoteList::finish(TryNoteArray* array)
   11592             : {
   11593        1074 :     MOZ_ASSERT(length() == array->length);
   11594             : 
   11595        3919 :     for (unsigned i = 0; i < length(); i++)
   11596        2845 :         array->vector[i] = list[i];
   11597        1074 : }
   11598             : 
   11599             : bool
   11600        5100 : CGScopeNoteList::append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
   11601             :                         uint32_t parent)
   11602             : {
   11603             :     CGScopeNote note;
   11604        5100 :     mozilla::PodZero(&note);
   11605             : 
   11606        5100 :     note.index = scopeIndex;
   11607        5100 :     note.start = offset;
   11608        5100 :     note.parent = parent;
   11609        5100 :     note.startInPrologue = inPrologue;
   11610             : 
   11611        5100 :     return list.append(note);
   11612             : }
   11613             : 
   11614             : void
   11615        5101 : CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset, bool inPrologue)
   11616             : {
   11617        5101 :     MOZ_ASSERT(index < length());
   11618        5101 :     MOZ_ASSERT(list[index].length == 0);
   11619        5101 :     list[index].end = offset;
   11620        5101 :     list[index].endInPrologue = inPrologue;
   11621        5101 : }
   11622             : 
   11623             : void
   11624        1656 : CGScopeNoteList::finish(ScopeNoteArray* array, uint32_t prologueLength)
   11625             : {
   11626        1656 :     MOZ_ASSERT(length() == array->length);
   11627             : 
   11628        6759 :     for (unsigned i = 0; i < length(); i++) {
   11629        5103 :         if (!list[i].startInPrologue)
   11630        5103 :             list[i].start += prologueLength;
   11631        5103 :         if (!list[i].endInPrologue && list[i].end != UINT32_MAX)
   11632        4999 :             list[i].end += prologueLength;
   11633        5103 :         MOZ_ASSERT(list[i].end >= list[i].start);
   11634        5103 :         list[i].length = list[i].end - list[i].start;
   11635        5103 :         array->vector[i] = list[i];
   11636             :     }
   11637        1656 : }
   11638             : 
   11639             : void
   11640         127 : CGYieldAndAwaitOffsetList::finish(YieldAndAwaitOffsetArray& array, uint32_t prologueLength)
   11641             : {
   11642         127 :     MOZ_ASSERT(length() == array.length());
   11643             : 
   11644         507 :     for (unsigned i = 0; i < length(); i++)
   11645         380 :         array[i] = prologueLength + list[i];
   11646         127 : }
   11647             : 
   11648             : /*
   11649             :  * We should try to get rid of offsetBias (always 0 or 1, where 1 is
   11650             :  * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR.
   11651             :  */
   11652             : const JSSrcNoteSpec js_SrcNoteSpec[] = {
   11653             : #define DEFINE_SRC_NOTE_SPEC(sym, name, arity) { name, arity },
   11654             :     FOR_EACH_SRC_NOTE_TYPE(DEFINE_SRC_NOTE_SPEC)
   11655             : #undef DEFINE_SRC_NOTE_SPEC
   11656             : };
   11657             : 
   11658             : static int
   11659      130942 : SrcNoteArity(jssrcnote* sn)
   11660             : {
   11661             :     MOZ_ASSERT(SN_TYPE(sn) < SRC_LAST);
   11662      130942 :     return js_SrcNoteSpec[SN_TYPE(sn)].arity;
   11663             : }
   11664             : 
   11665             : JS_FRIEND_API(unsigned)
   11666       98573 : js::SrcNoteLength(jssrcnote* sn)
   11667             : {
   11668             :     unsigned arity;
   11669             :     jssrcnote* base;
   11670             : 
   11671       98573 :     arity = SrcNoteArity(sn);
   11672      198437 :     for (base = sn++; arity; sn++, arity--) {
   11673       99861 :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11674       19466 :             sn += 3;
   11675             :     }
   11676       98576 :     return sn - base;
   11677             : }
   11678             : 
   11679             : JS_FRIEND_API(ptrdiff_t)
   11680       32379 : js::GetSrcNoteOffset(jssrcnote* sn, unsigned which)
   11681             : {
   11682             :     /* Find the offset numbered which (i.e., skip exactly which offsets). */
   11683       32379 :     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
   11684       32379 :     MOZ_ASSERT((int) which < SrcNoteArity(sn));
   11685       32697 :     for (sn++; which; sn++, which--) {
   11686         318 :         if (*sn & SN_4BYTE_OFFSET_FLAG)
   11687           9 :             sn += 3;
   11688             :     }
   11689       32379 :     if (*sn & SN_4BYTE_OFFSET_FLAG) {
   11690        4749 :         return (ptrdiff_t)(((uint32_t)(sn[0] & SN_4BYTE_OFFSET_MASK) << 24)
   11691        4749 :                            | (sn[1] << 16)
   11692        4749 :                            | (sn[2] << 8)
   11693        4749 :                            | sn[3]);
   11694             :     }
   11695       27630 :     return (ptrdiff_t)*sn;
   11696             : }

Generated by: LCOV version 1.13