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 "frontend/Parser.h"
32 #include "frontend/TokenStream.h"
33 #include "vm/Debugger.h"
34 #include "vm/GeneratorObject.h"
35 #include "vm/Stack.h"
36 #include "wasm/AsmJS.h"
37 
38 #include "jsatominlines.h"
39 #include "jsobjinlines.h"
40 #include "jsscriptinlines.h"
41 
42 #include "frontend/ParseNode-inl.h"
43 #include "vm/EnvironmentObject-inl.h"
44 #include "vm/NativeObject-inl.h"
45 
46 using namespace js;
47 using namespace js::gc;
48 using namespace js::frontend;
49 
50 using mozilla::AssertedCast;
51 using mozilla::DebugOnly;
52 using mozilla::Maybe;
53 using mozilla::Nothing;
54 using mozilla::NumberIsInt32;
55 using mozilla::PodCopy;
56 using mozilla::Some;
57 
58 class BreakableControl;
59 class LabelControl;
60 class LoopControl;
61 class TryFinallyControl;
62 
63 static bool
ParseNodeRequiresSpecialLineNumberNotes(ParseNode * pn)64 ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn)
65 {
66     return pn->getKind() == PNK_WHILE || pn->getKind() == PNK_FOR;
67 }
68 
69 // A cache that tracks superfluous TDZ checks.
70 //
71 // Each basic block should have a TDZCheckCache in scope. Some NestableControl
72 // subclasses contain a TDZCheckCache.
73 class BytecodeEmitter::TDZCheckCache : public Nestable<BytecodeEmitter::TDZCheckCache>
74 {
75     PooledMapPtr<CheckTDZMap> cache_;
76 
ensureCache(BytecodeEmitter * bce)77     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
78         return cache_ || cache_.acquire(bce->cx);
79     }
80 
81   public:
TDZCheckCache(BytecodeEmitter * bce)82     explicit TDZCheckCache(BytecodeEmitter* bce)
83       : Nestable<TDZCheckCache>(&bce->innermostTDZCheckCache),
84         cache_(bce->cx->frontendCollectionPool())
85     { }
86 
87     Maybe<MaybeCheckTDZ> needsTDZCheck(BytecodeEmitter* bce, JSAtom* name);
88     MOZ_MUST_USE bool noteTDZCheck(BytecodeEmitter* bce, JSAtom* name, MaybeCheckTDZ check);
89 };
90 
91 class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::NestableControl>
92 {
93     StatementKind kind_;
94 
95     // The innermost scope when this was pushed.
96     EmitterScope* emitterScope_;
97 
98   protected:
NestableControl(BytecodeEmitter * bce,StatementKind kind)99     NestableControl(BytecodeEmitter* bce, StatementKind kind)
100       : Nestable<NestableControl>(&bce->innermostNestableControl),
101         kind_(kind),
102         emitterScope_(bce->innermostEmitterScope)
103     { }
104 
105   public:
106     using Nestable<NestableControl>::enclosing;
107     using Nestable<NestableControl>::findNearest;
108 
kind() const109     StatementKind kind() const {
110         return kind_;
111     }
112 
emitterScope() const113     EmitterScope* emitterScope() const {
114         return emitterScope_;
115     }
116 
117     template <typename T>
118     bool is() const;
119 
120     template <typename T>
as()121     T& as() {
122         MOZ_ASSERT(this->is<T>());
123         return static_cast<T&>(*this);
124     }
125 };
126 
127 // Template specializations are disallowed in different namespaces; specialize
128 // all the NestableControl subtypes up front.
129 namespace js {
130 namespace frontend {
131 
132 template <>
133 bool
is() const134 BytecodeEmitter::NestableControl::is<BreakableControl>() const
135 {
136     return StatementKindIsUnlabeledBreakTarget(kind_) || kind_ == StatementKind::Label;
137 }
138 
139 template <>
140 bool
is() const141 BytecodeEmitter::NestableControl::is<LabelControl>() const
142 {
143     return kind_ == StatementKind::Label;
144 }
145 
146 template <>
147 bool
is() const148 BytecodeEmitter::NestableControl::is<LoopControl>() const
149 {
150     return StatementKindIsLoop(kind_);
151 }
152 
153 template <>
154 bool
is() const155 BytecodeEmitter::NestableControl::is<TryFinallyControl>() const
156 {
157     return kind_ == StatementKind::Try || kind_ == StatementKind::Finally;
158 }
159 
160 } // namespace frontend
161 } // namespace js
162 
163 class BreakableControl : public BytecodeEmitter::NestableControl
164 {
165   public:
166     // Offset of the last break.
167     JumpList breaks;
168 
BreakableControl(BytecodeEmitter * bce,StatementKind kind)169     BreakableControl(BytecodeEmitter* bce, StatementKind kind)
170       : NestableControl(bce, kind)
171     {
172         MOZ_ASSERT(is<BreakableControl>());
173     }
174 
patchBreaks(BytecodeEmitter * bce)175     MOZ_MUST_USE bool patchBreaks(BytecodeEmitter* bce) {
176         return bce->emitJumpTargetAndPatch(breaks);
177     }
178 };
179 
180 class LabelControl : public BreakableControl
181 {
182     RootedAtom label_;
183 
184     // The code offset when this was pushed. Used for effectfulness checking.
185     ptrdiff_t startOffset_;
186 
187   public:
LabelControl(BytecodeEmitter * bce,JSAtom * label,ptrdiff_t startOffset)188     LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
189       : BreakableControl(bce, StatementKind::Label),
190         label_(bce->cx, label),
191         startOffset_(startOffset)
192     { }
193 
label() const194     HandleAtom label() const {
195         return label_;
196     }
197 
startOffset() const198     ptrdiff_t startOffset() const {
199         return startOffset_;
200     }
201 };
202 
203 class LoopControl : public BreakableControl
204 {
205     // Loops' children are emitted in dominance order, so they can always
206     // have a TDZCheckCache.
207     BytecodeEmitter::TDZCheckCache tdzCache_;
208 
209     // Stack depth when this loop was pushed on the control stack.
210     int32_t stackDepth_;
211 
212     // The loop nesting depth. Used as a hint to Ion.
213     uint32_t loopDepth_;
214 
215     // Can we OSR into Ion from here? True unless there is non-loop state on the stack.
216     bool canIonOsr_;
217 
218   public:
219     // The target of continue statement jumps, e.g., the update portion of a
220     // for(;;) loop.
221     JumpTarget continueTarget;
222 
223     // Offset of the last continue in the loop.
224     JumpList continues;
225 
LoopControl(BytecodeEmitter * bce,StatementKind loopKind)226     LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
227       : BreakableControl(bce, loopKind),
228         tdzCache_(bce),
229         continueTarget({ -1 })
230     {
231         MOZ_ASSERT(is<LoopControl>());
232 
233         LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
234 
235         stackDepth_ = bce->stackDepth;
236         loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
237 
238         int loopSlots;
239         if (loopKind == StatementKind::Spread)
240             loopSlots = 3;
241         else if (loopKind == StatementKind::ForInLoop || loopKind == StatementKind::ForOfLoop)
242             loopSlots = 2;
243         else
244             loopSlots = 0;
245 
246         MOZ_ASSERT(loopSlots <= stackDepth_);
247 
248         if (enclosingLoop) {
249             canIonOsr_ = (enclosingLoop->canIonOsr_ &&
250                           stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
251         } else {
252             canIonOsr_ = stackDepth_ == loopSlots;
253         }
254     }
255 
loopDepth() const256     uint32_t loopDepth() const {
257         return loopDepth_;
258     }
259 
canIonOsr() const260     bool canIonOsr() const {
261         return canIonOsr_;
262     }
263 
patchBreaksAndContinues(BytecodeEmitter * bce)264     MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce) {
265         MOZ_ASSERT(continueTarget.offset != -1);
266         if (!patchBreaks(bce))
267             return false;
268         bce->patchJumpsToTarget(continues, continueTarget);
269         return true;
270     }
271 };
272 
273 class TryFinallyControl : public BytecodeEmitter::NestableControl
274 {
275     bool emittingSubroutine_;
276 
277   public:
278     // The subroutine when emitting a finally block.
279     JumpList gosubs;
280 
281     // Offset of the last catch guard, if any.
282     JumpList guardJump;
283 
TryFinallyControl(BytecodeEmitter * bce,StatementKind kind)284     TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
285       : NestableControl(bce, kind),
286         emittingSubroutine_(false)
287     {
288         MOZ_ASSERT(is<TryFinallyControl>());
289     }
290 
setEmittingSubroutine()291     void setEmittingSubroutine() {
292         emittingSubroutine_ = true;
293     }
294 
emittingSubroutine() const295     bool emittingSubroutine() const {
296         return emittingSubroutine_;
297     }
298 };
299 
300 static bool
ScopeKindIsInBody(ScopeKind kind)301 ScopeKindIsInBody(ScopeKind kind)
302 {
303     return kind == ScopeKind::Lexical ||
304            kind == ScopeKind::SimpleCatch ||
305            kind == ScopeKind::Catch ||
306            kind == ScopeKind::With ||
307            kind == ScopeKind::FunctionBodyVar ||
308            kind == ScopeKind::ParameterExpressionVar;
309 }
310 
311 static inline void
MarkAllBindingsClosedOver(LexicalScope::Data & data)312 MarkAllBindingsClosedOver(LexicalScope::Data& data)
313 {
314     BindingName* names = data.names;
315     for (uint32_t i = 0; i < data.length; i++)
316         names[i] = BindingName(names[i].name(), true);
317 }
318 
319 // A scope that introduces bindings.
320 class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterScope>
321 {
322     // The cache of bound names that may be looked up in the
323     // scope. Initially populated as the set of names this scope binds. As
324     // names are looked up in enclosing scopes, they are cached on the
325     // current scope.
326     PooledMapPtr<NameLocationMap> nameCache_;
327 
328     // If this scope's cache does not include free names, such as the
329     // global scope, the NameLocation to return.
330     Maybe<NameLocation> fallbackFreeNameLocation_;
331 
332     // True if there is a corresponding EnvironmentObject on the environment
333     // chain, false if all bindings are stored in frame slots on the stack.
334     bool hasEnvironment_;
335 
336     // The number of enclosing environments. Used for error checking.
337     uint8_t environmentChainLength_;
338 
339     // The next usable slot on the frame for not-closed over bindings.
340     //
341     // The initial frame slot when assigning slots to bindings is the
342     // enclosing scope's nextFrameSlot. For the first scope in a frame,
343     // the initial frame slot is 0.
344     uint32_t nextFrameSlot_;
345 
346     // The index in the BytecodeEmitter's interned scope vector, otherwise
347     // ScopeNote::NoScopeIndex.
348     uint32_t scopeIndex_;
349 
350     // If kind is Lexical, Catch, or With, the index in the BytecodeEmitter's
351     // block scope note list. Otherwise ScopeNote::NoScopeNote.
352     uint32_t noteIndex_;
353 
ensureCache(BytecodeEmitter * bce)354     MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce) {
355         return nameCache_.acquire(bce->cx);
356     }
357 
358     template <typename BindingIter>
checkSlotLimits(BytecodeEmitter * bce,const BindingIter & bi)359     MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce, const BindingIter& bi) {
360         if (bi.nextFrameSlot() >= LOCALNO_LIMIT ||
361             bi.nextEnvironmentSlot() >= ENVCOORD_SLOT_LIMIT)
362         {
363             return bce->reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
364         }
365         return true;
366     }
367 
checkEnvironmentChainLength(BytecodeEmitter * bce)368     MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce) {
369         uint32_t hops;
370         if (EmitterScope* emitterScope = enclosing(&bce))
371             hops = emitterScope->environmentChainLength_;
372         else
373             hops = bce->sc->compilationEnclosingScope()->environmentChainLength();
374         if (hops >= ENVCOORD_HOPS_LIMIT - 1)
375             return bce->reportError(nullptr, JSMSG_TOO_DEEP, js_function_str);
376         environmentChainLength_ = mozilla::AssertedCast<uint8_t>(hops + 1);
377         return true;
378     }
379 
updateFrameFixedSlots(BytecodeEmitter * bce,const BindingIter & bi)380     void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi) {
381         nextFrameSlot_ = bi.nextFrameSlot();
382         if (nextFrameSlot_ > bce->maxFixedSlots)
383             bce->maxFixedSlots = nextFrameSlot_;
384         MOZ_ASSERT_IF(bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator(),
385                       bce->maxFixedSlots == 0);
386     }
387 
putNameInCache(BytecodeEmitter * bce,JSAtom * name,NameLocation loc)388     MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc) {
389         NameLocationMap& cache = *nameCache_;
390         NameLocationMap::AddPtr p = cache.lookupForAdd(name);
391         MOZ_ASSERT(!p);
392         if (!cache.add(p, name, loc)) {
393             ReportOutOfMemory(bce->cx);
394             return false;
395         }
396         return true;
397     }
398 
lookupInCache(BytecodeEmitter * bce,JSAtom * name)399     Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce, JSAtom* name) {
400         if (NameLocationMap::Ptr p = nameCache_->lookup(name))
401             return Some(p->value().wrapped);
402         if (fallbackFreeNameLocation_ && nameCanBeFree(bce, name))
403             return fallbackFreeNameLocation_;
404         return Nothing();
405     }
406 
407     friend bool BytecodeEmitter::needsImplicitThis();
408 
enclosing(BytecodeEmitter ** bce) const409     EmitterScope* enclosing(BytecodeEmitter** bce) const {
410         // There is an enclosing scope with access to the same frame.
411         if (EmitterScope* inFrame = enclosingInFrame())
412             return inFrame;
413 
414         // We are currently compiling the enclosing script, look in the
415         // enclosing BCE.
416         if ((*bce)->parent) {
417             *bce = (*bce)->parent;
418             return (*bce)->innermostEmitterScope;
419         }
420 
421         return nullptr;
422     }
423 
enclosingScope(BytecodeEmitter * bce) const424     Scope* enclosingScope(BytecodeEmitter* bce) const {
425         if (EmitterScope* es = enclosing(&bce))
426             return es->scope(bce);
427 
428         // The enclosing script is already compiled or the current script is the
429         // global script.
430         return bce->sc->compilationEnclosingScope();
431     }
432 
nameCanBeFree(BytecodeEmitter * bce,JSAtom * name)433     static bool nameCanBeFree(BytecodeEmitter* bce, JSAtom* name) {
434         // '.generator' cannot be accessed by name.
435         return name != bce->cx->names().dotGenerator;
436     }
437 
438     static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops);
439     NameLocation searchAndCache(BytecodeEmitter* bce, JSAtom* name);
440 
441     template <typename ScopeCreator>
442     MOZ_MUST_USE bool internScope(BytecodeEmitter* bce, ScopeCreator createScope);
443     template <typename ScopeCreator>
444     MOZ_MUST_USE bool internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope);
445     MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
446 
447     MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
448                                              uint32_t slotEnd);
449 
450   public:
EmitterScope(BytecodeEmitter * bce)451     explicit EmitterScope(BytecodeEmitter* bce)
452       : Nestable<EmitterScope>(&bce->innermostEmitterScope),
453         nameCache_(bce->cx->frontendCollectionPool()),
454         hasEnvironment_(false),
455         environmentChainLength_(0),
456         nextFrameSlot_(0),
457         scopeIndex_(ScopeNote::NoScopeIndex),
458         noteIndex_(ScopeNote::NoScopeNoteIndex)
459     { }
460 
461     void dump(BytecodeEmitter* bce);
462 
463     MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
464                                    Handle<LexicalScope::Data*> bindings);
465     MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
466     MOZ_MUST_USE bool enterComprehensionFor(BytecodeEmitter* bce,
467                                             Handle<LexicalScope::Data*> bindings);
468     MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
469     MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox);
470     MOZ_MUST_USE bool enterParameterExpressionVar(BytecodeEmitter* bce);
471     MOZ_MUST_USE bool enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc);
472     MOZ_MUST_USE bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
473     MOZ_MUST_USE bool enterModule(BytecodeEmitter* module, ModuleSharedContext* modulesc);
474     MOZ_MUST_USE bool enterWith(BytecodeEmitter* bce);
475     MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce);
476 
477     MOZ_MUST_USE bool leave(BytecodeEmitter* bce, bool nonLocal = false);
478 
index() const479     uint32_t index() const {
480         MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex, "Did you forget to intern a Scope?");
481         return scopeIndex_;
482     }
483 
noteIndex() const484     uint32_t noteIndex() const {
485         return noteIndex_;
486     }
487 
scope(const BytecodeEmitter * bce) const488     Scope* scope(const BytecodeEmitter* bce) const {
489         return bce->scopeList.vector[index()];
490     }
491 
hasEnvironment() const492     bool hasEnvironment() const {
493         return hasEnvironment_;
494     }
495 
496     // The first frame slot used.
frameSlotStart() const497     uint32_t frameSlotStart() const {
498         if (EmitterScope* inFrame = enclosingInFrame())
499             return inFrame->nextFrameSlot_;
500         return 0;
501     }
502 
503     // The last frame slot used + 1.
frameSlotEnd() const504     uint32_t frameSlotEnd() const {
505         return nextFrameSlot_;
506     }
507 
numFrameSlots() const508     uint32_t numFrameSlots() const {
509         return frameSlotEnd() - frameSlotStart();
510     }
511 
enclosingInFrame() const512     EmitterScope* enclosingInFrame() const {
513         return Nestable<EmitterScope>::enclosing();
514     }
515 
lookup(BytecodeEmitter * bce,JSAtom * name)516     NameLocation lookup(BytecodeEmitter* bce, JSAtom* name) {
517         if (Maybe<NameLocation> loc = lookupInCache(bce, name))
518             return *loc;
519         return searchAndCache(bce, name);
520     }
521 
522     Maybe<NameLocation> locationBoundInScope(BytecodeEmitter* bce, JSAtom* name,
523                                              EmitterScope* target);
524 };
525 
526 void
dump(BytecodeEmitter * bce)527 BytecodeEmitter::EmitterScope::dump(BytecodeEmitter* bce)
528 {
529     fprintf(stdout, "EmitterScope [%s] %p\n", ScopeKindString(scope(bce)->kind()), this);
530 
531     for (NameLocationMap::Range r = nameCache_->all(); !r.empty(); r.popFront()) {
532         const NameLocation& l = r.front().value();
533 
534         JSAutoByteString bytes;
535         if (!AtomToPrintableString(bce->cx, r.front().key(), &bytes))
536             return;
537         if (l.kind() != NameLocation::Kind::Dynamic)
538             fprintf(stdout, "  %s %s ", BindingKindString(l.bindingKind()), bytes.ptr());
539         else
540             fprintf(stdout, "  %s ", bytes.ptr());
541 
542         switch (l.kind()) {
543           case NameLocation::Kind::Dynamic:
544             fprintf(stdout, "dynamic\n");
545             break;
546           case NameLocation::Kind::Global:
547             fprintf(stdout, "global\n");
548             break;
549           case NameLocation::Kind::Intrinsic:
550             fprintf(stdout, "intrinsic\n");
551             break;
552           case NameLocation::Kind::NamedLambdaCallee:
553             fprintf(stdout, "named lambda callee\n");
554             break;
555           case NameLocation::Kind::Import:
556             fprintf(stdout, "import\n");
557             break;
558           case NameLocation::Kind::ArgumentSlot:
559             fprintf(stdout, "arg slot=%u\n", l.argumentSlot());
560             break;
561           case NameLocation::Kind::FrameSlot:
562             fprintf(stdout, "frame slot=%u\n", l.frameSlot());
563             break;
564           case NameLocation::Kind::EnvironmentCoordinate:
565             fprintf(stdout, "environment hops=%u slot=%u\n",
566                     l.environmentCoordinate().hops(), l.environmentCoordinate().slot());
567             break;
568           case NameLocation::Kind::DynamicAnnexBVar:
569             fprintf(stdout, "dynamic annex b var\n");
570             break;
571         }
572     }
573 
574     fprintf(stdout, "\n");
575 }
576 
577 template <typename ScopeCreator>
578 bool
internScope(BytecodeEmitter * bce,ScopeCreator createScope)579 BytecodeEmitter::EmitterScope::internScope(BytecodeEmitter* bce, ScopeCreator createScope)
580 {
581     RootedScope enclosing(bce->cx, enclosingScope(bce));
582     Scope* scope = createScope(bce->cx, enclosing);
583     if (!scope)
584         return false;
585     hasEnvironment_ = scope->hasEnvironment();
586     scopeIndex_ = bce->scopeList.length();
587     return bce->scopeList.append(scope);
588 }
589 
590 template <typename ScopeCreator>
591 bool
internBodyScope(BytecodeEmitter * bce,ScopeCreator createScope)592 BytecodeEmitter::EmitterScope::internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope)
593 {
594     MOZ_ASSERT(bce->bodyScopeIndex == UINT32_MAX, "There can be only one body scope");
595     bce->bodyScopeIndex = bce->scopeList.length();
596     return internScope(bce, createScope);
597 }
598 
599 bool
appendScopeNote(BytecodeEmitter * bce)600 BytecodeEmitter::EmitterScope::appendScopeNote(BytecodeEmitter* bce)
601 {
602     MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
603                "Scope notes are not needed for body-level scopes.");
604     noteIndex_ = bce->scopeNoteList.length();
605     return bce->scopeNoteList.append(index(), bce->offset(), bce->inPrologue(),
606                                      enclosingInFrame() ? enclosingInFrame()->noteIndex()
607                                                         : ScopeNote::NoScopeNoteIndex);
608 }
609 
610 #ifdef DEBUG
611 static bool
NameIsOnEnvironment(Scope * scope,JSAtom * name)612 NameIsOnEnvironment(Scope* scope, JSAtom* name)
613 {
614     for (BindingIter bi(scope); bi; bi++) {
615         // If found, the name must already be on the environment or an import,
616         // or else there is a bug in the closed-over name analysis in the
617         // Parser.
618         if (bi.name() == name) {
619             BindingLocation::Kind kind = bi.location().kind();
620 
621             if (bi.hasArgumentSlot()) {
622                 JSScript* script = scope->as<FunctionScope>().script();
623                 if (!script->strict() && !script->functionHasParameterExprs()) {
624                     // Check for duplicate positional formal parameters.
625                     for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
626                         if (bi2.name() == name)
627                             kind = bi2.location().kind();
628                     }
629                 }
630             }
631 
632             return kind == BindingLocation::Kind::Global ||
633                    kind == BindingLocation::Kind::Environment ||
634                    kind == BindingLocation::Kind::Import;
635         }
636     }
637 
638     // If not found, assume it's on the global or dynamically accessed.
639     return true;
640 }
641 #endif
642 
643 /* static */ NameLocation
searchInEnclosingScope(JSAtom * name,Scope * scope,uint8_t hops)644 BytecodeEmitter::EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops)
645 {
646     for (ScopeIter si(scope); si; si++) {
647         MOZ_ASSERT(NameIsOnEnvironment(si.scope(), name));
648 
649         bool hasEnv = si.hasSyntacticEnvironment();
650 
651         switch (si.kind()) {
652           case ScopeKind::Function:
653             if (hasEnv) {
654                 JSScript* script = si.scope()->as<FunctionScope>().script();
655                 if (script->funHasExtensibleScope())
656                     return NameLocation::Dynamic();
657 
658                 for (BindingIter bi(si.scope()); bi; bi++) {
659                     if (bi.name() != name)
660                         continue;
661 
662                     BindingLocation bindLoc = bi.location();
663                     if (bi.hasArgumentSlot() &&
664                         !script->strict() &&
665                         !script->functionHasParameterExprs())
666                     {
667                         // Check for duplicate positional formal parameters.
668                         for (BindingIter bi2(bi); bi2 && bi2.hasArgumentSlot(); bi2++) {
669                             if (bi2.name() == name)
670                                 bindLoc = bi2.location();
671                         }
672                     }
673 
674                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
675                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
676                 }
677             }
678             break;
679 
680           case ScopeKind::FunctionBodyVar:
681           case ScopeKind::ParameterExpressionVar:
682           case ScopeKind::Lexical:
683           case ScopeKind::NamedLambda:
684           case ScopeKind::StrictNamedLambda:
685           case ScopeKind::SimpleCatch:
686           case ScopeKind::Catch:
687             if (hasEnv) {
688                 for (BindingIter bi(si.scope()); bi; bi++) {
689                     if (bi.name() != name)
690                         continue;
691 
692                     // The name must already have been marked as closed
693                     // over. If this assertion is hit, there is a bug in the
694                     // name analysis.
695                     BindingLocation bindLoc = bi.location();
696                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
697                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
698                 }
699             }
700             break;
701 
702           case ScopeKind::Module:
703             if (hasEnv) {
704                 for (BindingIter bi(si.scope()); bi; bi++) {
705                     if (bi.name() != name)
706                         continue;
707 
708                     BindingLocation bindLoc = bi.location();
709 
710                     // Imports are on the environment but are indirect
711                     // bindings and must be accessed dynamically instead of
712                     // using an EnvironmentCoordinate.
713                     if (bindLoc.kind() == BindingLocation::Kind::Import) {
714                         MOZ_ASSERT(si.kind() == ScopeKind::Module);
715                         return NameLocation::Import();
716                     }
717 
718                     MOZ_ASSERT(bindLoc.kind() == BindingLocation::Kind::Environment);
719                     return NameLocation::EnvironmentCoordinate(bi.kind(), hops, bindLoc.slot());
720                 }
721             }
722             break;
723 
724           case ScopeKind::Eval:
725           case ScopeKind::StrictEval:
726             // As an optimization, if the eval doesn't have its own var
727             // environment and its immediate enclosing scope is a global
728             // scope, all accesses are global.
729             if (!hasEnv && si.scope()->enclosing()->is<GlobalScope>())
730                 return NameLocation::Global(BindingKind::Var);
731             return NameLocation::Dynamic();
732 
733           case ScopeKind::Global:
734             return NameLocation::Global(BindingKind::Var);
735 
736           case ScopeKind::With:
737           case ScopeKind::NonSyntactic:
738             return NameLocation::Dynamic();
739         }
740 
741         if (hasEnv) {
742             MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT - 1);
743             hops++;
744         }
745     }
746 
747     MOZ_CRASH("Malformed scope chain");
748 }
749 
750 NameLocation
searchAndCache(BytecodeEmitter * bce,JSAtom * name)751 BytecodeEmitter::EmitterScope::searchAndCache(BytecodeEmitter* bce, JSAtom* name)
752 {
753     Maybe<NameLocation> loc;
754     uint8_t hops = hasEnvironment() ? 1 : 0;
755     DebugOnly<bool> inCurrentScript = enclosingInFrame();
756 
757     // Start searching in the current compilation.
758     for (EmitterScope* es = enclosing(&bce); es; es = es->enclosing(&bce)) {
759         loc = es->lookupInCache(bce, name);
760         if (loc) {
761             if (loc->kind() == NameLocation::Kind::EnvironmentCoordinate)
762                 *loc = loc->addHops(hops);
763             break;
764         }
765 
766         if (es->hasEnvironment())
767             hops++;
768 
769 #ifdef DEBUG
770         if (!es->enclosingInFrame())
771             inCurrentScript = false;
772 #endif
773     }
774 
775     // If the name is not found in the current compilation, walk the Scope
776     // chain encompassing the compilation.
777     if (!loc) {
778         inCurrentScript = false;
779         loc = Some(searchInEnclosingScope(name, bce->sc->compilationEnclosingScope(), hops));
780     }
781 
782     // Each script has its own frame. A free name that is accessed
783     // from an inner script must not be a frame slot access. If this
784     // assertion is hit, it is a bug in the free name analysis in the
785     // parser.
786     MOZ_ASSERT_IF(!inCurrentScript, loc->kind() != NameLocation::Kind::FrameSlot);
787 
788     // It is always correct to not cache the location. Ignore OOMs to make
789     // lookups infallible.
790     if (!putNameInCache(bce, name, *loc))
791         bce->cx->recoverFromOutOfMemory();
792 
793     return *loc;
794 }
795 
796 Maybe<NameLocation>
locationBoundInScope(BytecodeEmitter * bce,JSAtom * name,EmitterScope * target)797 BytecodeEmitter::EmitterScope::locationBoundInScope(BytecodeEmitter* bce, JSAtom* name,
798                                                     EmitterScope* target)
799 {
800     // The target scope must be an intra-frame enclosing scope of this
801     // one. Count the number of extra hops to reach it.
802     uint8_t extraHops = 0;
803     for (EmitterScope* es = this; es != target; es = es->enclosingInFrame()) {
804         if (es->hasEnvironment())
805             extraHops++;
806     }
807 
808     // Caches are prepopulated with bound names. So if the name is bound in a
809     // particular scope, it must already be in the cache. Furthermore, don't
810     // consult the fallback location as we only care about binding names.
811     Maybe<NameLocation> loc;
812     if (NameLocationMap::Ptr p = target->nameCache_->lookup(name)) {
813         NameLocation l = p->value().wrapped;
814         if (l.kind() == NameLocation::Kind::EnvironmentCoordinate)
815             loc = Some(l.addHops(extraHops));
816         else
817             loc = Some(l);
818     }
819     return loc;
820 }
821 
822 bool
deadZoneFrameSlotRange(BytecodeEmitter * bce,uint32_t slotStart,uint32_t slotEnd)823 BytecodeEmitter::EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
824                                                       uint32_t slotEnd)
825 {
826     // Lexical bindings throw ReferenceErrors if they are used before
827     // initialization. See ES6 8.1.1.1.6.
828     //
829     // For completeness, lexical bindings are initialized in ES6 by calling
830     // InitializeBinding, after which touching the binding will no longer
831     // throw reference errors. See 13.1.11, 9.2.13, 13.6.3.4, 13.6.4.6,
832     // 13.6.4.8, 13.14.5, 15.1.8, and 15.2.0.15.
833     if (slotStart != slotEnd) {
834         if (!bce->emit1(JSOP_UNINITIALIZED))
835             return false;
836         for (uint32_t slot = slotStart; slot < slotEnd; slot++) {
837             if (!bce->emitLocalOp(JSOP_INITLEXICAL, slot))
838                 return false;
839         }
840         if (!bce->emit1(JSOP_POP))
841             return false;
842     }
843 
844     return true;
845 }
846 
847 bool
deadZoneFrameSlots(BytecodeEmitter * bce)848 BytecodeEmitter::EmitterScope::deadZoneFrameSlots(BytecodeEmitter* bce)
849 {
850     return deadZoneFrameSlotRange(bce, frameSlotStart(), frameSlotEnd());
851 }
852 
853 bool
enterLexical(BytecodeEmitter * bce,ScopeKind kind,Handle<LexicalScope::Data * > bindings)854 BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
855                                             Handle<LexicalScope::Data*> bindings)
856 {
857     MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
858     MOZ_ASSERT(this == bce->innermostEmitterScope);
859 
860     if (!ensureCache(bce))
861         return false;
862 
863     // Marks all names as closed over if the the context requires it. This
864     // cannot be done in the Parser as we may not know if the context requires
865     // all bindings to be closed over until after parsing is finished. For
866     // example, legacy generators require all bindings to be closed over but
867     // it is unknown if a function is a legacy generator until the first
868     // 'yield' expression is parsed.
869     //
870     // This is not a problem with other scopes, as all other scopes with
871     // bindings are body-level. At the time of their creation, whether or not
872     // the context requires all bindings to be closed over is already known.
873     if (bce->sc->allBindingsClosedOver())
874         MarkAllBindingsClosedOver(*bindings);
875 
876     // Resolve bindings.
877     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
878     uint32_t firstFrameSlot = frameSlotStart();
879     BindingIter bi(*bindings, firstFrameSlot, /* isNamedLambda = */ false);
880     for (; bi; bi++) {
881         if (!checkSlotLimits(bce, bi))
882             return false;
883 
884         NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
885         if (!putNameInCache(bce, bi.name(), loc))
886             return false;
887 
888         if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
889             return false;
890     }
891 
892     updateFrameFixedSlots(bce, bi);
893 
894     // Create and intern the VM scope.
895     auto createScope = [kind, bindings, firstFrameSlot](ExclusiveContext* cx,
896                                                         HandleScope enclosing)
897     {
898         return LexicalScope::create(cx, kind, bindings, firstFrameSlot, enclosing);
899     };
900     if (!internScope(bce, createScope))
901         return false;
902 
903     if (ScopeKindIsInBody(kind) && hasEnvironment()) {
904         // After interning the VM scope we can get the scope index.
905         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHLEXICALENV))
906             return false;
907     }
908 
909     // Lexical scopes need notes to be mapped from a pc.
910     if (!appendScopeNote(bce))
911         return false;
912 
913     // Put frame slots in TDZ. Environment slots are poisoned during
914     // environment creation.
915     //
916     // This must be done after appendScopeNote to be considered in the extent
917     // of the scope.
918     if (!deadZoneFrameSlotRange(bce, firstFrameSlot, frameSlotEnd()))
919         return false;
920 
921     return checkEnvironmentChainLength(bce);
922 }
923 
924 bool
enterNamedLambda(BytecodeEmitter * bce,FunctionBox * funbox)925 BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
926 {
927     MOZ_ASSERT(this == bce->innermostEmitterScope);
928     MOZ_ASSERT(funbox->namedLambdaBindings());
929 
930     if (!ensureCache(bce))
931         return false;
932 
933     // See comment in enterLexical about allBindingsClosedOver.
934     if (funbox->allBindingsClosedOver())
935         MarkAllBindingsClosedOver(*funbox->namedLambdaBindings());
936 
937     BindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT, /* isNamedLambda = */ true);
938     MOZ_ASSERT(bi.kind() == BindingKind::NamedLambdaCallee);
939 
940     // The lambda name, if not closed over, is accessed via JSOP_CALLEE and
941     // not a frame slot. Do not update frame slot information.
942     NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
943     if (!putNameInCache(bce, bi.name(), loc))
944         return false;
945 
946     bi++;
947     MOZ_ASSERT(!bi, "There should be exactly one binding in a NamedLambda scope");
948 
949     auto createScope = [funbox](ExclusiveContext* cx, HandleScope enclosing) {
950         ScopeKind scopeKind =
951             funbox->strict() ? ScopeKind::StrictNamedLambda : ScopeKind::NamedLambda;
952         return LexicalScope::create(cx, scopeKind, funbox->namedLambdaBindings(),
953                                     LOCALNO_LIMIT, enclosing);
954     };
955     if (!internScope(bce, createScope))
956         return false;
957 
958     return checkEnvironmentChainLength(bce);
959 }
960 
961 bool
enterComprehensionFor(BytecodeEmitter * bce,Handle<LexicalScope::Data * > bindings)962 BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce,
963                                                      Handle<LexicalScope::Data*> bindings)
964 {
965     if (!enterLexical(bce, ScopeKind::Lexical, bindings))
966         return false;
967 
968     // For comprehensions, initialize all lexical names up front to undefined
969     // because they're now a dead feature and don't interact properly with
970     // TDZ.
971     auto nop = [](BytecodeEmitter*, const NameLocation&, bool) {
972         return true;
973     };
974 
975     if (!bce->emit1(JSOP_UNDEFINED))
976         return false;
977 
978     RootedAtom name(bce->cx);
979     for (BindingIter bi(*bindings, frameSlotStart(), /* isNamedLambda = */ false); bi; bi++) {
980         name = bi.name();
981         if (!bce->emitInitializeName(name, nop))
982             return false;
983     }
984 
985     if (!bce->emit1(JSOP_POP))
986         return false;
987 
988     return true;
989 }
990 
991 bool
enterParameterExpressionVar(BytecodeEmitter * bce)992 BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
993 {
994     MOZ_ASSERT(this == bce->innermostEmitterScope);
995 
996     if (!ensureCache(bce))
997         return false;
998 
999     // Parameter expressions var scopes have no pre-set bindings and are
1000     // always extensible, as they are needed for eval.
1001     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1002 
1003     // Create and intern the VM scope.
1004     uint32_t firstFrameSlot = frameSlotStart();
1005     auto createScope = [firstFrameSlot](ExclusiveContext* cx, HandleScope enclosing) {
1006         return VarScope::create(cx, ScopeKind::ParameterExpressionVar,
1007                                 /* data = */ nullptr, firstFrameSlot,
1008                                 /* needsEnvironment = */ true, enclosing);
1009     };
1010     if (!internScope(bce, createScope))
1011         return false;
1012 
1013     MOZ_ASSERT(hasEnvironment());
1014     if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
1015         return false;
1016 
1017     // The extra var scope needs a note to be mapped from a pc.
1018     if (!appendScopeNote(bce))
1019         return false;
1020 
1021     return checkEnvironmentChainLength(bce);
1022 }
1023 
1024 bool
enterFunction(BytecodeEmitter * bce,FunctionBox * funbox)1025 BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox)
1026 {
1027     MOZ_ASSERT(this == bce->innermostEmitterScope);
1028 
1029     // If there are parameter expressions, there is an extra var scope.
1030     if (!funbox->hasExtraBodyVarScope())
1031         bce->setVarEmitterScope(this);
1032 
1033     if (!ensureCache(bce))
1034         return false;
1035 
1036     // Resolve body-level bindings, if there are any.
1037     auto bindings = funbox->functionScopeBindings();
1038     Maybe<uint32_t> lastLexicalSlot;
1039     if (bindings) {
1040         NameLocationMap& cache = *nameCache_;
1041 
1042         BindingIter bi(*bindings, funbox->hasParameterExprs);
1043         for (; bi; bi++) {
1044             if (!checkSlotLimits(bce, bi))
1045                 return false;
1046 
1047             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
1048             NameLocationMap::AddPtr p = cache.lookupForAdd(bi.name());
1049 
1050             // The only duplicate bindings that occur are simple formal
1051             // parameters, in which case the last position counts, so update the
1052             // location.
1053             if (p) {
1054                 MOZ_ASSERT(bi.kind() == BindingKind::FormalParameter);
1055                 MOZ_ASSERT(!funbox->hasDestructuringArgs);
1056                 MOZ_ASSERT(!funbox->function()->hasRest());
1057                 p->value() = loc;
1058                 continue;
1059             }
1060 
1061             if (!cache.add(p, bi.name(), loc)) {
1062                 ReportOutOfMemory(bce->cx);
1063                 return false;
1064             }
1065         }
1066 
1067         updateFrameFixedSlots(bce, bi);
1068     } else {
1069         nextFrameSlot_ = 0;
1070     }
1071 
1072     // If the function's scope may be extended at runtime due to sloppy direct
1073     // eval and there is no extra var scope, any names beyond the function
1074     // scope must be accessed dynamically as we don't know if the name will
1075     // become a 'var' binding due to direct eval.
1076     if (!funbox->hasParameterExprs && funbox->hasExtensibleScope())
1077         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1078 
1079     // In case of parameter expressions, the parameters are lexical
1080     // bindings and have TDZ.
1081     if (funbox->hasParameterExprs && nextFrameSlot_) {
1082         uint32_t paramFrameSlotEnd = 0;
1083         for (BindingIter bi(*bindings, true); bi; bi++) {
1084             if (!BindingKindIsLexical(bi.kind()))
1085                 break;
1086 
1087             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
1088             if (loc.kind() == NameLocation::Kind::FrameSlot) {
1089                 MOZ_ASSERT(paramFrameSlotEnd <= loc.frameSlot());
1090                 paramFrameSlotEnd = loc.frameSlot() + 1;
1091             }
1092         }
1093 
1094         if (!deadZoneFrameSlotRange(bce, 0, paramFrameSlotEnd))
1095             return false;
1096     }
1097 
1098     // Create and intern the VM scope.
1099     auto createScope = [funbox](ExclusiveContext* cx, HandleScope enclosing) {
1100         RootedFunction fun(cx, funbox->function());
1101         return FunctionScope::create(cx, funbox->functionScopeBindings(),
1102                                      funbox->hasParameterExprs,
1103                                      funbox->needsCallObjectRegardlessOfBindings(),
1104                                      fun, enclosing);
1105     };
1106     if (!internBodyScope(bce, createScope))
1107         return false;
1108 
1109     return checkEnvironmentChainLength(bce);
1110 }
1111 
1112 bool
enterFunctionExtraBodyVar(BytecodeEmitter * bce,FunctionBox * funbox)1113 BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox)
1114 {
1115     MOZ_ASSERT(funbox->hasParameterExprs);
1116     MOZ_ASSERT(funbox->extraVarScopeBindings() ||
1117                funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings());
1118     MOZ_ASSERT(this == bce->innermostEmitterScope);
1119 
1120     // The extra var scope is never popped once it's entered. It replaces the
1121     // function scope as the var emitter scope.
1122     bce->setVarEmitterScope(this);
1123 
1124     if (!ensureCache(bce))
1125         return false;
1126 
1127     // Resolve body-level bindings, if there are any.
1128     uint32_t firstFrameSlot = frameSlotStart();
1129     if (auto bindings = funbox->extraVarScopeBindings()) {
1130         BindingIter bi(*bindings, firstFrameSlot);
1131         for (; bi; bi++) {
1132             if (!checkSlotLimits(bce, bi))
1133                 return false;
1134 
1135             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
1136             if (!putNameInCache(bce, bi.name(), loc))
1137                 return false;
1138         }
1139 
1140         updateFrameFixedSlots(bce, bi);
1141     } else {
1142         nextFrameSlot_ = firstFrameSlot;
1143     }
1144 
1145     // If the extra var scope may be extended at runtime due to sloppy
1146     // direct eval, any names beyond the var scope must be accessed
1147     // dynamically as we don't know if the name will become a 'var' binding
1148     // due to direct eval.
1149     if (funbox->hasExtensibleScope())
1150         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1151 
1152     // Create and intern the VM scope.
1153     auto createScope = [funbox, firstFrameSlot](ExclusiveContext* cx, HandleScope enclosing) {
1154         return VarScope::create(cx, ScopeKind::FunctionBodyVar,
1155                                 funbox->extraVarScopeBindings(), firstFrameSlot,
1156                                 funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(),
1157                                 enclosing);
1158     };
1159     if (!internScope(bce, createScope))
1160         return false;
1161 
1162     if (hasEnvironment()) {
1163         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
1164             return false;
1165     }
1166 
1167     // The extra var scope needs a note to be mapped from a pc.
1168     if (!appendScopeNote(bce))
1169         return false;
1170 
1171     return checkEnvironmentChainLength(bce);
1172 }
1173 
1174 class DynamicBindingIter : public BindingIter
1175 {
1176   public:
DynamicBindingIter(GlobalSharedContext * sc)1177     explicit DynamicBindingIter(GlobalSharedContext* sc)
1178       : BindingIter(*sc->bindings)
1179     { }
1180 
DynamicBindingIter(EvalSharedContext * sc)1181     explicit DynamicBindingIter(EvalSharedContext* sc)
1182       : BindingIter(*sc->bindings, /* strict = */ false)
1183     {
1184         MOZ_ASSERT(!sc->strict());
1185     }
1186 
bindingOp() const1187     JSOp bindingOp() const {
1188         switch (kind()) {
1189           case BindingKind::Var:
1190             return JSOP_DEFVAR;
1191           case BindingKind::Let:
1192             return JSOP_DEFLET;
1193           case BindingKind::Const:
1194             return JSOP_DEFCONST;
1195           default:
1196             MOZ_CRASH("Bad BindingKind");
1197         }
1198     }
1199 };
1200 
1201 bool
enterGlobal(BytecodeEmitter * bce,GlobalSharedContext * globalsc)1202 BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
1203 {
1204     MOZ_ASSERT(this == bce->innermostEmitterScope);
1205 
1206     bce->setVarEmitterScope(this);
1207 
1208     if (!ensureCache(bce))
1209         return false;
1210 
1211     if (bce->emitterMode == BytecodeEmitter::SelfHosting) {
1212         // In self-hosting, it is incorrect to consult the global scope because
1213         // self-hosted scripts are cloned into their target compartments before
1214         // they are run. Instead of Global, Intrinsic is used for all names.
1215         //
1216         // Intrinsic lookups are redirected to the special intrinsics holder
1217         // in the global object, into which any missing values are cloned
1218         // lazily upon first access.
1219         fallbackFreeNameLocation_ = Some(NameLocation::Intrinsic());
1220 
1221         auto createScope = [](ExclusiveContext* cx, HandleScope enclosing) {
1222             MOZ_ASSERT(!enclosing);
1223             return &cx->global()->emptyGlobalScope();
1224         };
1225         return internBodyScope(bce, createScope);
1226     }
1227 
1228     // Resolve binding names and emit DEF{VAR,LET,CONST} prologue ops.
1229     if (globalsc->bindings) {
1230         for (DynamicBindingIter bi(globalsc); bi; bi++) {
1231             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
1232             JSAtom* name = bi.name();
1233             if (!putNameInCache(bce, name, loc))
1234                 return false;
1235 
1236             // Define the name in the prologue. Do not emit DEFVAR for
1237             // functions that we'll emit DEFFUN for.
1238             if (bi.isTopLevelFunction())
1239                 continue;
1240 
1241             if (!bce->emitAtomOp(name, bi.bindingOp()))
1242                 return false;
1243         }
1244     }
1245 
1246     // Note that to save space, we don't add free names to the cache for
1247     // global scopes. They are assumed to be global vars in the syntactic
1248     // global scope, dynamic accesses under non-syntactic global scope.
1249     if (globalsc->scopeKind() == ScopeKind::Global)
1250         fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
1251     else
1252         fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1253 
1254     auto createScope = [globalsc](ExclusiveContext* cx, HandleScope enclosing) {
1255         MOZ_ASSERT(!enclosing);
1256         return GlobalScope::create(cx, globalsc->scopeKind(), globalsc->bindings);
1257     };
1258     return internBodyScope(bce, createScope);
1259 }
1260 
1261 bool
enterEval(BytecodeEmitter * bce,EvalSharedContext * evalsc)1262 BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
1263 {
1264     MOZ_ASSERT(this == bce->innermostEmitterScope);
1265 
1266     bce->setVarEmitterScope(this);
1267 
1268     if (!ensureCache(bce))
1269         return false;
1270 
1271     // For simplicity, treat all free name lookups in eval scripts as dynamic.
1272     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1273 
1274     // Create the `var` scope. Note that there is also a lexical scope, created
1275     // separately in emitScript().
1276     auto createScope = [evalsc](ExclusiveContext* cx, HandleScope enclosing) {
1277         ScopeKind scopeKind = evalsc->strict() ? ScopeKind::StrictEval : ScopeKind::Eval;
1278         return EvalScope::create(cx, scopeKind, evalsc->bindings, enclosing);
1279     };
1280     if (!internBodyScope(bce, createScope))
1281         return false;
1282 
1283     if (hasEnvironment()) {
1284         if (!bce->emitInternedScopeOp(index(), JSOP_PUSHVARENV))
1285             return false;
1286     } else {
1287         // Resolve binding names and emit DEFVAR prologue ops if we don't have
1288         // an environment (i.e., a sloppy eval not in a parameter expression).
1289         // Eval scripts always have their own lexical scope, but non-strict
1290         // scopes may introduce 'var' bindings to the nearest var scope.
1291         //
1292         // TODO: We may optimize strict eval bindings in the future to be on
1293         // the frame. For now, handle everything dynamically.
1294         if (!hasEnvironment() && evalsc->bindings) {
1295             for (DynamicBindingIter bi(evalsc); bi; bi++) {
1296                 MOZ_ASSERT(bi.bindingOp() == JSOP_DEFVAR);
1297 
1298                 if (bi.isTopLevelFunction())
1299                     continue;
1300 
1301                 if (!bce->emitAtomOp(bi.name(), JSOP_DEFVAR))
1302                     return false;
1303             }
1304         }
1305 
1306         // As an optimization, if the eval does not have its own var
1307         // environment and is directly enclosed in a global scope, then all
1308         // free name lookups are global.
1309         if (scope(bce)->enclosing()->is<GlobalScope>())
1310             fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
1311     }
1312 
1313     return true;
1314 }
1315 
1316 bool
enterModule(BytecodeEmitter * bce,ModuleSharedContext * modulesc)1317 BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
1318 {
1319     MOZ_ASSERT(this == bce->innermostEmitterScope);
1320 
1321     bce->setVarEmitterScope(this);
1322 
1323     if (!ensureCache(bce))
1324         return false;
1325 
1326     // Resolve body-level bindings, if there are any.
1327     TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
1328     Maybe<uint32_t> firstLexicalFrameSlot;
1329     if (ModuleScope::Data* bindings = modulesc->bindings) {
1330         BindingIter bi(*bindings);
1331         for (; bi; bi++) {
1332             if (!checkSlotLimits(bce, bi))
1333                 return false;
1334 
1335             NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
1336             if (!putNameInCache(bce, bi.name(), loc))
1337                 return false;
1338 
1339             if (BindingKindIsLexical(bi.kind())) {
1340                 if (loc.kind() == NameLocation::Kind::FrameSlot && !firstLexicalFrameSlot)
1341                     firstLexicalFrameSlot = Some(loc.frameSlot());
1342 
1343                 if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ))
1344                     return false;
1345             }
1346         }
1347 
1348         updateFrameFixedSlots(bce, bi);
1349     } else {
1350         nextFrameSlot_ = 0;
1351     }
1352 
1353     // Modules are toplevel, so any free names are global.
1354     fallbackFreeNameLocation_ = Some(NameLocation::Global(BindingKind::Var));
1355 
1356     // Put lexical frame slots in TDZ. Environment slots are poisoned during
1357     // environment creation.
1358     if (firstLexicalFrameSlot) {
1359         if (!deadZoneFrameSlotRange(bce, *firstLexicalFrameSlot, frameSlotEnd()))
1360             return false;
1361     }
1362 
1363     // Create and intern the VM scope.
1364     auto createScope = [modulesc](ExclusiveContext* cx, HandleScope enclosing) {
1365         return ModuleScope::create(cx, modulesc->bindings, modulesc->module(), enclosing);
1366     };
1367     if (!internBodyScope(bce, createScope))
1368         return false;
1369 
1370     return checkEnvironmentChainLength(bce);
1371 }
1372 
1373 bool
enterWith(BytecodeEmitter * bce)1374 BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
1375 {
1376     MOZ_ASSERT(this == bce->innermostEmitterScope);
1377 
1378     if (!ensureCache(bce))
1379         return false;
1380 
1381     // 'with' make all accesses dynamic and unanalyzable.
1382     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
1383 
1384     auto createScope = [](ExclusiveContext* cx, HandleScope enclosing) {
1385         return WithScope::create(cx, enclosing);
1386     };
1387     if (!internScope(bce, createScope))
1388         return false;
1389 
1390     if (!bce->emitInternedScopeOp(index(), JSOP_ENTERWITH))
1391         return false;
1392 
1393     if (!appendScopeNote(bce))
1394         return false;
1395 
1396     return checkEnvironmentChainLength(bce);
1397 }
1398 
1399 bool
leave(BytecodeEmitter * bce,bool nonLocal)1400 BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
1401 {
1402     // If we aren't leaving the scope due to a non-local jump (e.g., break),
1403     // we must be the innermost scope.
1404     MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope);
1405 
1406     ScopeKind kind = scope(bce)->kind();
1407     switch (kind) {
1408       case ScopeKind::Lexical:
1409       case ScopeKind::SimpleCatch:
1410       case ScopeKind::Catch:
1411         if (!bce->emit1(hasEnvironment() ? JSOP_POPLEXICALENV : JSOP_DEBUGLEAVELEXICALENV))
1412             return false;
1413         break;
1414 
1415       case ScopeKind::With:
1416         if (!bce->emit1(JSOP_LEAVEWITH))
1417             return false;
1418         break;
1419 
1420       case ScopeKind::ParameterExpressionVar:
1421         MOZ_ASSERT(hasEnvironment());
1422         if (!bce->emit1(JSOP_POPVARENV))
1423             return false;
1424         break;
1425 
1426       case ScopeKind::Function:
1427       case ScopeKind::FunctionBodyVar:
1428       case ScopeKind::NamedLambda:
1429       case ScopeKind::StrictNamedLambda:
1430       case ScopeKind::Eval:
1431       case ScopeKind::StrictEval:
1432       case ScopeKind::Global:
1433       case ScopeKind::NonSyntactic:
1434       case ScopeKind::Module:
1435         break;
1436     }
1437 
1438     // Finish up the scope if we are leaving it in LIFO fashion.
1439     if (!nonLocal) {
1440         // Popping scopes due to non-local jumps generate additional scope
1441         // notes. See NonLocalExitControl::prepareForNonLocalJump.
1442         if (ScopeKindIsInBody(kind)) {
1443             // The extra function var scope is never popped once it's pushed,
1444             // so its scope note extends until the end of any possible code.
1445             uint32_t offset = kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
1446             bce->scopeNoteList.recordEnd(noteIndex_, offset, bce->inPrologue());
1447         }
1448     }
1449 
1450     return true;
1451 }
1452 
1453 Maybe<MaybeCheckTDZ>
needsTDZCheck(BytecodeEmitter * bce,JSAtom * name)1454 BytecodeEmitter::TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name)
1455 {
1456     if (!ensureCache(bce))
1457         return Nothing();
1458 
1459     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
1460     if (p)
1461         return Some(p->value().wrapped);
1462 
1463     MaybeCheckTDZ rv = CheckTDZ;
1464     for (TDZCheckCache* it = enclosing(); it; it = it->enclosing()) {
1465         if (it->cache_) {
1466             if (CheckTDZMap::Ptr p2 = it->cache_->lookup(name)) {
1467                 rv = p2->value();
1468                 break;
1469             }
1470         }
1471     }
1472 
1473     if (!cache_->add(p, name, rv)) {
1474         ReportOutOfMemory(bce->cx);
1475         return Nothing();
1476     }
1477 
1478     return Some(rv);
1479 }
1480 
1481 bool
noteTDZCheck(BytecodeEmitter * bce,JSAtom * name,MaybeCheckTDZ check)1482 BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
1483                                              MaybeCheckTDZ check)
1484 {
1485     if (!ensureCache(bce))
1486         return false;
1487 
1488     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
1489     if (p) {
1490         MOZ_ASSERT(!check, "TDZ only needs to be checked once per binding per basic block.");
1491         p->value() = check;
1492     } else {
1493         if (!cache_->add(p, name, check))
1494             return false;
1495     }
1496 
1497     return true;
1498 }
1499 
BytecodeEmitter(BytecodeEmitter * parent,Parser<FullParseHandler> * parser,SharedContext * sc,HandleScript script,Handle<LazyScript * > lazyScript,uint32_t lineNum,EmitterMode emitterMode)1500 BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
1501                                  Parser<FullParseHandler>* parser, SharedContext* sc,
1502                                  HandleScript script, Handle<LazyScript*> lazyScript,
1503                                  uint32_t lineNum, EmitterMode emitterMode)
1504   : sc(sc),
1505     cx(sc->context),
1506     parent(parent),
1507     script(cx, script),
1508     lazyScript(cx, lazyScript),
1509     prologue(cx, lineNum),
1510     main(cx, lineNum),
1511     current(&main),
1512     parser(parser),
1513     atomIndices(cx->frontendCollectionPool()),
1514     firstLine(lineNum),
1515     maxFixedSlots(0),
1516     maxStackDepth(0),
1517     stackDepth(0),
1518     arrayCompDepth(0),
1519     emitLevel(0),
1520     bodyScopeIndex(UINT32_MAX),
1521     varEmitterScope(nullptr),
1522     innermostNestableControl(nullptr),
1523     innermostEmitterScope(nullptr),
1524     innermostTDZCheckCache(nullptr),
1525     constList(cx),
1526     scopeList(cx),
1527     tryNoteList(cx),
1528     scopeNoteList(cx),
1529     yieldOffsetList(cx),
1530     typesetCount(0),
1531     hasSingletons(false),
1532     hasTryFinally(false),
1533     emittingRunOnceLambda(false),
1534     emitterMode(emitterMode),
1535     functionBodyEndPosSet(false)
1536 {
1537     MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
1538 }
1539 
BytecodeEmitter(BytecodeEmitter * parent,Parser<FullParseHandler> * parser,SharedContext * sc,HandleScript script,Handle<LazyScript * > lazyScript,TokenPos bodyPosition,EmitterMode emitterMode)1540 BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
1541                                  Parser<FullParseHandler>* parser, SharedContext* sc,
1542                                  HandleScript script, Handle<LazyScript*> lazyScript,
1543                                  TokenPos bodyPosition, EmitterMode emitterMode)
1544     : BytecodeEmitter(parent, parser, sc, script, lazyScript,
1545                       parser->tokenStream.srcCoords.lineNum(bodyPosition.begin),
1546                       emitterMode)
1547 {
1548     setFunctionBodyEndPos(bodyPosition);
1549 }
1550 
1551 bool
init()1552 BytecodeEmitter::init()
1553 {
1554     return atomIndices.acquire(cx);
1555 }
1556 
1557 template <typename Predicate /* (NestableControl*) -> bool */>
1558 BytecodeEmitter::NestableControl*
findInnermostNestableControl(Predicate predicate) const1559 BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
1560 {
1561     return NestableControl::findNearest(innermostNestableControl, predicate);
1562 }
1563 
1564 template <typename T>
1565 T*
findInnermostNestableControl() const1566 BytecodeEmitter::findInnermostNestableControl() const
1567 {
1568     return NestableControl::findNearest<T>(innermostNestableControl);
1569 }
1570 
1571 template <typename T, typename Predicate /* (T*) -> bool */>
1572 T*
1573 BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const
1574 {
1575     return NestableControl::findNearest<T>(innermostNestableControl, predicate);
1576 }
1577 
1578 NameLocation
lookupName(JSAtom * name)1579 BytecodeEmitter::lookupName(JSAtom* name)
1580 {
1581     return innermostEmitterScope->lookup(this, name);
1582 }
1583 
1584 Maybe<NameLocation>
locationOfNameBoundInScope(JSAtom * name,EmitterScope * target)1585 BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
1586 {
1587     return innermostEmitterScope->locationBoundInScope(this, name, target);
1588 }
1589 
1590 Maybe<NameLocation>
locationOfNameBoundInFunctionScope(JSAtom * name,EmitterScope * source)1591 BytecodeEmitter::locationOfNameBoundInFunctionScope(JSAtom* name, EmitterScope* source)
1592 {
1593     EmitterScope* funScope = source;
1594     while (!funScope->scope(this)->is<FunctionScope>())
1595         funScope = funScope->enclosingInFrame();
1596     return source->locationBoundInScope(this, name, funScope);
1597 }
1598 
1599 bool
emitCheck(ptrdiff_t delta,ptrdiff_t * offset)1600 BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
1601 {
1602     *offset = code().length();
1603 
1604     // Start it off moderately large to avoid repeated resizings early on.
1605     // ~98% of cases fit within 1024 bytes.
1606     if (code().capacity() == 0 && !code().reserve(1024))
1607         return false;
1608 
1609     if (!code().growBy(delta)) {
1610         ReportOutOfMemory(cx);
1611         return false;
1612     }
1613     return true;
1614 }
1615 
1616 void
updateDepth(ptrdiff_t target)1617 BytecodeEmitter::updateDepth(ptrdiff_t target)
1618 {
1619     jsbytecode* pc = code(target);
1620 
1621     int nuses = StackUses(nullptr, pc);
1622     int ndefs = StackDefs(nullptr, pc);
1623 
1624     stackDepth -= nuses;
1625     MOZ_ASSERT(stackDepth >= 0);
1626     stackDepth += ndefs;
1627 
1628     if ((uint32_t)stackDepth > maxStackDepth)
1629         maxStackDepth = stackDepth;
1630 }
1631 
1632 #ifdef DEBUG
1633 bool
checkStrictOrSloppy(JSOp op)1634 BytecodeEmitter::checkStrictOrSloppy(JSOp op)
1635 {
1636     if (IsCheckStrictOp(op) && !sc->strict())
1637         return false;
1638     if (IsCheckSloppyOp(op) && sc->strict())
1639         return false;
1640     return true;
1641 }
1642 #endif
1643 
1644 bool
emit1(JSOp op)1645 BytecodeEmitter::emit1(JSOp op)
1646 {
1647     MOZ_ASSERT(checkStrictOrSloppy(op));
1648 
1649     ptrdiff_t offset;
1650     if (!emitCheck(1, &offset))
1651         return false;
1652 
1653     jsbytecode* code = this->code(offset);
1654     code[0] = jsbytecode(op);
1655     updateDepth(offset);
1656     return true;
1657 }
1658 
1659 bool
emit2(JSOp op,uint8_t op1)1660 BytecodeEmitter::emit2(JSOp op, uint8_t op1)
1661 {
1662     MOZ_ASSERT(checkStrictOrSloppy(op));
1663 
1664     ptrdiff_t offset;
1665     if (!emitCheck(2, &offset))
1666         return false;
1667 
1668     jsbytecode* code = this->code(offset);
1669     code[0] = jsbytecode(op);
1670     code[1] = jsbytecode(op1);
1671     updateDepth(offset);
1672     return true;
1673 }
1674 
1675 bool
emit3(JSOp op,jsbytecode op1,jsbytecode op2)1676 BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
1677 {
1678     MOZ_ASSERT(checkStrictOrSloppy(op));
1679 
1680     /* These should filter through emitVarOp. */
1681     MOZ_ASSERT(!IsArgOp(op));
1682     MOZ_ASSERT(!IsLocalOp(op));
1683 
1684     ptrdiff_t offset;
1685     if (!emitCheck(3, &offset))
1686         return false;
1687 
1688     jsbytecode* code = this->code(offset);
1689     code[0] = jsbytecode(op);
1690     code[1] = op1;
1691     code[2] = op2;
1692     updateDepth(offset);
1693     return true;
1694 }
1695 
1696 bool
emitN(JSOp op,size_t extra,ptrdiff_t * offset)1697 BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset)
1698 {
1699     MOZ_ASSERT(checkStrictOrSloppy(op));
1700     ptrdiff_t length = 1 + ptrdiff_t(extra);
1701 
1702     ptrdiff_t off;
1703     if (!emitCheck(length, &off))
1704         return false;
1705 
1706     jsbytecode* code = this->code(off);
1707     code[0] = jsbytecode(op);
1708     /* The remaining |extra| bytes are set by the caller */
1709 
1710     /*
1711      * Don't updateDepth if op's use-count comes from the immediate
1712      * operand yet to be stored in the extra bytes after op.
1713      */
1714     if (CodeSpec[op].nuses >= 0)
1715         updateDepth(off);
1716 
1717     if (offset)
1718         *offset = off;
1719     return true;
1720 }
1721 
1722 bool
emitJumpTarget(JumpTarget * target)1723 BytecodeEmitter::emitJumpTarget(JumpTarget* target)
1724 {
1725     ptrdiff_t off = offset();
1726 
1727     // Alias consecutive jump targets.
1728     if (off == current->lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
1729         target->offset = current->lastTarget.offset;
1730         return true;
1731     }
1732 
1733     target->offset = off;
1734     current->lastTarget.offset = off;
1735     if (!emit1(JSOP_JUMPTARGET))
1736         return false;
1737     return true;
1738 }
1739 
1740 void
push(jsbytecode * code,ptrdiff_t jumpOffset)1741 JumpList::push(jsbytecode* code, ptrdiff_t jumpOffset)
1742 {
1743     SET_JUMP_OFFSET(&code[jumpOffset], offset - jumpOffset);
1744     offset = jumpOffset;
1745 }
1746 
1747 void
patchAll(jsbytecode * code,JumpTarget target)1748 JumpList::patchAll(jsbytecode* code, JumpTarget target)
1749 {
1750     ptrdiff_t delta;
1751     for (ptrdiff_t jumpOffset = offset; jumpOffset != -1; jumpOffset += delta) {
1752         jsbytecode* pc = &code[jumpOffset];
1753         MOZ_ASSERT(IsJumpOpcode(JSOp(*pc)) || JSOp(*pc) == JSOP_LABEL);
1754         delta = GET_JUMP_OFFSET(pc);
1755         MOZ_ASSERT(delta < 0);
1756         ptrdiff_t span = target.offset - jumpOffset;
1757         SET_JUMP_OFFSET(pc, span);
1758     }
1759 }
1760 
1761 bool
emitJumpNoFallthrough(JSOp op,JumpList * jump)1762 BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump)
1763 {
1764     ptrdiff_t offset;
1765     if (!emitCheck(5, &offset))
1766         return false;
1767 
1768     jsbytecode* code = this->code(offset);
1769     code[0] = jsbytecode(op);
1770     MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
1771     jump->push(this->code(0), offset);
1772     updateDepth(offset);
1773     return true;
1774 }
1775 
1776 bool
emitJump(JSOp op,JumpList * jump)1777 BytecodeEmitter::emitJump(JSOp op, JumpList* jump)
1778 {
1779     if (!emitJumpNoFallthrough(op, jump))
1780         return false;
1781     if (BytecodeFallsThrough(op)) {
1782         JumpTarget fallthrough;
1783         if (!emitJumpTarget(&fallthrough))
1784             return false;
1785     }
1786     return true;
1787 }
1788 
1789 bool
emitBackwardJump(JSOp op,JumpTarget target,JumpList * jump,JumpTarget * fallthrough)1790 BytecodeEmitter::emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump, JumpTarget* fallthrough)
1791 {
1792     if (!emitJumpNoFallthrough(op, jump))
1793         return false;
1794     patchJumpsToTarget(*jump, target);
1795 
1796     // Unconditionally create a fallthrough for closing iterators, and as a
1797     // target for break statements.
1798     if (!emitJumpTarget(fallthrough))
1799         return false;
1800     return true;
1801 }
1802 
1803 void
patchJumpsToTarget(JumpList jump,JumpTarget target)1804 BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target)
1805 {
1806     MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
1807     MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
1808     MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
1809                   BytecodeIsJumpTarget(JSOp(*code(target.offset))));
1810     jump.patchAll(code(0), target);
1811 }
1812 
1813 bool
emitJumpTargetAndPatch(JumpList jump)1814 BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump)
1815 {
1816     if (jump.offset == -1)
1817         return true;
1818     JumpTarget target;
1819     if (!emitJumpTarget(&target))
1820         return false;
1821     patchJumpsToTarget(jump, target);
1822     return true;
1823 }
1824 
1825 bool
emitCall(JSOp op,uint16_t argc,ParseNode * pn)1826 BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
1827 {
1828     if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
1829         return false;
1830     return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
1831 }
1832 
1833 bool
emitDupAt(unsigned slotFromTop)1834 BytecodeEmitter::emitDupAt(unsigned slotFromTop)
1835 {
1836     MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
1837 
1838     if (slotFromTop >= JS_BIT(24)) {
1839         reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
1840         return false;
1841     }
1842 
1843     ptrdiff_t off;
1844     if (!emitN(JSOP_DUPAT, 3, &off))
1845         return false;
1846 
1847     jsbytecode* pc = code(off);
1848     SET_UINT24(pc, slotFromTop);
1849     return true;
1850 }
1851 
1852 bool
emitCheckIsObj(CheckIsObjectKind kind)1853 BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind)
1854 {
1855     return emit2(JSOP_CHECKISOBJ, uint8_t(kind));
1856 }
1857 
1858 static inline unsigned
LengthOfSetLine(unsigned line)1859 LengthOfSetLine(unsigned line)
1860 {
1861     return 1 /* SN_SETLINE */ + (line > SN_4BYTE_OFFSET_MASK ? 4 : 1);
1862 }
1863 
1864 /* Updates line number notes, not column notes. */
1865 bool
updateLineNumberNotes(uint32_t offset)1866 BytecodeEmitter::updateLineNumberNotes(uint32_t offset)
1867 {
1868     TokenStream* ts = &parser->tokenStream;
1869     bool onThisLine;
1870     if (!ts->srcCoords.isOnThisLine(offset, currentLine(), &onThisLine))
1871         return ts->reportError(JSMSG_OUT_OF_MEMORY);
1872     if (!onThisLine) {
1873         unsigned line = ts->srcCoords.lineNum(offset);
1874         unsigned delta = line - currentLine();
1875 
1876         /*
1877          * Encode any change in the current source line number by using
1878          * either several SRC_NEWLINE notes or just one SRC_SETLINE note,
1879          * whichever consumes less space.
1880          *
1881          * NB: We handle backward line number deltas (possible with for
1882          * loops where the update part is emitted after the body, but its
1883          * line number is <= any line number in the body) here by letting
1884          * unsigned delta_ wrap to a very large number, which triggers a
1885          * SRC_SETLINE.
1886          */
1887         current->currentLine = line;
1888         current->lastColumn  = 0;
1889         if (delta >= LengthOfSetLine(line)) {
1890             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line)))
1891                 return false;
1892         } else {
1893             do {
1894                 if (!newSrcNote(SRC_NEWLINE))
1895                     return false;
1896             } while (--delta != 0);
1897         }
1898     }
1899     return true;
1900 }
1901 
1902 /* Updates the line number and column number information in the source notes. */
1903 bool
updateSourceCoordNotes(uint32_t offset)1904 BytecodeEmitter::updateSourceCoordNotes(uint32_t offset)
1905 {
1906     if (!updateLineNumberNotes(offset))
1907         return false;
1908 
1909     uint32_t columnIndex = parser->tokenStream.srcCoords.columnIndex(offset);
1910     ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(current->lastColumn);
1911     if (colspan != 0) {
1912         // If the column span is so large that we can't store it, then just
1913         // discard this information. This can happen with minimized or otherwise
1914         // machine-generated code. Even gigantic column numbers are still
1915         // valuable if you have a source map to relate them to something real;
1916         // but it's better to fail soft here.
1917         if (!SN_REPRESENTABLE_COLSPAN(colspan))
1918             return true;
1919         if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)))
1920             return false;
1921         current->lastColumn = columnIndex;
1922     }
1923     return true;
1924 }
1925 
1926 bool
emitLoopHead(ParseNode * nextpn,JumpTarget * top)1927 BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
1928 {
1929     if (nextpn) {
1930         /*
1931          * Try to give the JSOP_LOOPHEAD the same line number as the next
1932          * instruction. nextpn is often a block, in which case the next
1933          * instruction typically comes from the first statement inside.
1934          */
1935         if (nextpn->isKind(PNK_LEXICALSCOPE))
1936             nextpn = nextpn->scopeBody();
1937         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
1938         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
1939             nextpn = nextpn->pn_head;
1940         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
1941             return false;
1942     }
1943 
1944     *top = { offset() };
1945     return emit1(JSOP_LOOPHEAD);
1946 }
1947 
1948 bool
emitLoopEntry(ParseNode * nextpn,JumpList entryJump)1949 BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
1950 {
1951     if (nextpn) {
1952         /* Update the line number, as for LOOPHEAD. */
1953         if (nextpn->isKind(PNK_LEXICALSCOPE))
1954             nextpn = nextpn->scopeBody();
1955         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
1956         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
1957             nextpn = nextpn->pn_head;
1958         if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
1959             return false;
1960     }
1961 
1962     JumpTarget entry{ offset() };
1963     patchJumpsToTarget(entryJump, entry);
1964 
1965     LoopControl& loopInfo = innermostNestableControl->as<LoopControl>();
1966     MOZ_ASSERT(loopInfo.loopDepth() > 0);
1967 
1968     uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loopInfo.loopDepth(),
1969                                                                loopInfo.canIonOsr());
1970     return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
1971 }
1972 
1973 void
checkTypeSet(JSOp op)1974 BytecodeEmitter::checkTypeSet(JSOp op)
1975 {
1976     if (CodeSpec[op].format & JOF_TYPESET) {
1977         if (typesetCount < UINT16_MAX)
1978             typesetCount++;
1979     }
1980 }
1981 
1982 bool
emitUint16Operand(JSOp op,uint32_t operand)1983 BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
1984 {
1985     MOZ_ASSERT(operand <= UINT16_MAX);
1986     if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand)))
1987         return false;
1988     checkTypeSet(op);
1989     return true;
1990 }
1991 
1992 bool
emitUint32Operand(JSOp op,uint32_t operand)1993 BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand)
1994 {
1995     ptrdiff_t off;
1996     if (!emitN(op, 4, &off))
1997         return false;
1998     SET_UINT32(code(off), operand);
1999     checkTypeSet(op);
2000     return true;
2001 }
2002 
2003 bool
flushPops(int * npops)2004 BytecodeEmitter::flushPops(int* npops)
2005 {
2006     MOZ_ASSERT(*npops != 0);
2007     if (!emitUint16Operand(JSOP_POPN, *npops))
2008         return false;
2009 
2010     *npops = 0;
2011     return true;
2012 }
2013 
2014 namespace {
2015 
2016 class NonLocalExitControl {
2017     BytecodeEmitter* bce_;
2018     const uint32_t savedScopeNoteIndex_;
2019     const int savedDepth_;
2020     uint32_t openScopeNoteIndex_;
2021 
2022     NonLocalExitControl(const NonLocalExitControl&) = delete;
2023 
2024     MOZ_MUST_USE bool leaveScope(BytecodeEmitter::EmitterScope* scope);
2025 
2026   public:
NonLocalExitControl(BytecodeEmitter * bce)2027     explicit NonLocalExitControl(BytecodeEmitter* bce)
2028       : bce_(bce),
2029         savedScopeNoteIndex_(bce->scopeNoteList.length()),
2030         savedDepth_(bce->stackDepth),
2031         openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex())
2032     { }
2033 
~NonLocalExitControl()2034     ~NonLocalExitControl() {
2035         for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length(); n++)
2036             bce_->scopeNoteList.recordEnd(n, bce_->offset(), bce_->inPrologue());
2037         bce_->stackDepth = savedDepth_;
2038     }
2039 
2040     MOZ_MUST_USE bool prepareForNonLocalJump(BytecodeEmitter::NestableControl* target);
2041 
prepareForNonLocalJumpToOutermost()2042     MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
2043         return prepareForNonLocalJump(nullptr);
2044     }
2045 };
2046 
2047 bool
leaveScope(BytecodeEmitter::EmitterScope * es)2048 NonLocalExitControl::leaveScope(BytecodeEmitter::EmitterScope* es)
2049 {
2050     if (!es->leave(bce_, /* nonLocal = */ true))
2051         return false;
2052 
2053     // As we pop each scope due to the non-local jump, emit notes that
2054     // record the extent of the enclosing scope. These notes will have
2055     // their ends recorded in ~NonLocalExitControl().
2056     uint32_t enclosingScopeIndex = ScopeNote::NoScopeIndex;
2057     if (es->enclosingInFrame())
2058         enclosingScopeIndex = es->enclosingInFrame()->index();
2059     if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(), bce_->inPrologue(),
2060                                     openScopeNoteIndex_))
2061         return false;
2062     openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
2063 
2064     return true;
2065 }
2066 
2067 /*
2068  * Emit additional bytecode(s) for non-local jumps.
2069  */
2070 bool
prepareForNonLocalJump(BytecodeEmitter::NestableControl * target)2071 NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* target)
2072 {
2073     using NestableControl = BytecodeEmitter::NestableControl;
2074     using EmitterScope = BytecodeEmitter::EmitterScope;
2075 
2076     EmitterScope* es = bce_->innermostEmitterScope;
2077     int npops = 0;
2078 
2079     auto flushPops = [&npops](BytecodeEmitter* bce) {
2080         if (npops && !bce->flushPops(&npops))
2081             return false;
2082         return true;
2083     };
2084 
2085     // Walk the nestable control stack and patch jumps.
2086     for (NestableControl* control = bce_->innermostNestableControl;
2087          control != target;
2088          control = control->enclosing())
2089     {
2090         // Walk the scope stack and leave the scopes we entered. Leaving a scope
2091         // may emit administrative ops like JSOP_POPLEXICALENV but never anything
2092         // that manipulates the stack.
2093         for (; es != control->emitterScope(); es = es->enclosingInFrame()) {
2094             if (!leaveScope(es))
2095                 return false;
2096         }
2097 
2098         switch (control->kind()) {
2099           case StatementKind::Finally: {
2100             TryFinallyControl& finallyControl = control->as<TryFinallyControl>();
2101             if (finallyControl.emittingSubroutine()) {
2102                 /*
2103                  * There's a [exception or hole, retsub pc-index] pair and the
2104                  * possible return value on the stack that we need to pop.
2105                  */
2106                 npops += 3;
2107             } else {
2108                 if (!flushPops(bce_))
2109                     return false;
2110                 if (!bce_->emitJump(JSOP_GOSUB, &finallyControl.gosubs))
2111                     return false;
2112             }
2113             break;
2114           }
2115 
2116           case StatementKind::ForOfLoop:
2117             npops += 2;
2118             break;
2119 
2120           case StatementKind::ForInLoop:
2121             /* The iterator and the current value are on the stack. */
2122             npops += 1;
2123             if (!flushPops(bce_))
2124                 return false;
2125             if (!bce_->emit1(JSOP_ENDITER))
2126                 return false;
2127             break;
2128 
2129           default:
2130             break;
2131         }
2132     }
2133 
2134     EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope;
2135     for (; es != targetEmitterScope; es = es->enclosingInFrame()) {
2136         if (!leaveScope(es))
2137             return false;
2138     }
2139 
2140     return flushPops(bce_);
2141 }
2142 
2143 }  // anonymous namespace
2144 
2145 bool
emitGoto(NestableControl * target,JumpList * jumplist,SrcNoteType noteType)2146 BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteType noteType)
2147 {
2148     NonLocalExitControl nle(this);
2149 
2150     if (!nle.prepareForNonLocalJump(target))
2151         return false;
2152 
2153     if (noteType != SRC_NULL) {
2154         if (!newSrcNote(noteType))
2155             return false;
2156     }
2157 
2158     return emitJump(JSOP_GOTO, jumplist);
2159 }
2160 
2161 Scope*
innermostScope() const2162 BytecodeEmitter::innermostScope() const
2163 {
2164     return innermostEmitterScope->scope(this);
2165 }
2166 
2167 bool
emitIndex32(JSOp op,uint32_t index)2168 BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
2169 {
2170     MOZ_ASSERT(checkStrictOrSloppy(op));
2171 
2172     const size_t len = 1 + UINT32_INDEX_LEN;
2173     MOZ_ASSERT(len == size_t(CodeSpec[op].length));
2174 
2175     ptrdiff_t offset;
2176     if (!emitCheck(len, &offset))
2177         return false;
2178 
2179     jsbytecode* code = this->code(offset);
2180     code[0] = jsbytecode(op);
2181     SET_UINT32_INDEX(code, index);
2182     checkTypeSet(op);
2183     updateDepth(offset);
2184     return true;
2185 }
2186 
2187 bool
emitIndexOp(JSOp op,uint32_t index)2188 BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
2189 {
2190     MOZ_ASSERT(checkStrictOrSloppy(op));
2191 
2192     const size_t len = CodeSpec[op].length;
2193     MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
2194 
2195     ptrdiff_t offset;
2196     if (!emitCheck(len, &offset))
2197         return false;
2198 
2199     jsbytecode* code = this->code(offset);
2200     code[0] = jsbytecode(op);
2201     SET_UINT32_INDEX(code, index);
2202     checkTypeSet(op);
2203     updateDepth(offset);
2204     return true;
2205 }
2206 
2207 bool
emitAtomOp(JSAtom * atom,JSOp op)2208 BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op)
2209 {
2210     MOZ_ASSERT(atom);
2211     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
2212 
2213     // .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of
2214     // JSOP_GETNAME etc, to bypass |with| objects on the scope chain.
2215     // It's safe to emit .this lookups though because |with| objects skip
2216     // those.
2217     MOZ_ASSERT_IF(op == JSOP_GETNAME || op == JSOP_GETGNAME,
2218                   atom != cx->names().dotGenerator);
2219 
2220     if (op == JSOP_GETPROP && atom == cx->names().length) {
2221         /* Specialize length accesses for the interpreter. */
2222         op = JSOP_LENGTH;
2223     }
2224 
2225     uint32_t index;
2226     if (!makeAtomIndex(atom, &index))
2227         return false;
2228 
2229     return emitIndexOp(op, index);
2230 }
2231 
2232 bool
emitAtomOp(ParseNode * pn,JSOp op)2233 BytecodeEmitter::emitAtomOp(ParseNode* pn, JSOp op)
2234 {
2235     MOZ_ASSERT(pn->pn_atom != nullptr);
2236     return emitAtomOp(pn->pn_atom, op);
2237 }
2238 
2239 bool
emitInternedScopeOp(uint32_t index,JSOp op)2240 BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op)
2241 {
2242     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPE);
2243     MOZ_ASSERT(index < scopeList.length());
2244     return emitIndex32(op, index);
2245 }
2246 
2247 bool
emitInternedObjectOp(uint32_t index,JSOp op)2248 BytecodeEmitter::emitInternedObjectOp(uint32_t index, JSOp op)
2249 {
2250     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
2251     MOZ_ASSERT(index < objectList.length);
2252     return emitIndex32(op, index);
2253 }
2254 
2255 bool
emitObjectOp(ObjectBox * objbox,JSOp op)2256 BytecodeEmitter::emitObjectOp(ObjectBox* objbox, JSOp op)
2257 {
2258     return emitInternedObjectOp(objectList.add(objbox), op);
2259 }
2260 
2261 bool
emitObjectPairOp(ObjectBox * objbox1,ObjectBox * objbox2,JSOp op)2262 BytecodeEmitter::emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op)
2263 {
2264     uint32_t index = objectList.add(objbox1);
2265     objectList.add(objbox2);
2266     return emitInternedObjectOp(index, op);
2267 }
2268 
2269 bool
emitRegExp(uint32_t index)2270 BytecodeEmitter::emitRegExp(uint32_t index)
2271 {
2272     return emitIndex32(JSOP_REGEXP, index);
2273 }
2274 
2275 bool
emitLocalOp(JSOp op,uint32_t slot)2276 BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot)
2277 {
2278     MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD);
2279     MOZ_ASSERT(IsLocalOp(op));
2280 
2281     ptrdiff_t off;
2282     if (!emitN(op, LOCALNO_LEN, &off))
2283         return false;
2284 
2285     SET_LOCALNO(code(off), slot);
2286     return true;
2287 }
2288 
2289 bool
emitArgOp(JSOp op,uint16_t slot)2290 BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot)
2291 {
2292     MOZ_ASSERT(IsArgOp(op));
2293     ptrdiff_t off;
2294     if (!emitN(op, ARGNO_LEN, &off))
2295         return false;
2296 
2297     SET_ARGNO(code(off), slot);
2298     return true;
2299 }
2300 
2301 bool
emitEnvCoordOp(JSOp op,EnvironmentCoordinate ec)2302 BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec)
2303 {
2304     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD);
2305 
2306     unsigned n = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
2307     MOZ_ASSERT(int(n) + 1 /* op */ == CodeSpec[op].length);
2308 
2309     ptrdiff_t off;
2310     if (!emitN(op, n, &off))
2311         return false;
2312 
2313     jsbytecode* pc = code(off);
2314     SET_ENVCOORD_HOPS(pc, ec.hops());
2315     pc += ENVCOORD_HOPS_LEN;
2316     SET_ENVCOORD_SLOT(pc, ec.slot());
2317     pc += ENVCOORD_SLOT_LEN;
2318     checkTypeSet(op);
2319     return true;
2320 }
2321 
2322 static JSOp
GetIncDecInfo(ParseNodeKind kind,bool * post)2323 GetIncDecInfo(ParseNodeKind kind, bool* post)
2324 {
2325     MOZ_ASSERT(kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT ||
2326                kind == PNK_POSTDECREMENT || kind == PNK_PREDECREMENT);
2327     *post = kind == PNK_POSTINCREMENT || kind == PNK_POSTDECREMENT;
2328     return (kind == PNK_POSTINCREMENT || kind == PNK_PREINCREMENT) ? JSOP_ADD : JSOP_SUB;
2329 }
2330 
2331 JSOp
strictifySetNameOp(JSOp op)2332 BytecodeEmitter::strictifySetNameOp(JSOp op)
2333 {
2334     switch (op) {
2335       case JSOP_SETNAME:
2336         if (sc->strict())
2337             op = JSOP_STRICTSETNAME;
2338         break;
2339       case JSOP_SETGNAME:
2340         if (sc->strict())
2341             op = JSOP_STRICTSETGNAME;
2342         break;
2343         default:;
2344     }
2345     return op;
2346 }
2347 
2348 bool
checkSideEffects(ParseNode * pn,bool * answer)2349 BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
2350 {
2351     JS_CHECK_RECURSION(cx, return false);
2352 
2353  restart:
2354 
2355     switch (pn->getKind()) {
2356       // Trivial cases with no side effects.
2357       case PNK_NOP:
2358       case PNK_STRING:
2359       case PNK_TEMPLATE_STRING:
2360       case PNK_REGEXP:
2361       case PNK_TRUE:
2362       case PNK_FALSE:
2363       case PNK_NULL:
2364       case PNK_ELISION:
2365       case PNK_GENERATOR:
2366       case PNK_NUMBER:
2367       case PNK_OBJECT_PROPERTY_NAME:
2368         MOZ_ASSERT(pn->isArity(PN_NULLARY));
2369         *answer = false;
2370         return true;
2371 
2372       // |this| can throw in derived class constructors, including nested arrow
2373       // functions or eval.
2374       case PNK_THIS:
2375         MOZ_ASSERT(pn->isArity(PN_UNARY));
2376         *answer = sc->needsThisTDZChecks();
2377         return true;
2378 
2379       // Trivial binary nodes with more token pos holders.
2380       case PNK_NEWTARGET:
2381         MOZ_ASSERT(pn->isArity(PN_BINARY));
2382         MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
2383         MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
2384         *answer = false;
2385         return true;
2386 
2387       case PNK_BREAK:
2388       case PNK_CONTINUE:
2389       case PNK_DEBUGGER:
2390         MOZ_ASSERT(pn->isArity(PN_NULLARY));
2391         *answer = true;
2392         return true;
2393 
2394       // Watch out for getters!
2395       case PNK_DOT:
2396         MOZ_ASSERT(pn->isArity(PN_NAME));
2397         *answer = true;
2398         return true;
2399 
2400       // Unary cases with side effects only if the child has them.
2401       case PNK_TYPEOFEXPR:
2402       case PNK_VOID:
2403       case PNK_NOT:
2404         MOZ_ASSERT(pn->isArity(PN_UNARY));
2405         return checkSideEffects(pn->pn_kid, answer);
2406 
2407       // Even if the name expression is effect-free, performing ToPropertyKey on
2408       // it might not be effect-free:
2409       //
2410       //   RegExp.prototype.toString = () => { throw 42; };
2411       //   ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
2412       //
2413       //   function Q() {
2414       //     ({ [new.target]: 0 });
2415       //   }
2416       //   Q.toString = () => { throw 17; };
2417       //   new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
2418       case PNK_COMPUTED_NAME:
2419         MOZ_ASSERT(pn->isArity(PN_UNARY));
2420         *answer = true;
2421         return true;
2422 
2423       // Looking up or evaluating the associated name could throw.
2424       case PNK_TYPEOFNAME:
2425         MOZ_ASSERT(pn->isArity(PN_UNARY));
2426         *answer = true;
2427         return true;
2428 
2429       // These unary cases have side effects on the enclosing object/array,
2430       // sure.  But that's not the question this function answers: it's
2431       // whether the operation may have a side effect on something *other* than
2432       // the result of the overall operation in which it's embedded.  The
2433       // answer to that is no, for an object literal having a mutated prototype
2434       // and an array comprehension containing no other effectful operations
2435       // only produce a value, without affecting anything else.
2436       case PNK_MUTATEPROTO:
2437       case PNK_ARRAYPUSH:
2438         MOZ_ASSERT(pn->isArity(PN_UNARY));
2439         return checkSideEffects(pn->pn_kid, answer);
2440 
2441       // Unary cases with obvious side effects.
2442       case PNK_PREINCREMENT:
2443       case PNK_POSTINCREMENT:
2444       case PNK_PREDECREMENT:
2445       case PNK_POSTDECREMENT:
2446       case PNK_THROW:
2447         MOZ_ASSERT(pn->isArity(PN_UNARY));
2448         *answer = true;
2449         return true;
2450 
2451       // These might invoke valueOf/toString, even with a subexpression without
2452       // side effects!  Consider |+{ valueOf: null, toString: null }|.
2453       case PNK_BITNOT:
2454       case PNK_POS:
2455       case PNK_NEG:
2456         MOZ_ASSERT(pn->isArity(PN_UNARY));
2457         *answer = true;
2458         return true;
2459 
2460       // This invokes the (user-controllable) iterator protocol.
2461       case PNK_SPREAD:
2462         MOZ_ASSERT(pn->isArity(PN_UNARY));
2463         *answer = true;
2464         return true;
2465 
2466       case PNK_YIELD_STAR:
2467       case PNK_YIELD:
2468       case PNK_AWAIT:
2469         MOZ_ASSERT(pn->isArity(PN_BINARY));
2470         *answer = true;
2471         return true;
2472 
2473       // Deletion generally has side effects, even if isolated cases have none.
2474       case PNK_DELETENAME:
2475       case PNK_DELETEPROP:
2476       case PNK_DELETEELEM:
2477         MOZ_ASSERT(pn->isArity(PN_UNARY));
2478         *answer = true;
2479         return true;
2480 
2481       // Deletion of a non-Reference expression has side effects only through
2482       // evaluating the expression.
2483       case PNK_DELETEEXPR: {
2484         MOZ_ASSERT(pn->isArity(PN_UNARY));
2485         ParseNode* expr = pn->pn_kid;
2486         return checkSideEffects(expr, answer);
2487       }
2488 
2489       case PNK_SEMI:
2490         MOZ_ASSERT(pn->isArity(PN_UNARY));
2491         if (ParseNode* expr = pn->pn_kid)
2492             return checkSideEffects(expr, answer);
2493         *answer = false;
2494         return true;
2495 
2496       // Binary cases with obvious side effects.
2497       case PNK_ASSIGN:
2498       case PNK_ADDASSIGN:
2499       case PNK_SUBASSIGN:
2500       case PNK_BITORASSIGN:
2501       case PNK_BITXORASSIGN:
2502       case PNK_BITANDASSIGN:
2503       case PNK_LSHASSIGN:
2504       case PNK_RSHASSIGN:
2505       case PNK_URSHASSIGN:
2506       case PNK_MULASSIGN:
2507       case PNK_DIVASSIGN:
2508       case PNK_MODASSIGN:
2509       case PNK_POWASSIGN:
2510       case PNK_SETTHIS:
2511         MOZ_ASSERT(pn->isArity(PN_BINARY));
2512         *answer = true;
2513         return true;
2514 
2515       case PNK_STATEMENTLIST:
2516       case PNK_CATCHLIST:
2517       // Strict equality operations and logical operators are well-behaved and
2518       // perform no conversions.
2519       case PNK_OR:
2520       case PNK_AND:
2521       case PNK_STRICTEQ:
2522       case PNK_STRICTNE:
2523       // Any subexpression of a comma expression could be effectful.
2524       case PNK_COMMA:
2525         MOZ_ASSERT(pn->pn_count > 0);
2526         MOZ_FALLTHROUGH;
2527       // Subcomponents of a literal may be effectful.
2528       case PNK_ARRAY:
2529       case PNK_OBJECT:
2530         MOZ_ASSERT(pn->isArity(PN_LIST));
2531         for (ParseNode* item = pn->pn_head; item; item = item->pn_next) {
2532             if (!checkSideEffects(item, answer))
2533                 return false;
2534             if (*answer)
2535                 return true;
2536         }
2537         return true;
2538 
2539       // Most other binary operations (parsed as lists in SpiderMonkey) may
2540       // perform conversions triggering side effects.  Math operations perform
2541       // ToNumber and may fail invoking invalid user-defined toString/valueOf:
2542       // |5 < { toString: null }|.  |instanceof| throws if provided a
2543       // non-object constructor: |null instanceof null|.  |in| throws if given
2544       // a non-object RHS: |5 in null|.
2545       case PNK_BITOR:
2546       case PNK_BITXOR:
2547       case PNK_BITAND:
2548       case PNK_EQ:
2549       case PNK_NE:
2550       case PNK_LT:
2551       case PNK_LE:
2552       case PNK_GT:
2553       case PNK_GE:
2554       case PNK_INSTANCEOF:
2555       case PNK_IN:
2556       case PNK_LSH:
2557       case PNK_RSH:
2558       case PNK_URSH:
2559       case PNK_ADD:
2560       case PNK_SUB:
2561       case PNK_STAR:
2562       case PNK_DIV:
2563       case PNK_MOD:
2564       case PNK_POW:
2565         MOZ_ASSERT(pn->isArity(PN_LIST));
2566         MOZ_ASSERT(pn->pn_count >= 2);
2567         *answer = true;
2568         return true;
2569 
2570       case PNK_COLON:
2571       case PNK_CASE:
2572         MOZ_ASSERT(pn->isArity(PN_BINARY));
2573         if (!checkSideEffects(pn->pn_left, answer))
2574             return false;
2575         if (*answer)
2576             return true;
2577         return checkSideEffects(pn->pn_right, answer);
2578 
2579       // More getters.
2580       case PNK_ELEM:
2581         MOZ_ASSERT(pn->isArity(PN_BINARY));
2582         *answer = true;
2583         return true;
2584 
2585       // These affect visible names in this code, or in other code.
2586       case PNK_IMPORT:
2587       case PNK_EXPORT_FROM:
2588       case PNK_EXPORT_DEFAULT:
2589         MOZ_ASSERT(pn->isArity(PN_BINARY));
2590         *answer = true;
2591         return true;
2592 
2593       // Likewise.
2594       case PNK_EXPORT:
2595         MOZ_ASSERT(pn->isArity(PN_UNARY));
2596         *answer = true;
2597         return true;
2598 
2599       // Every part of a loop might be effect-free, but looping infinitely *is*
2600       // an effect.  (Language lawyer trivia: C++ says threads can be assumed
2601       // to exit or have side effects, C++14 [intro.multithread]p27, so a C++
2602       // implementation's equivalent of the below could set |*answer = false;|
2603       // if all loop sub-nodes set |*answer = false|!)
2604       case PNK_DOWHILE:
2605       case PNK_WHILE:
2606       case PNK_FOR:
2607       case PNK_COMPREHENSIONFOR:
2608         MOZ_ASSERT(pn->isArity(PN_BINARY));
2609         *answer = true;
2610         return true;
2611 
2612       // Declarations affect the name set of the relevant scope.
2613       case PNK_VAR:
2614       case PNK_CONST:
2615       case PNK_LET:
2616         MOZ_ASSERT(pn->isArity(PN_LIST));
2617         *answer = true;
2618         return true;
2619 
2620       case PNK_IF:
2621       case PNK_CONDITIONAL:
2622         MOZ_ASSERT(pn->isArity(PN_TERNARY));
2623         if (!checkSideEffects(pn->pn_kid1, answer))
2624             return false;
2625         if (*answer)
2626             return true;
2627         if (!checkSideEffects(pn->pn_kid2, answer))
2628             return false;
2629         if (*answer)
2630             return true;
2631         if ((pn = pn->pn_kid3))
2632             goto restart;
2633         return true;
2634 
2635       // Function calls can invoke non-local code.
2636       case PNK_NEW:
2637       case PNK_CALL:
2638       case PNK_TAGGED_TEMPLATE:
2639       case PNK_SUPERCALL:
2640         MOZ_ASSERT(pn->isArity(PN_LIST));
2641         *answer = true;
2642         return true;
2643 
2644       // Classes typically introduce names.  Even if no name is introduced,
2645       // the heritage and/or class body (through computed property names)
2646       // usually have effects.
2647       case PNK_CLASS:
2648         MOZ_ASSERT(pn->isArity(PN_TERNARY));
2649         *answer = true;
2650         return true;
2651 
2652       // |with| calls |ToObject| on its expression and so throws if that value
2653       // is null/undefined.
2654       case PNK_WITH:
2655         MOZ_ASSERT(pn->isArity(PN_BINARY));
2656         *answer = true;
2657         return true;
2658 
2659       case PNK_RETURN:
2660         MOZ_ASSERT(pn->isArity(PN_BINARY));
2661         *answer = true;
2662         return true;
2663 
2664       case PNK_NAME:
2665         MOZ_ASSERT(pn->isArity(PN_NAME));
2666         *answer = true;
2667         return true;
2668 
2669       // Shorthands could trigger getters: the |x| in the object literal in
2670       // |with ({ get x() { throw 42; } }) ({ x });|, for example, triggers
2671       // one.  (Of course, it isn't necessary to use |with| for a shorthand to
2672       // trigger a getter.)
2673       case PNK_SHORTHAND:
2674         MOZ_ASSERT(pn->isArity(PN_BINARY));
2675         *answer = true;
2676         return true;
2677 
2678       case PNK_FUNCTION:
2679         MOZ_ASSERT(pn->isArity(PN_CODE));
2680         /*
2681          * A named function, contrary to ES3, is no longer effectful, because
2682          * we bind its name lexically (using JSOP_CALLEE) instead of creating
2683          * an Object instance and binding a readonly, permanent property in it
2684          * (the object and binding can be detected and hijacked or captured).
2685          * This is a bug fix to ES3; it is fixed in ES3.1 drafts.
2686          */
2687         *answer = false;
2688         return true;
2689 
2690       case PNK_MODULE:
2691         *answer = false;
2692         return true;
2693 
2694       // Generator expressions have no side effects on their own.
2695       case PNK_GENEXP:
2696         MOZ_ASSERT(pn->isArity(PN_LIST));
2697         *answer = false;
2698         return true;
2699 
2700       case PNK_TRY:
2701         MOZ_ASSERT(pn->isArity(PN_TERNARY));
2702         if (!checkSideEffects(pn->pn_kid1, answer))
2703             return false;
2704         if (*answer)
2705             return true;
2706         if (ParseNode* catchList = pn->pn_kid2) {
2707             MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
2708             if (!checkSideEffects(catchList, answer))
2709                 return false;
2710             if (*answer)
2711                 return true;
2712         }
2713         if (ParseNode* finallyBlock = pn->pn_kid3) {
2714             if (!checkSideEffects(finallyBlock, answer))
2715                 return false;
2716         }
2717         return true;
2718 
2719       case PNK_CATCH:
2720         MOZ_ASSERT(pn->isArity(PN_TERNARY));
2721         if (!checkSideEffects(pn->pn_kid1, answer))
2722             return false;
2723         if (*answer)
2724             return true;
2725         if (ParseNode* cond = pn->pn_kid2) {
2726             if (!checkSideEffects(cond, answer))
2727                 return false;
2728             if (*answer)
2729                 return true;
2730         }
2731         return checkSideEffects(pn->pn_kid3, answer);
2732 
2733       case PNK_SWITCH:
2734         MOZ_ASSERT(pn->isArity(PN_BINARY));
2735         if (!checkSideEffects(pn->pn_left, answer))
2736             return false;
2737         return *answer || checkSideEffects(pn->pn_right, answer);
2738 
2739       case PNK_LABEL:
2740         MOZ_ASSERT(pn->isArity(PN_NAME));
2741         return checkSideEffects(pn->expr(), answer);
2742 
2743       case PNK_LEXICALSCOPE:
2744         MOZ_ASSERT(pn->isArity(PN_SCOPE));
2745         return checkSideEffects(pn->scopeBody(), answer);
2746 
2747       // We could methodically check every interpolated expression, but it's
2748       // probably not worth the trouble.  Treat template strings as effect-free
2749       // only if they don't contain any substitutions.
2750       case PNK_TEMPLATE_STRING_LIST:
2751         MOZ_ASSERT(pn->isArity(PN_LIST));
2752         MOZ_ASSERT(pn->pn_count > 0);
2753         MOZ_ASSERT((pn->pn_count % 2) == 1,
2754                    "template strings must alternate template and substitution "
2755                    "parts");
2756         *answer = pn->pn_count > 1;
2757         return true;
2758 
2759       case PNK_ARRAYCOMP:
2760         MOZ_ASSERT(pn->isArity(PN_LIST));
2761         MOZ_ASSERT(pn->pn_count == 1);
2762         return checkSideEffects(pn->pn_head, answer);
2763 
2764       // This should be unreachable but is left as-is for now.
2765       case PNK_PARAMSBODY:
2766         *answer = true;
2767         return true;
2768 
2769       case PNK_FORIN:           // by PNK_FOR/PNK_COMPREHENSIONFOR
2770       case PNK_FOROF:           // by PNK_FOR/PNK_COMPREHENSIONFOR
2771       case PNK_FORHEAD:         // by PNK_FOR/PNK_COMPREHENSIONFOR
2772       case PNK_CLASSMETHOD:     // by PNK_CLASS
2773       case PNK_CLASSNAMES:      // by PNK_CLASS
2774       case PNK_CLASSMETHODLIST: // by PNK_CLASS
2775       case PNK_IMPORT_SPEC_LIST: // by PNK_IMPORT
2776       case PNK_IMPORT_SPEC:      // by PNK_IMPORT
2777       case PNK_EXPORT_BATCH_SPEC:// by PNK_EXPORT
2778       case PNK_EXPORT_SPEC_LIST: // by PNK_EXPORT
2779       case PNK_EXPORT_SPEC:      // by PNK_EXPORT
2780       case PNK_CALLSITEOBJ:      // by PNK_TAGGED_TEMPLATE
2781       case PNK_POSHOLDER:        // by PNK_NEWTARGET
2782       case PNK_SUPERBASE:        // by PNK_ELEM and others
2783         MOZ_CRASH("handled by parent nodes");
2784 
2785       case PNK_LIMIT: // invalid sentinel value
2786         MOZ_CRASH("invalid node kind");
2787     }
2788 
2789     MOZ_CRASH("invalid, unenumerated ParseNodeKind value encountered in "
2790               "BytecodeEmitter::checkSideEffects");
2791 }
2792 
2793 bool
isInLoop()2794 BytecodeEmitter::isInLoop()
2795 {
2796     return findInnermostNestableControl<LoopControl>();
2797 }
2798 
2799 bool
checkSingletonContext()2800 BytecodeEmitter::checkSingletonContext()
2801 {
2802     if (!script->treatAsRunOnce() || sc->isFunctionBox() || isInLoop())
2803         return false;
2804     hasSingletons = true;
2805     return true;
2806 }
2807 
2808 bool
checkRunOnceContext()2809 BytecodeEmitter::checkRunOnceContext()
2810 {
2811     return checkSingletonContext() || (!isInLoop() && isRunOnceLambda());
2812 }
2813 
2814 bool
needsImplicitThis()2815 BytecodeEmitter::needsImplicitThis()
2816 {
2817     // Short-circuit if there is an enclosing 'with' scope.
2818     if (sc->inWith())
2819         return true;
2820 
2821     // Otherwise see if the current point is under a 'with'.
2822     for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) {
2823         if (es->scope(this)->kind() == ScopeKind::With)
2824             return true;
2825     }
2826 
2827     return false;
2828 }
2829 
2830 bool
maybeSetDisplayURL()2831 BytecodeEmitter::maybeSetDisplayURL()
2832 {
2833     if (tokenStream()->hasDisplayURL()) {
2834         if (!parser->ss->setDisplayURL(cx, tokenStream()->displayURL()))
2835             return false;
2836     }
2837     return true;
2838 }
2839 
2840 bool
maybeSetSourceMap()2841 BytecodeEmitter::maybeSetSourceMap()
2842 {
2843     if (tokenStream()->hasSourceMapURL()) {
2844         MOZ_ASSERT(!parser->ss->hasSourceMapURL());
2845         if (!parser->ss->setSourceMapURL(cx, tokenStream()->sourceMapURL()))
2846             return false;
2847     }
2848 
2849     /*
2850      * Source map URLs passed as a compile option (usually via a HTTP source map
2851      * header) override any source map urls passed as comment pragmas.
2852      */
2853     if (parser->options().sourceMapURL()) {
2854         // Warn about the replacement, but use the new one.
2855         if (parser->ss->hasSourceMapURL()) {
2856             if(!parser->report(ParseWarning, false, nullptr, JSMSG_ALREADY_HAS_PRAGMA,
2857                                parser->ss->filename(), "//# sourceMappingURL"))
2858                 return false;
2859         }
2860 
2861         if (!parser->ss->setSourceMapURL(cx, parser->options().sourceMapURL()))
2862             return false;
2863     }
2864 
2865     return true;
2866 }
2867 
2868 void
tellDebuggerAboutCompiledScript(ExclusiveContext * cx)2869 BytecodeEmitter::tellDebuggerAboutCompiledScript(ExclusiveContext* cx)
2870 {
2871     // Note: when parsing off thread the resulting scripts need to be handed to
2872     // the debugger after rejoining to the main thread.
2873     if (!cx->isJSContext())
2874         return;
2875 
2876     // Lazy scripts are never top level (despite always being invoked with a
2877     // nullptr parent), and so the hook should never be fired.
2878     if (emitterMode != LazyFunction && !parent) {
2879         Debugger::onNewScript(cx->asJSContext(), script);
2880     }
2881 }
2882 
2883 inline TokenStream*
tokenStream()2884 BytecodeEmitter::tokenStream()
2885 {
2886     return &parser->tokenStream;
2887 }
2888 
2889 bool
reportError(ParseNode * pn,unsigned errorNumber,...)2890 BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
2891 {
2892     TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
2893 
2894     va_list args;
2895     va_start(args, errorNumber);
2896     bool result = tokenStream()->reportCompileErrorNumberVA(pos.begin, JSREPORT_ERROR,
2897                                                             errorNumber, args);
2898     va_end(args);
2899     return result;
2900 }
2901 
2902 bool
reportStrictWarning(ParseNode * pn,unsigned errorNumber,...)2903 BytecodeEmitter::reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...)
2904 {
2905     TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
2906 
2907     va_list args;
2908     va_start(args, errorNumber);
2909     bool result = tokenStream()->reportStrictWarningErrorNumberVA(pos.begin, errorNumber, args);
2910     va_end(args);
2911     return result;
2912 }
2913 
2914 bool
reportStrictModeError(ParseNode * pn,unsigned errorNumber,...)2915 BytecodeEmitter::reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...)
2916 {
2917     TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
2918 
2919     va_list args;
2920     va_start(args, errorNumber);
2921     bool result = tokenStream()->reportStrictModeErrorNumberVA(pos.begin, sc->strict(),
2922                                                                errorNumber, args);
2923     va_end(args);
2924     return result;
2925 }
2926 
2927 bool
emitNewInit(JSProtoKey key)2928 BytecodeEmitter::emitNewInit(JSProtoKey key)
2929 {
2930     const size_t len = 1 + UINT32_INDEX_LEN;
2931     ptrdiff_t offset;
2932     if (!emitCheck(len, &offset))
2933         return false;
2934 
2935     jsbytecode* code = this->code(offset);
2936     code[0] = JSOP_NEWINIT;
2937     code[1] = jsbytecode(key);
2938     code[2] = 0;
2939     code[3] = 0;
2940     code[4] = 0;
2941     checkTypeSet(JSOP_NEWINIT);
2942     updateDepth(offset);
2943     return true;
2944 }
2945 
2946 bool
iteratorResultShape(unsigned * shape)2947 BytecodeEmitter::iteratorResultShape(unsigned* shape)
2948 {
2949     // No need to do any guessing for the object kind, since we know exactly how
2950     // many properties we plan to have.
2951     gc::AllocKind kind = gc::GetGCObjectKind(2);
2952     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
2953     if (!obj)
2954         return false;
2955 
2956     Rooted<jsid> value_id(cx, AtomToId(cx->names().value));
2957     Rooted<jsid> done_id(cx, AtomToId(cx->names().done));
2958     if (!NativeDefineProperty(cx, obj, value_id, UndefinedHandleValue, nullptr, nullptr,
2959                               JSPROP_ENUMERATE))
2960     {
2961         return false;
2962     }
2963     if (!NativeDefineProperty(cx, obj, done_id, UndefinedHandleValue, nullptr, nullptr,
2964                               JSPROP_ENUMERATE))
2965     {
2966         return false;
2967     }
2968 
2969     ObjectBox* objbox = parser->newObjectBox(obj);
2970     if (!objbox)
2971         return false;
2972 
2973     *shape = objectList.add(objbox);
2974 
2975     return true;
2976 }
2977 
2978 bool
emitPrepareIteratorResult()2979 BytecodeEmitter::emitPrepareIteratorResult()
2980 {
2981     unsigned shape;
2982     if (!iteratorResultShape(&shape))
2983         return false;
2984     return emitIndex32(JSOP_NEWOBJECT, shape);
2985 }
2986 
2987 bool
emitFinishIteratorResult(bool done)2988 BytecodeEmitter::emitFinishIteratorResult(bool done)
2989 {
2990     uint32_t value_id;
2991     if (!makeAtomIndex(cx->names().value, &value_id))
2992         return false;
2993     uint32_t done_id;
2994     if (!makeAtomIndex(cx->names().done, &done_id))
2995         return false;
2996 
2997     if (!emitIndex32(JSOP_INITPROP, value_id))
2998         return false;
2999     if (!emit1(done ? JSOP_TRUE : JSOP_FALSE))
3000         return false;
3001     if (!emitIndex32(JSOP_INITPROP, done_id))
3002         return false;
3003     return true;
3004 }
3005 
3006 bool
emitGetNameAtLocation(JSAtom * name,const NameLocation & loc,bool callContext)3007 BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bool callContext)
3008 {
3009     switch (loc.kind()) {
3010       case NameLocation::Kind::Dynamic:
3011         if (!emitAtomOp(name, JSOP_GETNAME))
3012             return false;
3013         break;
3014 
3015       case NameLocation::Kind::Global:
3016         if (!emitAtomOp(name, JSOP_GETGNAME))
3017             return false;
3018         break;
3019 
3020       case NameLocation::Kind::Intrinsic:
3021         if (!emitAtomOp(name, JSOP_GETINTRINSIC))
3022             return false;
3023         break;
3024 
3025       case NameLocation::Kind::NamedLambdaCallee:
3026         if (!emit1(JSOP_CALLEE))
3027             return false;
3028         break;
3029 
3030       case NameLocation::Kind::Import:
3031         if (!emitAtomOp(name, JSOP_GETIMPORT))
3032             return false;
3033         break;
3034 
3035       case NameLocation::Kind::ArgumentSlot:
3036         if (!emitArgOp(JSOP_GETARG, loc.argumentSlot()))
3037             return false;
3038         break;
3039 
3040       case NameLocation::Kind::FrameSlot:
3041         if (loc.isLexical()) {
3042             if (!emitTDZCheckIfNeeded(name, loc))
3043                 return false;
3044         }
3045         if (!emitLocalOp(JSOP_GETLOCAL, loc.frameSlot()))
3046             return false;
3047         break;
3048 
3049       case NameLocation::Kind::EnvironmentCoordinate:
3050         if (loc.isLexical()) {
3051             if (!emitTDZCheckIfNeeded(name, loc))
3052                 return false;
3053         }
3054         if (!emitEnvCoordOp(JSOP_GETALIASEDVAR, loc.environmentCoordinate()))
3055             return false;
3056         break;
3057 
3058       case NameLocation::Kind::DynamicAnnexBVar:
3059         MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
3060     }
3061 
3062     // Need to provide |this| value for call.
3063     if (callContext) {
3064         switch (loc.kind()) {
3065           case NameLocation::Kind::Dynamic: {
3066             JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS;
3067             if (!emitAtomOp(name, thisOp))
3068                 return false;
3069             break;
3070           }
3071 
3072           case NameLocation::Kind::Global:
3073             if (!emitAtomOp(name, JSOP_GIMPLICITTHIS))
3074                 return false;
3075             break;
3076 
3077           case NameLocation::Kind::Intrinsic:
3078           case NameLocation::Kind::NamedLambdaCallee:
3079           case NameLocation::Kind::Import:
3080           case NameLocation::Kind::ArgumentSlot:
3081           case NameLocation::Kind::FrameSlot:
3082           case NameLocation::Kind::EnvironmentCoordinate:
3083             if (!emit1(JSOP_UNDEFINED))
3084                 return false;
3085             break;
3086 
3087           case NameLocation::Kind::DynamicAnnexBVar:
3088             MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization");
3089         }
3090     }
3091 
3092     return true;
3093 }
3094 
3095 bool
emitGetName(ParseNode * pn,bool callContext)3096 BytecodeEmitter::emitGetName(ParseNode* pn, bool callContext)
3097 {
3098     return emitGetName(pn->name(), callContext);
3099 }
3100 
3101 template <typename RHSEmitter>
3102 bool
emitSetOrInitializeNameAtLocation(HandleAtom name,const NameLocation & loc,RHSEmitter emitRhs,bool initialize)3103 BytecodeEmitter::emitSetOrInitializeNameAtLocation(HandleAtom name, const NameLocation& loc,
3104                                                    RHSEmitter emitRhs, bool initialize)
3105 {
3106     bool emittedBindOp = false;
3107 
3108     switch (loc.kind()) {
3109       case NameLocation::Kind::Dynamic:
3110       case NameLocation::Kind::Import:
3111       case NameLocation::Kind::DynamicAnnexBVar: {
3112         uint32_t atomIndex;
3113         if (!makeAtomIndex(name, &atomIndex))
3114             return false;
3115         if (loc.kind() == NameLocation::Kind::DynamicAnnexBVar) {
3116             // Annex B vars always go on the nearest variable environment,
3117             // even if lexical environments in between contain same-named
3118             // bindings.
3119             if (!emit1(JSOP_BINDVAR))
3120                 return false;
3121         } else {
3122             if (!emitIndexOp(JSOP_BINDNAME, atomIndex))
3123                 return false;
3124         }
3125         emittedBindOp = true;
3126         if (!emitRhs(this, loc, emittedBindOp))
3127             return false;
3128         if (!emitIndexOp(strictifySetNameOp(JSOP_SETNAME), atomIndex))
3129             return false;
3130         break;
3131       }
3132 
3133       case NameLocation::Kind::Global: {
3134         JSOp op;
3135         uint32_t atomIndex;
3136         if (!makeAtomIndex(name, &atomIndex))
3137             return false;
3138         if (loc.isLexical() && initialize) {
3139             // INITGLEXICAL always gets the global lexical scope. It doesn't
3140             // need a BINDGNAME.
3141             MOZ_ASSERT(innermostScope()->is<GlobalScope>());
3142             op = JSOP_INITGLEXICAL;
3143         } else {
3144             if (!emitIndexOp(JSOP_BINDGNAME, atomIndex))
3145                 return false;
3146             emittedBindOp = true;
3147             op = strictifySetNameOp(JSOP_SETGNAME);
3148         }
3149         if (!emitRhs(this, loc, emittedBindOp))
3150             return false;
3151         if (!emitIndexOp(op, atomIndex))
3152             return false;
3153         break;
3154       }
3155 
3156       case NameLocation::Kind::Intrinsic:
3157         if (!emitRhs(this, loc, emittedBindOp))
3158             return false;
3159         if (!emitAtomOp(name, JSOP_SETINTRINSIC))
3160             return false;
3161         break;
3162 
3163       case NameLocation::Kind::NamedLambdaCallee:
3164         if (!emitRhs(this, loc, emittedBindOp))
3165             return false;
3166         // Assigning to the named lambda is a no-op in sloppy mode but
3167         // throws in strict mode.
3168         if (sc->strict() && !emit1(JSOP_THROWSETCALLEE))
3169             return false;
3170         break;
3171 
3172       case NameLocation::Kind::ArgumentSlot: {
3173         // If we assign to a positional formal parameter and the arguments
3174         // object is unmapped (strict mode or function with
3175         // default/rest/destructing args), parameters do not alias
3176         // arguments[i], and to make the arguments object reflect initial
3177         // parameter values prior to any mutation we create it eagerly
3178         // whenever parameters are (or might, in the case of calls to eval)
3179         // assigned.
3180         FunctionBox* funbox = sc->asFunctionBox();
3181         if (funbox->argumentsHasLocalBinding() && !funbox->hasMappedArgsObj())
3182             funbox->setDefinitelyNeedsArgsObj();
3183 
3184         if (!emitRhs(this, loc, emittedBindOp))
3185             return false;
3186         if (!emitArgOp(JSOP_SETARG, loc.argumentSlot()))
3187             return false;
3188         break;
3189       }
3190 
3191       case NameLocation::Kind::FrameSlot: {
3192         JSOp op = JSOP_SETLOCAL;
3193         if (!emitRhs(this, loc, emittedBindOp))
3194             return false;
3195         if (loc.isLexical()) {
3196             if (initialize) {
3197                 op = JSOP_INITLEXICAL;
3198             } else {
3199                 if (loc.isConst())
3200                     op = JSOP_THROWSETCONST;
3201 
3202                 if (!emitTDZCheckIfNeeded(name, loc))
3203                     return false;
3204             }
3205         }
3206         if (!emitLocalOp(op, loc.frameSlot()))
3207             return false;
3208         if (op == JSOP_INITLEXICAL) {
3209             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
3210                 return false;
3211         }
3212         break;
3213       }
3214 
3215       case NameLocation::Kind::EnvironmentCoordinate: {
3216         JSOp op = JSOP_SETALIASEDVAR;
3217         if (!emitRhs(this, loc, emittedBindOp))
3218             return false;
3219         if (loc.isLexical()) {
3220             if (initialize) {
3221                 op = JSOP_INITALIASEDLEXICAL;
3222             } else {
3223                 if (loc.isConst())
3224                     op = JSOP_THROWSETALIASEDCONST;
3225 
3226                 if (!emitTDZCheckIfNeeded(name, loc))
3227                     return false;
3228             }
3229         }
3230         if (loc.bindingKind() == BindingKind::NamedLambdaCallee) {
3231             // Assigning to the named lambda is a no-op in sloppy mode and throws
3232             // in strict mode.
3233             op = JSOP_THROWSETALIASEDCONST;
3234             if (sc->strict() && !emitEnvCoordOp(op, loc.environmentCoordinate()))
3235                 return false;
3236         } else {
3237             if (!emitEnvCoordOp(op, loc.environmentCoordinate()))
3238                 return false;
3239         }
3240         if (op == JSOP_INITALIASEDLEXICAL) {
3241             if (!innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ))
3242                 return false;
3243         }
3244         break;
3245       }
3246     }
3247 
3248     return true;
3249 }
3250 
3251 bool
emitTDZCheckIfNeeded(JSAtom * name,const NameLocation & loc)3252 BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc)
3253 {
3254     // Dynamic accesses have TDZ checks built into their VM code and should
3255     // never emit explicit TDZ checks.
3256     MOZ_ASSERT(loc.hasKnownSlot());
3257     MOZ_ASSERT(loc.isLexical());
3258 
3259     Maybe<MaybeCheckTDZ> check = innermostTDZCheckCache->needsTDZCheck(this, name);
3260     if (!check)
3261         return false;
3262 
3263     // We've already emitted a check in this basic block.
3264     if (*check == DontCheckTDZ)
3265         return true;
3266 
3267     if (loc.kind() == NameLocation::Kind::FrameSlot) {
3268         if (!emitLocalOp(JSOP_CHECKLEXICAL, loc.frameSlot()))
3269             return false;
3270     } else {
3271         if (!emitEnvCoordOp(JSOP_CHECKALIASEDLEXICAL, loc.environmentCoordinate()))
3272             return false;
3273     }
3274 
3275     return innermostTDZCheckCache->noteTDZCheck(this, name, DontCheckTDZ);
3276 }
3277 
3278 bool
emitPropLHS(ParseNode * pn)3279 BytecodeEmitter::emitPropLHS(ParseNode* pn)
3280 {
3281     MOZ_ASSERT(pn->isKind(PNK_DOT));
3282     MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
3283 
3284     ParseNode* pn2 = pn->pn_expr;
3285 
3286     /*
3287      * If the object operand is also a dotted property reference, reverse the
3288      * list linked via pn_expr temporarily so we can iterate over it from the
3289      * bottom up (reversing again as we go), to avoid excessive recursion.
3290      */
3291     if (pn2->isKind(PNK_DOT) && !pn2->as<PropertyAccess>().isSuper()) {
3292         ParseNode* pndot = pn2;
3293         ParseNode* pnup = nullptr;
3294         ParseNode* pndown;
3295         for (;;) {
3296             /* Reverse pndot->pn_expr to point up, not down. */
3297             pndown = pndot->pn_expr;
3298             pndot->pn_expr = pnup;
3299             if (!pndown->isKind(PNK_DOT) || pndown->as<PropertyAccess>().isSuper())
3300                 break;
3301             pnup = pndot;
3302             pndot = pndown;
3303         }
3304 
3305         /* pndown is a primary expression, not a dotted property reference. */
3306         if (!emitTree(pndown))
3307             return false;
3308 
3309         do {
3310             /* Walk back up the list, emitting annotated name ops. */
3311             if (!emitAtomOp(pndot, JSOP_GETPROP))
3312                 return false;
3313 
3314             /* Reverse the pn_expr link again. */
3315             pnup = pndot->pn_expr;
3316             pndot->pn_expr = pndown;
3317             pndown = pndot;
3318         } while ((pndot = pnup) != nullptr);
3319         return true;
3320     }
3321 
3322     // The non-optimized case.
3323     return emitTree(pn2);
3324 }
3325 
3326 bool
emitSuperPropLHS(ParseNode * superBase,bool isCall)3327 BytecodeEmitter::emitSuperPropLHS(ParseNode* superBase, bool isCall)
3328 {
3329     if (!emitGetThisForSuperBase(superBase))
3330         return false;
3331     if (isCall && !emit1(JSOP_DUP))
3332         return false;
3333     if (!emit1(JSOP_SUPERBASE))
3334         return false;
3335     return true;
3336 }
3337 
3338 bool
emitPropOp(ParseNode * pn,JSOp op)3339 BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
3340 {
3341     MOZ_ASSERT(pn->isArity(PN_NAME));
3342 
3343     if (!emitPropLHS(pn))
3344         return false;
3345 
3346     if (op == JSOP_CALLPROP && !emit1(JSOP_DUP))
3347         return false;
3348 
3349     if (!emitAtomOp(pn, op))
3350         return false;
3351 
3352     if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP))
3353         return false;
3354 
3355     return true;
3356 }
3357 
3358 bool
emitSuperPropOp(ParseNode * pn,JSOp op,bool isCall)3359 BytecodeEmitter::emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall)
3360 {
3361     ParseNode* base = &pn->as<PropertyAccess>().expression();
3362     if (!emitSuperPropLHS(base, isCall))
3363         return false;
3364 
3365     if (!emitAtomOp(pn, op))
3366         return false;
3367 
3368     if (isCall && !emit1(JSOP_SWAP))
3369         return false;
3370 
3371     return true;
3372 }
3373 
3374 bool
emitPropIncDec(ParseNode * pn)3375 BytecodeEmitter::emitPropIncDec(ParseNode* pn)
3376 {
3377     MOZ_ASSERT(pn->pn_kid->isKind(PNK_DOT));
3378 
3379     bool post;
3380     bool isSuper = pn->pn_kid->as<PropertyAccess>().isSuper();
3381     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
3382 
3383     if (isSuper) {
3384         ParseNode* base = &pn->pn_kid->as<PropertyAccess>().expression();
3385         if (!emitSuperPropLHS(base))                // THIS OBJ
3386             return false;
3387         if (!emit1(JSOP_DUP2))                      // THIS OBJ THIS OBJ
3388             return false;
3389     } else {
3390         if (!emitPropLHS(pn->pn_kid))               // OBJ
3391             return false;
3392         if (!emit1(JSOP_DUP))                       // OBJ OBJ
3393             return false;
3394     }
3395     if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
3396         return false;
3397     if (!emit1(JSOP_POS))                           // OBJ N
3398         return false;
3399     if (post && !emit1(JSOP_DUP))                   // OBJ N? N
3400         return false;
3401     if (!emit1(JSOP_ONE))                           // OBJ N? N 1
3402         return false;
3403     if (!emit1(binop))                              // OBJ N? N+1
3404         return false;
3405 
3406     if (post) {
3407         if (!emit2(JSOP_PICK, 2 + isSuper))        // N? N+1 OBJ
3408             return false;
3409         if (!emit1(JSOP_SWAP))                     // N? OBJ N+1
3410             return false;
3411         if (isSuper) {
3412             if (!emit2(JSOP_PICK, 3))              // N THIS N+1 OBJ
3413                 return false;
3414             if (!emit1(JSOP_SWAP))                 // N THIS OBJ N+1
3415                 return false;
3416         }
3417     }
3418 
3419     JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
3420                          : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
3421     if (!emitAtomOp(pn->pn_kid, setOp))             // N? N+1
3422         return false;
3423     if (post && !emit1(JSOP_POP))                   // RESULT
3424         return false;
3425 
3426     return true;
3427 }
3428 
3429 bool
emitNameIncDec(ParseNode * pn)3430 BytecodeEmitter::emitNameIncDec(ParseNode* pn)
3431 {
3432     MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME));
3433 
3434     bool post;
3435     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
3436 
3437     auto emitRhs = [pn, post, binop](BytecodeEmitter* bce, const NameLocation& loc,
3438                                      bool emittedBindOp)
3439     {
3440         JSAtom* name = pn->pn_kid->name();
3441         if (!bce->emitGetNameAtLocation(name, loc, false)) // SCOPE? V
3442             return false;
3443         if (!bce->emit1(JSOP_POS))                         // SCOPE? N
3444             return false;
3445         if (post && !bce->emit1(JSOP_DUP))                 // SCOPE? N? N
3446             return false;
3447         if (!bce->emit1(JSOP_ONE))                         // SCOPE? N? N 1
3448             return false;
3449         if (!bce->emit1(binop))                            // SCOPE? N? N+1
3450             return false;
3451 
3452         if (post && emittedBindOp) {
3453             if (!bce->emit2(JSOP_PICK, 2))                 // N? N+1 SCOPE?
3454                 return false;
3455             if (!bce->emit1(JSOP_SWAP))                    // N? SCOPE? N+1
3456                 return false;
3457         }
3458 
3459         return true;
3460     };
3461 
3462     if (!emitSetName(pn->pn_kid, emitRhs))
3463         return false;
3464 
3465     if (post && !emit1(JSOP_POP))
3466         return false;
3467 
3468     return true;
3469 }
3470 
3471 bool
emitElemOperands(ParseNode * pn,EmitElemOption opts)3472 BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
3473 {
3474     MOZ_ASSERT(pn->isArity(PN_BINARY));
3475 
3476     if (!emitTree(pn->pn_left))
3477         return false;
3478 
3479     if (opts == EmitElemOption::IncDec) {
3480         if (!emit1(JSOP_CHECKOBJCOERCIBLE))
3481             return false;
3482     } else if (opts == EmitElemOption::Call) {
3483         if (!emit1(JSOP_DUP))
3484             return false;
3485     }
3486 
3487     if (!emitTree(pn->pn_right))
3488         return false;
3489 
3490     if (opts == EmitElemOption::Set) {
3491         if (!emit2(JSOP_PICK, 2))
3492             return false;
3493     } else if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
3494         if (!emit1(JSOP_TOID))
3495             return false;
3496     }
3497     return true;
3498 }
3499 
3500 bool
emitSuperElemOperands(ParseNode * pn,EmitElemOption opts)3501 BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
3502 {
3503     MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
3504 
3505     // The ordering here is somewhat screwy. We need to evaluate the propval
3506     // first, by spec. Do a little dance to not emit more than one JSOP_THIS.
3507     // Since JSOP_THIS might throw in derived class constructors, we cannot
3508     // just push it earlier as the receiver. We have to swap it down instead.
3509 
3510     if (!emitTree(pn->pn_right))
3511         return false;
3512 
3513     // We need to convert the key to an object id first, so that we do not do
3514     // it inside both the GETELEM and the SETELEM.
3515     if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) {
3516         if (!emit1(JSOP_TOID))
3517             return false;
3518     }
3519 
3520     if (!emitGetThisForSuperBase(pn->pn_left))
3521         return false;
3522 
3523     if (opts == EmitElemOption::Call) {
3524         if (!emit1(JSOP_SWAP))
3525             return false;
3526 
3527         // We need another |this| on top, also
3528         if (!emitDupAt(1))
3529             return false;
3530     }
3531 
3532     if (!emit1(JSOP_SUPERBASE))
3533         return false;
3534 
3535     if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 3))
3536         return false;
3537 
3538     return true;
3539 }
3540 
3541 bool
emitElemOpBase(JSOp op)3542 BytecodeEmitter::emitElemOpBase(JSOp op)
3543 {
3544     if (!emit1(op))
3545         return false;
3546 
3547     checkTypeSet(op);
3548     return true;
3549 }
3550 
3551 bool
emitElemOp(ParseNode * pn,JSOp op)3552 BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op)
3553 {
3554     EmitElemOption opts = EmitElemOption::Get;
3555     if (op == JSOP_CALLELEM)
3556         opts = EmitElemOption::Call;
3557     else if (op == JSOP_SETELEM || op == JSOP_STRICTSETELEM)
3558         opts = EmitElemOption::Set;
3559 
3560     return emitElemOperands(pn, opts) && emitElemOpBase(op);
3561 }
3562 
3563 bool
emitSuperElemOp(ParseNode * pn,JSOp op,bool isCall)3564 BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
3565 {
3566     EmitElemOption opts = EmitElemOption::Get;
3567     if (isCall)
3568         opts = EmitElemOption::Call;
3569     else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
3570         opts = EmitElemOption::Set;
3571 
3572     if (!emitSuperElemOperands(pn, opts))
3573         return false;
3574     if (!emitElemOpBase(op))
3575         return false;
3576 
3577     if (isCall && !emit1(JSOP_SWAP))
3578         return false;
3579 
3580     return true;
3581 }
3582 
3583 bool
emitElemIncDec(ParseNode * pn)3584 BytecodeEmitter::emitElemIncDec(ParseNode* pn)
3585 {
3586     MOZ_ASSERT(pn->pn_kid->isKind(PNK_ELEM));
3587 
3588     bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
3589 
3590     // We need to convert the key to an object id first, so that we do not do
3591     // it inside both the GETELEM and the SETELEM. This is done by
3592     // emit(Super)ElemOperands.
3593     if (isSuper) {
3594         if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
3595             return false;
3596     } else {
3597         if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec))
3598             return false;
3599     }
3600 
3601     bool post;
3602     JSOp binop = GetIncDecInfo(pn->getKind(), &post);
3603 
3604     JSOp getOp;
3605     if (isSuper) {
3606         // There's no such thing as JSOP_DUP3, so we have to be creative.
3607         // Note that pushing things again is no fewer JSOps.
3608         if (!emitDupAt(2))                              // KEY THIS OBJ KEY
3609             return false;
3610         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS
3611             return false;
3612         if (!emitDupAt(2))                              // KEY THIS OBJ KEY THIS OBJ
3613             return false;
3614         getOp = JSOP_GETELEM_SUPER;
3615     } else {
3616                                                         // OBJ KEY
3617         if (!emit1(JSOP_DUP2))                          // OBJ KEY OBJ KEY
3618             return false;
3619         getOp = JSOP_GETELEM;
3620     }
3621     if (!emitElemOpBase(getOp))                         // OBJ KEY V
3622         return false;
3623     if (!emit1(JSOP_POS))                               // OBJ KEY N
3624         return false;
3625     if (post && !emit1(JSOP_DUP))                       // OBJ KEY N? N
3626         return false;
3627     if (!emit1(JSOP_ONE))                               // OBJ KEY N? N 1
3628         return false;
3629     if (!emit1(binop))                                  // OBJ KEY N? N+1
3630         return false;
3631 
3632     if (post) {
3633         if (isSuper) {
3634             // We have one more value to rotate around, because of |this|
3635             // on the stack
3636             if (!emit2(JSOP_PICK, 4))
3637                 return false;
3638         }
3639         if (!emit2(JSOP_PICK, 3 + isSuper))             // KEY N N+1 OBJ
3640             return false;
3641         if (!emit2(JSOP_PICK, 3 + isSuper))             // N N+1 OBJ KEY
3642             return false;
3643         if (!emit2(JSOP_PICK, 2 + isSuper))             // N OBJ KEY N+1
3644             return false;
3645     }
3646 
3647     JSOp setOp = isSuper ? (sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER)
3648                          : (sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM);
3649     if (!emitElemOpBase(setOp))                         // N? N+1
3650         return false;
3651     if (post && !emit1(JSOP_POP))                       // RESULT
3652         return false;
3653 
3654     return true;
3655 }
3656 
3657 bool
emitCallIncDec(ParseNode * incDec)3658 BytecodeEmitter::emitCallIncDec(ParseNode* incDec)
3659 {
3660     MOZ_ASSERT(incDec->isKind(PNK_PREINCREMENT) ||
3661                incDec->isKind(PNK_POSTINCREMENT) ||
3662                incDec->isKind(PNK_PREDECREMENT) ||
3663                incDec->isKind(PNK_POSTDECREMENT));
3664 
3665     MOZ_ASSERT(incDec->pn_kid->isKind(PNK_CALL));
3666 
3667     ParseNode* call = incDec->pn_kid;
3668     if (!emitTree(call))                                // CALLRESULT
3669         return false;
3670     if (!emit1(JSOP_POS))                               // N
3671         return false;
3672 
3673     // The increment/decrement has no side effects, so proceed to throw for
3674     // invalid assignment target.
3675     return emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS);
3676 }
3677 
3678 bool
emitNumberOp(double dval)3679 BytecodeEmitter::emitNumberOp(double dval)
3680 {
3681     int32_t ival;
3682     if (NumberIsInt32(dval, &ival)) {
3683         if (ival == 0)
3684             return emit1(JSOP_ZERO);
3685         if (ival == 1)
3686             return emit1(JSOP_ONE);
3687         if ((int)(int8_t)ival == ival)
3688             return emit2(JSOP_INT8, uint8_t(int8_t(ival)));
3689 
3690         uint32_t u = uint32_t(ival);
3691         if (u < JS_BIT(16)) {
3692             if (!emitUint16Operand(JSOP_UINT16, u))
3693                 return false;
3694         } else if (u < JS_BIT(24)) {
3695             ptrdiff_t off;
3696             if (!emitN(JSOP_UINT24, 3, &off))
3697                 return false;
3698             SET_UINT24(code(off), u);
3699         } else {
3700             ptrdiff_t off;
3701             if (!emitN(JSOP_INT32, 4, &off))
3702                 return false;
3703             SET_INT32(code(off), ival);
3704         }
3705         return true;
3706     }
3707 
3708     if (!constList.append(DoubleValue(dval)))
3709         return false;
3710 
3711     return emitIndex32(JSOP_DOUBLE, constList.length() - 1);
3712 }
3713 
3714 /*
3715  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
3716  * LLVM is deciding to inline this function which uses a lot of stack space
3717  * into emitTree which is recursive and uses relatively little stack space.
3718  */
3719 MOZ_NEVER_INLINE bool
emitSwitch(ParseNode * pn)3720 BytecodeEmitter::emitSwitch(ParseNode* pn)
3721 {
3722     ParseNode* cases = pn->pn_right;
3723     MOZ_ASSERT(cases->isKind(PNK_LEXICALSCOPE) || cases->isKind(PNK_STATEMENTLIST));
3724 
3725     // Emit code for the discriminant.
3726     if (!emitTree(pn->pn_left))
3727         return false;
3728 
3729     // Enter the scope before pushing the switch BreakableControl since all
3730     // breaks are under this scope.
3731     Maybe<TDZCheckCache> tdzCache;
3732     Maybe<EmitterScope> emitterScope;
3733     if (cases->isKind(PNK_LEXICALSCOPE)) {
3734         if (!cases->isEmptyScope()) {
3735             tdzCache.emplace(this);
3736             emitterScope.emplace(this);
3737             if (!emitterScope->enterLexical(this, ScopeKind::Lexical, cases->scopeBindings()))
3738                 return false;
3739         }
3740 
3741         // Advance |cases| to refer to the switch case list.
3742         cases = cases->scopeBody();
3743 
3744         // A switch statement may contain hoisted functions inside its
3745         // cases. The PNX_FUNCDEFS flag is propagated from the STATEMENTLIST
3746         // bodies of the cases to the case list.
3747         if (cases->pn_xflags & PNX_FUNCDEFS) {
3748             MOZ_ASSERT(emitterScope);
3749             for (ParseNode* caseNode = cases->pn_head; caseNode; caseNode = caseNode->pn_next) {
3750                 if (caseNode->pn_right->pn_xflags & PNX_FUNCDEFS) {
3751                     if (!emitHoistedFunctionsInList(caseNode->pn_right))
3752                         return false;
3753                 }
3754             }
3755         }
3756     }
3757 
3758     // After entering the scope, push the switch control.
3759     BreakableControl controlInfo(this, StatementKind::Switch);
3760 
3761     ptrdiff_t top = offset();
3762 
3763     // Switch bytecodes run from here till end of final case.
3764     uint32_t caseCount = cases->pn_count;
3765     if (caseCount > JS_BIT(16)) {
3766         parser->tokenStream.reportError(JSMSG_TOO_MANY_CASES);
3767         return false;
3768     }
3769 
3770     // Try for most optimal, fall back if not dense ints.
3771     JSOp switchOp = JSOP_TABLESWITCH;
3772     uint32_t tableLength = 0;
3773     int32_t low, high;
3774     bool hasDefault = false;
3775     CaseClause* firstCase = cases->pn_head ? &cases->pn_head->as<CaseClause>() : nullptr;
3776     if (caseCount == 0 ||
3777         (caseCount == 1 && (hasDefault = firstCase->isDefault())))
3778     {
3779         caseCount = 0;
3780         low = 0;
3781         high = -1;
3782     } else {
3783         Vector<jsbitmap, 128, SystemAllocPolicy> intmap;
3784         int32_t intmapBitLength = 0;
3785 
3786         low  = JSVAL_INT_MAX;
3787         high = JSVAL_INT_MIN;
3788 
3789         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
3790             if (caseNode->isDefault()) {
3791                 hasDefault = true;
3792                 caseCount--;  // one of the "cases" was the default
3793                 continue;
3794             }
3795 
3796             if (switchOp == JSOP_CONDSWITCH)
3797                 continue;
3798 
3799             MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
3800 
3801             ParseNode* caseValue = caseNode->caseExpression();
3802 
3803             if (caseValue->getKind() != PNK_NUMBER) {
3804                 switchOp = JSOP_CONDSWITCH;
3805                 continue;
3806             }
3807 
3808             int32_t i;
3809             if (!NumberIsInt32(caseValue->pn_dval, &i)) {
3810                 switchOp = JSOP_CONDSWITCH;
3811                 continue;
3812             }
3813 
3814             if (unsigned(i + int(JS_BIT(15))) >= unsigned(JS_BIT(16))) {
3815                 switchOp = JSOP_CONDSWITCH;
3816                 continue;
3817             }
3818             if (i < low)
3819                 low = i;
3820             if (i > high)
3821                 high = i;
3822 
3823             // Check for duplicates, which require a JSOP_CONDSWITCH.
3824             // We bias i by 65536 if it's negative, and hope that's a rare
3825             // case (because it requires a malloc'd bitmap).
3826             if (i < 0)
3827                 i += JS_BIT(16);
3828             if (i >= intmapBitLength) {
3829                 size_t newLength = (i / JS_BITMAP_NBITS) + 1;
3830                 if (!intmap.resize(newLength))
3831                     return false;
3832                 intmapBitLength = newLength * JS_BITMAP_NBITS;
3833             }
3834             if (JS_TEST_BIT(intmap, i)) {
3835                 switchOp = JSOP_CONDSWITCH;
3836                 continue;
3837             }
3838             JS_SET_BIT(intmap, i);
3839         }
3840 
3841         // Compute table length and select condswitch instead if overlarge or
3842         // more than half-sparse.
3843         if (switchOp == JSOP_TABLESWITCH) {
3844             tableLength = uint32_t(high - low + 1);
3845             if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
3846                 switchOp = JSOP_CONDSWITCH;
3847         }
3848     }
3849 
3850     // The note has one or two offsets: first tells total switch code length;
3851     // second (if condswitch) tells offset to first JSOP_CASE.
3852     unsigned noteIndex;
3853     size_t switchSize;
3854     if (switchOp == JSOP_CONDSWITCH) {
3855         // 0 bytes of immediate for unoptimized switch.
3856         switchSize = 0;
3857         if (!newSrcNote3(SRC_CONDSWITCH, 0, 0, &noteIndex))
3858             return false;
3859     } else {
3860         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
3861 
3862         // 3 offsets (len, low, high) before the table, 1 per entry.
3863         switchSize = size_t(JUMP_OFFSET_LEN * (3 + tableLength));
3864         if (!newSrcNote2(SRC_TABLESWITCH, 0, &noteIndex))
3865             return false;
3866     }
3867 
3868     // Emit switchOp followed by switchSize bytes of jump or lookup table.
3869     MOZ_ASSERT(top == offset());
3870     if (!emitN(switchOp, switchSize))
3871         return false;
3872 
3873     Vector<CaseClause*, 32, SystemAllocPolicy> table;
3874 
3875     JumpList condSwitchDefaultOff;
3876     if (switchOp == JSOP_CONDSWITCH) {
3877         unsigned caseNoteIndex;
3878         bool beforeCases = true;
3879         ptrdiff_t lastCaseOffset = -1;
3880 
3881         // The case conditions need their own TDZ cache since they might not
3882         // all execute.
3883         TDZCheckCache tdzCache(this);
3884 
3885         // Emit code for evaluating cases and jumping to case statements.
3886         for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
3887             ParseNode* caseValue = caseNode->caseExpression();
3888 
3889             // If the expression is a literal, suppress line number emission so
3890             // that debugging works more naturally.
3891             if (caseValue) {
3892                 if (!emitTree(caseValue,
3893                               caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE))
3894                 {
3895                     return false;
3896                 }
3897             }
3898 
3899             if (!beforeCases) {
3900                 // prevCase is the previous JSOP_CASE's bytecode offset.
3901                 if (!setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
3902                     return false;
3903             }
3904             if (!caseValue) {
3905                 // This is the default clause.
3906                 continue;
3907             }
3908 
3909             if (!newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex))
3910                 return false;
3911 
3912             // The case clauses are produced before any of the case body. The
3913             // JumpList is saved on the parsed tree, then later restored and
3914             // patched when generating the cases body.
3915             JumpList caseJump;
3916             if (!emitJump(JSOP_CASE, &caseJump))
3917                 return false;
3918             caseNode->setOffset(caseJump.offset);
3919             lastCaseOffset = caseJump.offset;
3920 
3921             if (beforeCases) {
3922                 // Switch note's second offset is to first JSOP_CASE.
3923                 unsigned noteCount = notes().length();
3924                 if (!setSrcNoteOffset(noteIndex, 1, lastCaseOffset - top))
3925                     return false;
3926                 unsigned noteCountDelta = notes().length() - noteCount;
3927                 if (noteCountDelta != 0)
3928                     caseNoteIndex += noteCountDelta;
3929                 beforeCases = false;
3930             }
3931         }
3932 
3933         // If we didn't have an explicit default (which could fall in between
3934         // cases, preventing us from fusing this setSrcNoteOffset with the call
3935         // in the loop above), link the last case to the implicit default for
3936         // the benefit of IonBuilder.
3937         if (!hasDefault &&
3938             !beforeCases &&
3939             !setSrcNoteOffset(caseNoteIndex, 0, offset() - lastCaseOffset))
3940         {
3941             return false;
3942         }
3943 
3944         // Emit default even if no explicit default statement.
3945         if (!emitJump(JSOP_DEFAULT, &condSwitchDefaultOff))
3946             return false;
3947     } else {
3948         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
3949 
3950         // skip default offset.
3951         jsbytecode* pc = code(top + JUMP_OFFSET_LEN);
3952 
3953         // Fill in switch bounds, which we know fit in 16-bit offsets.
3954         SET_JUMP_OFFSET(pc, low);
3955         pc += JUMP_OFFSET_LEN;
3956         SET_JUMP_OFFSET(pc, high);
3957         pc += JUMP_OFFSET_LEN;
3958 
3959         if (tableLength != 0) {
3960             if (!table.growBy(tableLength))
3961                 return false;
3962 
3963             for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
3964                 if (ParseNode* caseValue = caseNode->caseExpression()) {
3965                     MOZ_ASSERT(caseValue->isKind(PNK_NUMBER));
3966 
3967                     int32_t i = int32_t(caseValue->pn_dval);
3968                     MOZ_ASSERT(double(i) == caseValue->pn_dval);
3969 
3970                     i -= low;
3971                     MOZ_ASSERT(uint32_t(i) < tableLength);
3972                     MOZ_ASSERT(!table[i]);
3973                     table[i] = caseNode;
3974                 }
3975             }
3976         }
3977     }
3978 
3979     JumpTarget defaultOffset{ -1 };
3980 
3981     // Emit code for each case's statements.
3982     for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
3983         if (switchOp == JSOP_CONDSWITCH && !caseNode->isDefault()) {
3984             // The case offset got saved in the caseNode structure after
3985             // emitting the JSOP_CASE jump instruction above.
3986             JumpList caseCond;
3987             caseCond.offset = caseNode->offset();
3988             if (!emitJumpTargetAndPatch(caseCond))
3989                 return false;
3990         }
3991 
3992         JumpTarget here;
3993         if (!emitJumpTarget(&here))
3994             return false;
3995         if (caseNode->isDefault())
3996             defaultOffset = here;
3997 
3998         // If this is emitted as a TABLESWITCH, we'll need to know this case's
3999         // offset later when emitting the table. Store it in the node's
4000         // pn_offset (giving the field a different meaning vs. how we used it
4001         // on the immediately preceding line of code).
4002         caseNode->setOffset(here.offset);
4003 
4004         TDZCheckCache tdzCache(this);
4005 
4006         if (!emitTree(caseNode->statementList()))
4007             return false;
4008     }
4009 
4010     if (!hasDefault) {
4011         // If no default case, offset for default is to end of switch.
4012         if (!emitJumpTarget(&defaultOffset))
4013             return false;
4014     }
4015     MOZ_ASSERT(defaultOffset.offset != -1);
4016 
4017     // Set the default offset (to end of switch if no default).
4018     jsbytecode* pc;
4019     if (switchOp == JSOP_CONDSWITCH) {
4020         pc = nullptr;
4021         patchJumpsToTarget(condSwitchDefaultOff, defaultOffset);
4022     } else {
4023         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
4024         pc = code(top);
4025         SET_JUMP_OFFSET(pc, defaultOffset.offset - top);
4026         pc += JUMP_OFFSET_LEN;
4027     }
4028 
4029     // Set the SRC_SWITCH note's offset operand to tell end of switch.
4030     if (!setSrcNoteOffset(noteIndex, 0, lastNonJumpTargetOffset() - top))
4031         return false;
4032 
4033     if (switchOp == JSOP_TABLESWITCH) {
4034         // Skip over the already-initialized switch bounds.
4035         pc += 2 * JUMP_OFFSET_LEN;
4036 
4037         // Fill in the jump table, if there is one.
4038         for (uint32_t i = 0; i < tableLength; i++) {
4039             CaseClause* caseNode = table[i];
4040             ptrdiff_t off = caseNode ? caseNode->offset() - top : 0;
4041             SET_JUMP_OFFSET(pc, off);
4042             pc += JUMP_OFFSET_LEN;
4043         }
4044     }
4045 
4046     // Patch breaks before leaving the scope, as all breaks are under the
4047     // lexical scope if it exists.
4048     if (!controlInfo.patchBreaks(this))
4049         return false;
4050 
4051     if (emitterScope && !emitterScope->leave(this))
4052         return false;
4053 
4054     return true;
4055 }
4056 
4057 bool
isRunOnceLambda()4058 BytecodeEmitter::isRunOnceLambda()
4059 {
4060     // The run once lambda flags set by the parser are approximate, and we look
4061     // at properties of the function itself before deciding to emit a function
4062     // as a run once lambda.
4063 
4064     if (!(parent && parent->emittingRunOnceLambda) &&
4065         (emitterMode != LazyFunction || !lazyScript->treatAsRunOnce()))
4066     {
4067         return false;
4068     }
4069 
4070     FunctionBox* funbox = sc->asFunctionBox();
4071     return !funbox->argumentsHasLocalBinding() &&
4072            !funbox->isGenerator() &&
4073            !funbox->function()->name();
4074 }
4075 
4076 bool
emitYieldOp(JSOp op)4077 BytecodeEmitter::emitYieldOp(JSOp op)
4078 {
4079     if (op == JSOP_FINALYIELDRVAL)
4080         return emit1(JSOP_FINALYIELDRVAL);
4081 
4082     MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD);
4083 
4084     ptrdiff_t off;
4085     if (!emitN(op, 3, &off))
4086         return false;
4087 
4088     uint32_t yieldIndex = yieldOffsetList.length();
4089     if (yieldIndex >= JS_BIT(24)) {
4090         reportError(nullptr, JSMSG_TOO_MANY_YIELDS);
4091         return false;
4092     }
4093 
4094     SET_UINT24(code(off), yieldIndex);
4095 
4096     if (!yieldOffsetList.append(offset()))
4097         return false;
4098 
4099     return emit1(JSOP_DEBUGAFTERYIELD);
4100 }
4101 
4102 bool
emitSetThis(ParseNode * pn)4103 BytecodeEmitter::emitSetThis(ParseNode* pn)
4104 {
4105     // PNK_SETTHIS is used to update |this| after a super() call in a derived
4106     // class constructor.
4107 
4108     MOZ_ASSERT(pn->isKind(PNK_SETTHIS));
4109     MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME));
4110 
4111     RootedAtom name(cx, pn->pn_left->name());
4112     auto emitRhs = [&name, pn](BytecodeEmitter* bce, const NameLocation&, bool) {
4113         // Emit the new |this| value.
4114         if (!bce->emitTree(pn->pn_right))
4115             return false;
4116         // Get the original |this| and throw if we already initialized
4117         // it. Do *not* use the NameLocation argument, as that's the special
4118         // lexical location below to deal with super() semantics.
4119         if (!bce->emitGetName(name))
4120             return false;
4121         if (!bce->emit1(JSOP_CHECKTHISREINIT))
4122             return false;
4123         if (!bce->emit1(JSOP_POP))
4124             return false;
4125         return true;
4126     };
4127 
4128     // The 'this' binding is not lexical, but due to super() semantics this
4129     // initialization needs to be treated as a lexical one.
4130     NameLocation loc = lookupName(name);
4131     NameLocation lexicalLoc;
4132     if (loc.kind() == NameLocation::Kind::FrameSlot) {
4133         lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
4134     } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
4135         EnvironmentCoordinate coord = loc.environmentCoordinate();
4136         uint8_t hops = AssertedCast<uint8_t>(coord.hops());
4137         lexicalLoc = NameLocation::EnvironmentCoordinate(BindingKind::Let, hops, coord.slot());
4138     } else {
4139         MOZ_ASSERT(loc.kind() == NameLocation::Kind::Dynamic);
4140         lexicalLoc = loc;
4141     }
4142 
4143     return emitSetOrInitializeNameAtLocation(name, lexicalLoc, emitRhs, true);
4144 }
4145 
4146 bool
emitScript(ParseNode * body)4147 BytecodeEmitter::emitScript(ParseNode* body)
4148 {
4149     TDZCheckCache tdzCache(this);
4150     EmitterScope emitterScope(this);
4151     if (sc->isGlobalContext()) {
4152         switchToPrologue();
4153         if (!emitterScope.enterGlobal(this, sc->asGlobalContext()))
4154             return false;
4155         switchToMain();
4156     } else if (sc->isEvalContext()) {
4157         switchToPrologue();
4158         if (!emitterScope.enterEval(this, sc->asEvalContext()))
4159             return false;
4160         switchToMain();
4161     } else {
4162         MOZ_ASSERT(sc->isModuleContext());
4163         if (!emitterScope.enterModule(this, sc->asModuleContext()))
4164             return false;
4165     }
4166 
4167     setFunctionBodyEndPos(body->pn_pos);
4168 
4169     if (sc->isEvalContext() && !sc->strict() &&
4170         body->isKind(PNK_LEXICALSCOPE) && !body->isEmptyScope())
4171     {
4172         // Sloppy eval scripts may need to emit DEFFUNs in the prologue. If there is
4173         // an immediately enclosed lexical scope, we need to enter the lexical
4174         // scope in the prologue for the DEFFUNs to pick up the right
4175         // environment chain.
4176         EmitterScope lexicalEmitterScope(this);
4177 
4178         switchToPrologue();
4179         if (!lexicalEmitterScope.enterLexical(this, ScopeKind::Lexical, body->scopeBindings()))
4180             return false;
4181         switchToMain();
4182 
4183         if (!emitLexicalScopeBody(body->scopeBody()))
4184             return false;
4185 
4186         if (!lexicalEmitterScope.leave(this))
4187             return false;
4188     } else {
4189         if (!emitTree(body))
4190             return false;
4191     }
4192 
4193     if (!emit1(JSOP_RETRVAL))
4194         return false;
4195 
4196     if (!emitterScope.leave(this))
4197         return false;
4198 
4199     if (!JSScript::fullyInitFromEmitter(cx, script, this))
4200         return false;
4201 
4202     // URL and source map information must be set before firing
4203     // Debugger::onNewScript.
4204     if (!maybeSetDisplayURL() || !maybeSetSourceMap())
4205         return false;
4206 
4207     tellDebuggerAboutCompiledScript(cx);
4208 
4209     return true;
4210 }
4211 
4212 bool
emitFunctionScript(ParseNode * body)4213 BytecodeEmitter::emitFunctionScript(ParseNode* body)
4214 {
4215     FunctionBox* funbox = sc->asFunctionBox();
4216 
4217     // The ordering of these EmitterScopes is important. The named lambda
4218     // scope needs to enclose the function scope needs to enclose the extra
4219     // var scope.
4220 
4221     Maybe<EmitterScope> namedLambdaEmitterScope;
4222     if (funbox->namedLambdaBindings()) {
4223         namedLambdaEmitterScope.emplace(this);
4224         if (!namedLambdaEmitterScope->enterNamedLambda(this, funbox))
4225             return false;
4226     }
4227 
4228     /*
4229      * Emit a prologue for run-once scripts which will deoptimize JIT code
4230      * if the script ends up running multiple times via foo.caller related
4231      * shenanigans.
4232      *
4233      * Also mark the script so that initializers created within it may be
4234      * given more precise types.
4235      */
4236     if (isRunOnceLambda()) {
4237         script->setTreatAsRunOnce();
4238         MOZ_ASSERT(!script->hasRunOnce());
4239 
4240         switchToPrologue();
4241         if (!emit1(JSOP_RUNONCE))
4242             return false;
4243         switchToMain();
4244     }
4245 
4246     setFunctionBodyEndPos(body->pn_pos);
4247     if (!emitTree(body))
4248         return false;
4249 
4250     if (!updateSourceCoordNotes(body->pn_pos.end))
4251         return false;
4252 
4253     // Always end the script with a JSOP_RETRVAL. Some other parts of the
4254     // codebase depend on this opcode,
4255     // e.g. InterpreterRegs::setToEndOfScript.
4256     if (!emit1(JSOP_RETRVAL))
4257         return false;
4258 
4259     if (namedLambdaEmitterScope) {
4260         if (!namedLambdaEmitterScope->leave(this))
4261             return false;
4262         namedLambdaEmitterScope.reset();
4263     }
4264 
4265     if (!JSScript::fullyInitFromEmitter(cx, script, this))
4266         return false;
4267 
4268     // URL and source map information must be set before firing
4269     // Debugger::onNewScript. Only top-level functions need this, as compiling
4270     // the outer scripts of nested functions already processed the source.
4271     if (emitterMode != LazyFunction && !parent) {
4272         if (!maybeSetDisplayURL() || !maybeSetSourceMap())
4273             return false;
4274 
4275         tellDebuggerAboutCompiledScript(cx);
4276     }
4277 
4278     return true;
4279 }
4280 
4281 template <typename NameEmitter>
4282 bool
emitDestructuringDeclsWithEmitter(ParseNode * pattern,NameEmitter emitName)4283 BytecodeEmitter::emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName)
4284 {
4285     if (pattern->isKind(PNK_ARRAY)) {
4286         for (ParseNode* element = pattern->pn_head; element; element = element->pn_next) {
4287             if (element->isKind(PNK_ELISION))
4288                 continue;
4289             ParseNode* target = element;
4290             if (element->isKind(PNK_SPREAD)) {
4291                 target = element->pn_kid;
4292             }
4293             if (target->isKind(PNK_ASSIGN))
4294                 target = target->pn_left;
4295             if (target->isKind(PNK_NAME)) {
4296                 if (!emitName(this, target))
4297                     return false;
4298             } else {
4299                 if (!emitDestructuringDeclsWithEmitter(target, emitName))
4300                     return false;
4301             }
4302         }
4303         return true;
4304     }
4305 
4306     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
4307     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
4308         MOZ_ASSERT(member->isKind(PNK_MUTATEPROTO) ||
4309                    member->isKind(PNK_COLON) ||
4310                    member->isKind(PNK_SHORTHAND));
4311 
4312         ParseNode* target = member->isKind(PNK_MUTATEPROTO) ? member->pn_kid : member->pn_right;
4313 
4314         if (target->isKind(PNK_ASSIGN))
4315             target = target->pn_left;
4316         if (target->isKind(PNK_NAME)) {
4317             if (!emitName(this, target))
4318                 return false;
4319         } else {
4320             if (!emitDestructuringDeclsWithEmitter(target, emitName))
4321                 return false;
4322         }
4323     }
4324     return true;
4325 }
4326 
4327 bool
emitDestructuringLHS(ParseNode * target,DestructuringFlavor flav)4328 BytecodeEmitter::emitDestructuringLHS(ParseNode* target, DestructuringFlavor flav)
4329 {
4330     // Now emit the lvalue opcode sequence. If the lvalue is a nested
4331     // destructuring initialiser-form, call ourselves to handle it, then pop
4332     // the matched value. Otherwise emit an lvalue bytecode sequence followed
4333     // by an assignment op.
4334     if (target->isKind(PNK_SPREAD))
4335         target = target->pn_kid;
4336     else if (target->isKind(PNK_ASSIGN))
4337         target = target->pn_left;
4338     if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) {
4339         if (!emitDestructuringOps(target, flav))
4340             return false;
4341         // Per its post-condition, emitDestructuringOps has left the
4342         // to-be-destructured value on top of the stack.
4343         if (!emit1(JSOP_POP))
4344             return false;
4345     } else {
4346         switch (target->getKind()) {
4347           case PNK_NAME: {
4348             auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
4349                                           bool emittedBindOp)
4350             {
4351                 if (emittedBindOp) {
4352                     // This is like ordinary assignment, but with one
4353                     // difference.
4354                     //
4355                     // In `a = b`, we first determine a binding for `a` (using
4356                     // JSOP_BINDNAME or JSOP_BINDGNAME), then we evaluate `b`,
4357                     // then a JSOP_SETNAME instruction.
4358                     //
4359                     // In `[a] = [b]`, per spec, `b` is evaluated first, then
4360                     // we determine a binding for `a`. Then we need to do
4361                     // assignment-- but the operands are on the stack in the
4362                     // wrong order for JSOP_SETPROP, so we have to add a
4363                     // JSOP_SWAP.
4364                     //
4365                     // In the cases where we are emitting a name op, emit a
4366                     // swap because of this.
4367                     return bce->emit1(JSOP_SWAP);
4368                 }
4369 
4370                 // In cases of emitting a frame slot or environment slot,
4371                 // nothing needs be done.
4372                 return true;
4373             };
4374 
4375             RootedAtom name(cx, target->name());
4376             switch (flav) {
4377               case DestructuringDeclaration:
4378                 if (!emitInitializeName(name, emitSwapScopeAndRhs))
4379                     return false;
4380                 break;
4381 
4382               case DestructuringFormalParameterInVarScope: {
4383                 // If there's an parameter expression var scope, the
4384                 // destructuring declaration needs to initialize the name in
4385                 // the function scope. The innermost scope is the var scope,
4386                 // and its enclosing scope is the function scope.
4387                 EmitterScope* funScope = innermostEmitterScope->enclosingInFrame();
4388                 NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope);
4389                 if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true))
4390                     return false;
4391                 break;
4392               }
4393 
4394               case DestructuringAssignment:
4395                 if (!emitSetName(name, emitSwapScopeAndRhs))
4396                     return false;
4397                 break;
4398             }
4399 
4400             break;
4401           }
4402 
4403           case PNK_DOT: {
4404             // See the (PNK_NAME, JSOP_SETNAME) case above.
4405             //
4406             // In `a.x = b`, `a` is evaluated first, then `b`, then a
4407             // JSOP_SETPROP instruction.
4408             //
4409             // In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
4410             // need a property set -- but the operands are on the stack in the
4411             // wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
4412             JSOp setOp;
4413             if (target->as<PropertyAccess>().isSuper()) {
4414                 if (!emitSuperPropLHS(&target->as<PropertyAccess>().expression()))
4415                     return false;
4416                 if (!emit2(JSOP_PICK, 2))
4417                     return false;
4418                 setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
4419             } else {
4420                 if (!emitTree(target->pn_expr))
4421                     return false;
4422                 if (!emit1(JSOP_SWAP))
4423                     return false;
4424                 setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
4425             }
4426             if (!emitAtomOp(target, setOp))
4427                 return false;
4428             break;
4429           }
4430 
4431           case PNK_ELEM: {
4432             // See the comment at `case PNK_DOT:` above. This case,
4433             // `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP
4434             // is emitted by emitElemOperands.
4435             if (target->as<PropertyByValue>().isSuper()) {
4436                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER;
4437                 if (!emitSuperElemOp(target, setOp))
4438                     return false;
4439             } else {
4440                 JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
4441                 if (!emitElemOp(target, setOp))
4442                     return false;
4443             }
4444             break;
4445           }
4446 
4447           case PNK_CALL:
4448             MOZ_ASSERT_UNREACHABLE("Parser::reportIfNotValidSimpleAssignmentTarget "
4449                                    "rejects function calls as assignment "
4450                                    "targets in destructuring assignments");
4451             break;
4452 
4453           default:
4454             MOZ_CRASH("emitDestructuringLHS: bad lhs kind");
4455         }
4456 
4457         // Pop the assigned value.
4458         if (!emit1(JSOP_POP))
4459             return false;
4460     }
4461 
4462     return true;
4463 }
4464 
4465 bool
emitConditionallyExecutedDestructuringLHS(ParseNode * target,DestructuringFlavor flav)4466 BytecodeEmitter::emitConditionallyExecutedDestructuringLHS(ParseNode* target, DestructuringFlavor flav)
4467 {
4468     TDZCheckCache tdzCache(this);
4469     return emitDestructuringLHS(target, flav);
4470 }
4471 
4472 bool
emitIteratorNext(ParseNode * pn,bool allowSelfHosted)4473 BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted)
4474 {
4475     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
4476                ".next() iteration is prohibited in self-hosted code because it "
4477                "can run user-modifiable iteration code");
4478 
4479     if (!emit1(JSOP_DUP))                                 // ... ITER ITER
4480         return false;
4481     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))     // ... ITER NEXT
4482         return false;
4483     if (!emit1(JSOP_SWAP))                                // ... NEXT ITER
4484         return false;
4485     if (!emitCall(JSOP_CALL, 0, pn))                      // ... RESULT
4486         return false;
4487     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
4488         return false;
4489     checkTypeSet(JSOP_CALL);
4490     return true;
4491 }
4492 
4493 bool
emitDefault(ParseNode * defaultExpr)4494 BytecodeEmitter::emitDefault(ParseNode* defaultExpr)
4495 {
4496     if (!emit1(JSOP_DUP))                                 // VALUE VALUE
4497         return false;
4498     if (!emit1(JSOP_UNDEFINED))                           // VALUE VALUE UNDEFINED
4499         return false;
4500     if (!emit1(JSOP_STRICTEQ))                            // VALUE EQL?
4501         return false;
4502     // Emit source note to enable ion compilation.
4503     if (!newSrcNote(SRC_IF))
4504         return false;
4505     JumpList jump;
4506     if (!emitJump(JSOP_IFEQ, &jump))                      // VALUE
4507         return false;
4508     if (!emit1(JSOP_POP))                                 // .
4509         return false;
4510     if (!emitConditionallyExecutedTree(defaultExpr))      // DEFAULTVALUE
4511         return false;
4512     if (!emitJumpTargetAndPatch(jump))
4513         return false;
4514     return true;
4515 }
4516 
4517 class MOZ_STACK_CLASS IfThenElseEmitter
4518 {
4519     BytecodeEmitter* bce_;
4520     JumpList jumpAroundThen_;
4521     JumpList jumpsAroundElse_;
4522     unsigned noteIndex_;
4523     int32_t thenDepth_;
4524 #ifdef DEBUG
4525     int32_t pushed_;
4526     bool calculatedPushed_;
4527 #endif
4528     enum State {
4529         Start,
4530         If,
4531         Cond,
4532         IfElse,
4533         Else,
4534         End
4535     };
4536     State state_;
4537 
4538   public:
IfThenElseEmitter(BytecodeEmitter * bce)4539     explicit IfThenElseEmitter(BytecodeEmitter* bce)
4540       : bce_(bce),
4541         noteIndex_(-1),
4542         thenDepth_(0),
4543 #ifdef DEBUG
4544         pushed_(0),
4545         calculatedPushed_(false),
4546 #endif
4547         state_(Start)
4548     {}
4549 
~IfThenElseEmitter()4550     ~IfThenElseEmitter()
4551     {}
4552 
4553   private:
emitIf(State nextState)4554     bool emitIf(State nextState) {
4555         MOZ_ASSERT(state_ == Start || state_ == Else);
4556         MOZ_ASSERT(nextState == If || nextState == IfElse || nextState == Cond);
4557 
4558         // Clear jumpAroundThen_ offset that points previous JSOP_IFEQ.
4559         if (state_ == Else)
4560             jumpAroundThen_ = JumpList();
4561 
4562         // Emit an annotated branch-if-false around the then part.
4563         SrcNoteType type = nextState == If ? SRC_IF : nextState == IfElse ? SRC_IF_ELSE : SRC_COND;
4564         if (!bce_->newSrcNote(type, &noteIndex_))
4565             return false;
4566         if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_))
4567             return false;
4568 
4569         // To restore stack depth in else part, save depth of the then part.
4570 #ifdef DEBUG
4571         // If DEBUG, this is also necessary to calculate |pushed_|.
4572         thenDepth_ = bce_->stackDepth;
4573 #else
4574         if (nextState == IfElse || nextState == Cond)
4575             thenDepth_ = bce_->stackDepth;
4576 #endif
4577         state_ = nextState;
4578         return true;
4579     }
4580 
4581   public:
emitIf()4582     bool emitIf() {
4583         return emitIf(If);
4584     }
4585 
emitCond()4586     bool emitCond() {
4587         return emitIf(Cond);
4588     }
4589 
emitIfElse()4590     bool emitIfElse() {
4591         return emitIf(IfElse);
4592     }
4593 
emitElse()4594     bool emitElse() {
4595         MOZ_ASSERT(state_ == IfElse || state_ == Cond);
4596 
4597         calculateOrCheckPushed();
4598 
4599         // Emit a jump from the end of our then part around the else part. The
4600         // patchJumpsToTarget call at the bottom of this function will fix up
4601         // the offset with jumpsAroundElse value.
4602         if (!bce_->emitJump(JSOP_GOTO, &jumpsAroundElse_))
4603             return false;
4604 
4605         // Ensure the branch-if-false comes here, then emit the else.
4606         if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
4607             return false;
4608 
4609         // Annotate SRC_IF_ELSE or SRC_COND with the offset from branch to
4610         // jump, for IonMonkey's benefit.  We can't just "back up" from the pc
4611         // of the else clause, because we don't know whether an extended
4612         // jump was required to leap from the end of the then clause over
4613         // the else clause.
4614         if (!bce_->setSrcNoteOffset(noteIndex_, 0,
4615                                     jumpsAroundElse_.offset - jumpAroundThen_.offset))
4616         {
4617             return false;
4618         }
4619 
4620         // Restore stack depth of the then part.
4621         bce_->stackDepth = thenDepth_;
4622         state_ = Else;
4623         return true;
4624     }
4625 
emitEnd()4626     bool emitEnd() {
4627         MOZ_ASSERT(state_ == If || state_ == Else);
4628 
4629         calculateOrCheckPushed();
4630 
4631         if (state_ == If) {
4632             // No else part, fixup the branch-if-false to come here.
4633             if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
4634                 return false;
4635         }
4636 
4637         // Patch all the jumps around else parts.
4638         if (!bce_->emitJumpTargetAndPatch(jumpsAroundElse_))
4639             return false;
4640 
4641         state_ = End;
4642         return true;
4643     }
4644 
calculateOrCheckPushed()4645     void calculateOrCheckPushed() {
4646 #ifdef DEBUG
4647         if (!calculatedPushed_) {
4648             pushed_ = bce_->stackDepth - thenDepth_;
4649             calculatedPushed_ = true;
4650         } else {
4651             MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
4652         }
4653 #endif
4654     }
4655 
4656 #ifdef DEBUG
pushed() const4657     int32_t pushed() const {
4658         return pushed_;
4659     }
4660 
popped() const4661     int32_t popped() const {
4662         return -pushed_;
4663     }
4664 #endif
4665 };
4666 
4667 bool
emitDestructuringOpsArray(ParseNode * pattern,DestructuringFlavor flav)4668 BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav)
4669 {
4670     MOZ_ASSERT(pattern->isKind(PNK_ARRAY));
4671     MOZ_ASSERT(pattern->isArity(PN_LIST));
4672     MOZ_ASSERT(this->stackDepth != 0);
4673 
4674     // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
4675     //
4676     //   let x, y;
4677     //   let a, b, c, d;
4678     //   let tmp, done, iter, result; // stack values
4679     //
4680     //   iter = x[Symbol.iterator]();
4681     //
4682     //   // ==== emitted by loop for a ====
4683     //   result = iter.next();
4684     //   done = result.done;
4685     //
4686     //   if (done) {
4687     //     a = undefined;
4688     //
4689     //     result = undefined;
4690     //     done = true;
4691     //   } else {
4692     //     a = result.value;
4693     //
4694     //     // Do next element's .next() and .done access here
4695     //     result = iter.next();
4696     //     done = result.done;
4697     //   }
4698     //
4699     //   // ==== emitted by loop for b ====
4700     //   if (done) {
4701     //     b = undefined;
4702     //
4703     //     result = undefined;
4704     //     done = true;
4705     //   } else {
4706     //     b = result.value;
4707     //
4708     //     result = iter.next();
4709     //     done = result.done;
4710     //   }
4711     //
4712     //   // ==== emitted by loop for elision ====
4713     //   if (done) {
4714     //     result = undefined
4715     //     done = true
4716     //   } else {
4717     //     result.value;
4718     //
4719     //     result = iter.next();
4720     //     done = result.done;
4721     //   }
4722     //
4723     //   // ==== emitted by loop for c ====
4724     //   if (done) {
4725     //     c = y;
4726     //   } else {
4727     //     tmp = result.value;
4728     //     if (tmp === undefined)
4729     //       tmp = y;
4730     //     c = tmp;
4731     //
4732     //     // Don't do next element's .next() and .done access if
4733     //     // this is the last non-spread element.
4734     //   }
4735     //
4736     //   // ==== emitted by loop for d ====
4737     //   if (done) {
4738     //     // Assing empty array when completed
4739     //     d = [];
4740     //   } else {
4741     //     d = [...iter];
4742     //   }
4743 
4744     /*
4745      * Use an iterator to destructure the RHS, instead of index lookup. We
4746      * must leave the *original* value on the stack.
4747      */
4748     if (!emit1(JSOP_DUP))                                         // ... OBJ OBJ
4749         return false;
4750     if (!emitIterator())                                          // ... OBJ? ITER
4751         return false;
4752     bool needToPopIterator = true;
4753 
4754     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
4755         bool isHead = member == pattern->pn_head;
4756         if (member->isKind(PNK_SPREAD)) {
4757             IfThenElseEmitter ifThenElse(this);
4758             if (!isHead) {
4759                 // If spread is not the first element of the pattern,
4760                 // iterator can already be completed.
4761                 if (!ifThenElse.emitIfElse())                     // ... OBJ? ITER
4762                     return false;
4763 
4764                 if (!emit1(JSOP_POP))                             // ... OBJ?
4765                     return false;
4766                 if (!emitUint32Operand(JSOP_NEWARRAY, 0))         // ... OBJ? ARRAY
4767                     return false;
4768                 if (!emitConditionallyExecutedDestructuringLHS(member, flav)) // ... OBJ?
4769                     return false;
4770 
4771                 if (!ifThenElse.emitElse())                       // ... OBJ? ITER
4772                     return false;
4773             }
4774 
4775             // If iterator is not completed, create a new array with the rest
4776             // of the iterator.
4777             if (!emitUint32Operand(JSOP_NEWARRAY, 0))             // ... OBJ? ITER ARRAY
4778                 return false;
4779             if (!emitNumberOp(0))                                 // ... OBJ? ITER ARRAY INDEX
4780                 return false;
4781             if (!emitSpread())                                    // ... OBJ? ARRAY INDEX
4782                 return false;
4783             if (!emit1(JSOP_POP))                                 // ... OBJ? ARRAY
4784                 return false;
4785             if (!emitConditionallyExecutedDestructuringLHS(member, flav)) // ... OBJ?
4786                 return false;
4787 
4788             if (!isHead) {
4789                 if (!ifThenElse.emitEnd())
4790                     return false;
4791                 MOZ_ASSERT(ifThenElse.popped() == 1);
4792             }
4793             needToPopIterator = false;
4794             MOZ_ASSERT(!member->pn_next);
4795             break;
4796         }
4797 
4798         ParseNode* pndefault = nullptr;
4799         ParseNode* subpattern = member;
4800         if (subpattern->isKind(PNK_ASSIGN)) {
4801             pndefault = subpattern->pn_right;
4802             subpattern = subpattern->pn_left;
4803         }
4804 
4805         bool isElision = subpattern->isKind(PNK_ELISION);
4806         bool hasNextNonSpread = member->pn_next && !member->pn_next->isKind(PNK_SPREAD);
4807         bool hasNextSpread = member->pn_next && member->pn_next->isKind(PNK_SPREAD);
4808 
4809         MOZ_ASSERT(!subpattern->isKind(PNK_SPREAD));
4810 
4811         auto emitNext = [pattern](ExclusiveContext* cx, BytecodeEmitter* bce) {
4812             if (!bce->emit1(JSOP_DUP))                            // ... OBJ? ITER ITER
4813                 return false;
4814             if (!bce->emitIteratorNext(pattern))                  // ... OBJ? ITER RESULT
4815                 return false;
4816             if (!bce->emit1(JSOP_DUP))                            // ... OBJ? ITER RESULT RESULT
4817                 return false;
4818             if (!bce->emitAtomOp(cx->names().done, JSOP_GETPROP)) // ... OBJ? ITER RESULT DONE?
4819                 return false;
4820             return true;
4821         };
4822 
4823         if (isHead) {
4824             if (!emitNext(cx, this))                              // ... OBJ? ITER RESULT DONE?
4825                 return false;
4826         }
4827 
4828         IfThenElseEmitter ifThenElse(this);
4829         if (!ifThenElse.emitIfElse())                             // ... OBJ? ITER RESULT
4830             return false;
4831 
4832         if (!emit1(JSOP_POP))                                     // ... OBJ? ITER
4833             return false;
4834         if (pndefault) {
4835             // Emit only pndefault tree here, as undefined check in emitDefault
4836             // should always be true.
4837             if (!emitConditionallyExecutedTree(pndefault))        // ... OBJ? ITER VALUE
4838                 return false;
4839         } else {
4840             if (!isElision) {
4841                 if (!emit1(JSOP_UNDEFINED))                       // ... OBJ? ITER UNDEFINED
4842                     return false;
4843                 if (!emit1(JSOP_NOP_DESTRUCTURING))
4844                     return false;
4845             }
4846         }
4847         if (!isElision) {
4848             if (!emitConditionallyExecutedDestructuringLHS(subpattern, flav)) // ... OBJ? ITER
4849                 return false;
4850         } else if (pndefault) {
4851             if (!emit1(JSOP_POP))                                 // ... OBJ? ITER
4852                 return false;
4853         }
4854 
4855         // Setup next element's result when the iterator is done.
4856         if (hasNextNonSpread) {
4857             if (!emit1(JSOP_UNDEFINED))                           // ... OBJ? ITER RESULT
4858                 return false;
4859             if (!emit1(JSOP_NOP_DESTRUCTURING))
4860                 return false;
4861             if (!emit1(JSOP_TRUE))                                // ... OBJ? ITER RESULT DONE?
4862                 return false;
4863         } else if (hasNextSpread) {
4864             if (!emit1(JSOP_TRUE))                                // ... OBJ? ITER DONE?
4865                 return false;
4866         }
4867 
4868         if (!ifThenElse.emitElse())                               // ... OBJ? ITER RESULT
4869             return false;
4870 
4871         if (!emitAtomOp(cx->names().value, JSOP_GETPROP))         // ... OBJ? ITER VALUE
4872             return false;
4873 
4874         if (pndefault) {
4875             if (!emitDefault(pndefault))                          // ... OBJ? ITER VALUE
4876                 return false;
4877         }
4878 
4879         if (!isElision) {
4880             if (!emitConditionallyExecutedDestructuringLHS(subpattern, flav)) // ... OBJ? ITER
4881                 return false;
4882         } else {
4883             if (!emit1(JSOP_POP))                                 // ... OBJ? ITER
4884                 return false;
4885         }
4886 
4887         // Setup next element's result when the iterator is not done.
4888         if (hasNextNonSpread) {
4889             if (!emitNext(cx, this))                              // ... OBJ? ITER RESULT DONE?
4890                 return false;
4891         } else if (hasNextSpread) {
4892             if (!emit1(JSOP_FALSE))                               // ... OBJ? ITER DONE?
4893                 return false;
4894         }
4895 
4896         if (!ifThenElse.emitEnd())
4897             return false;
4898         if (hasNextNonSpread)
4899             MOZ_ASSERT(ifThenElse.pushed() == 1);
4900         else if (hasNextSpread)
4901             MOZ_ASSERT(ifThenElse.pushed() == 0);
4902         else
4903             MOZ_ASSERT(ifThenElse.popped() == 1);
4904     }
4905 
4906     if (needToPopIterator) {
4907         if (!emit1(JSOP_POP))                                     // ... OBJ?
4908             return false;
4909     }
4910 
4911     return true;
4912 }
4913 
4914 bool
emitComputedPropertyName(ParseNode * computedPropName)4915 BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName)
4916 {
4917     MOZ_ASSERT(computedPropName->isKind(PNK_COMPUTED_NAME));
4918     return emitTree(computedPropName->pn_kid) && emit1(JSOP_TOID);
4919 }
4920 
4921 bool
emitDestructuringOpsObject(ParseNode * pattern,DestructuringFlavor flav)4922 BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
4923 {
4924     MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
4925     MOZ_ASSERT(pattern->isArity(PN_LIST));
4926 
4927     MOZ_ASSERT(this->stackDepth > 0);                             // ... RHS
4928 
4929     if (!emitRequireObjectCoercible())                            // ... RHS
4930         return false;
4931 
4932     for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
4933         // Duplicate the value being destructured to use as a reference base.
4934         if (!emit1(JSOP_DUP))                                     // ... RHS RHS
4935             return false;
4936 
4937         // Now push the property name currently being matched, which is the
4938         // current property name "label" on the left of a colon in the object
4939         // initialiser.
4940         bool needsGetElem = true;
4941 
4942         ParseNode* subpattern;
4943         if (member->isKind(PNK_MUTATEPROTO)) {
4944             if (!emitAtomOp(cx->names().proto, JSOP_GETPROP))     // ... RHS PROP
4945                 return false;
4946             needsGetElem = false;
4947             subpattern = member->pn_kid;
4948         } else {
4949             MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
4950 
4951             ParseNode* key = member->pn_left;
4952             if (key->isKind(PNK_NUMBER)) {
4953                 if (!emitNumberOp(key->pn_dval))                  // ... RHS RHS KEY
4954                     return false;
4955             } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
4956                 PropertyName* name = key->pn_atom->asPropertyName();
4957 
4958                 // The parser already checked for atoms representing indexes and
4959                 // used PNK_NUMBER instead, but also watch for ids which TI treats
4960                 // as indexes for simplification of downstream analysis.
4961                 jsid id = NameToId(name);
4962                 if (id != IdToTypeId(id)) {
4963                     if (!emitTree(key))                           // ... RHS RHS KEY
4964                         return false;
4965                 } else {
4966                     if (!emitAtomOp(name, JSOP_GETPROP))          // ...RHS PROP
4967                         return false;
4968                     needsGetElem = false;
4969                 }
4970             } else {
4971                 if (!emitComputedPropertyName(key))               // ... RHS RHS KEY
4972                     return false;
4973             }
4974 
4975             subpattern = member->pn_right;
4976         }
4977 
4978         // Get the property value if not done already.
4979         if (needsGetElem && !emitElemOpBase(JSOP_GETELEM))        // ... RHS PROP
4980             return false;
4981 
4982         if (subpattern->isKind(PNK_ASSIGN)) {
4983             if (!emitDefault(subpattern->pn_right))
4984                 return false;
4985             subpattern = subpattern->pn_left;
4986         }
4987 
4988         // Destructure PROP per this member's subpattern.
4989         if (!emitDestructuringLHS(subpattern, flav))
4990             return false;
4991     }
4992 
4993     return true;
4994 }
4995 
4996 bool
emitDestructuringOps(ParseNode * pattern,DestructuringFlavor flav)4997 BytecodeEmitter::emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav)
4998 {
4999     if (pattern->isKind(PNK_ARRAY))
5000         return emitDestructuringOpsArray(pattern, flav);
5001     return emitDestructuringOpsObject(pattern, flav);
5002 }
5003 
5004 bool
emitTemplateString(ParseNode * pn)5005 BytecodeEmitter::emitTemplateString(ParseNode* pn)
5006 {
5007     MOZ_ASSERT(pn->isArity(PN_LIST));
5008 
5009     bool pushedString = false;
5010 
5011     for (ParseNode* pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
5012         bool isString = (pn2->getKind() == PNK_STRING || pn2->getKind() == PNK_TEMPLATE_STRING);
5013 
5014         // Skip empty strings. These are very common: a template string like
5015         // `${a}${b}` has three empty strings and without this optimization
5016         // we'd emit four JSOP_ADD operations instead of just one.
5017         if (isString && pn2->pn_atom->empty())
5018             continue;
5019 
5020         if (!isString) {
5021             // We update source notes before emitting the expression
5022             if (!updateSourceCoordNotes(pn2->pn_pos.begin))
5023                 return false;
5024         }
5025 
5026         if (!emitTree(pn2))
5027             return false;
5028 
5029         if (!isString) {
5030             // We need to convert the expression to a string
5031             if (!emit1(JSOP_TOSTRING))
5032                 return false;
5033         }
5034 
5035         if (pushedString) {
5036             // We've pushed two strings onto the stack. Add them together, leaving just one.
5037             if (!emit1(JSOP_ADD))
5038                 return false;
5039         } else {
5040             pushedString = true;
5041         }
5042     }
5043 
5044     if (!pushedString) {
5045         // All strings were empty, this can happen for something like `${""}`.
5046         // Just push an empty string.
5047         if (!emitAtomOp(cx->names().empty, JSOP_STRING))
5048             return false;
5049     }
5050 
5051     return true;
5052 }
5053 
5054 bool
emitDeclarationList(ParseNode * declList)5055 BytecodeEmitter::emitDeclarationList(ParseNode* declList)
5056 {
5057     MOZ_ASSERT(declList->isArity(PN_LIST));
5058 
5059     ParseNode* next;
5060     for (ParseNode* decl = declList->pn_head; decl; decl = next) {
5061         if (!updateSourceCoordNotes(decl->pn_pos.begin))
5062             return false;
5063         next = decl->pn_next;
5064 
5065         if (decl->isKind(PNK_ASSIGN)) {
5066             MOZ_ASSERT(decl->isOp(JSOP_NOP));
5067 
5068             ParseNode* pattern = decl->pn_left;
5069             MOZ_ASSERT(pattern->isKind(PNK_ARRAY) || pattern->isKind(PNK_OBJECT));
5070 
5071             if (!emitTree(decl->pn_right))
5072                 return false;
5073 
5074             if (!emitDestructuringOps(pattern, DestructuringDeclaration))
5075                 return false;
5076 
5077             if (!emit1(JSOP_POP))
5078                 return false;
5079         } else {
5080             if (!emitSingleDeclaration(declList, decl, decl->expr()))
5081                 return false;
5082         }
5083     }
5084     return true;
5085 }
5086 
5087 bool
emitSingleDeclaration(ParseNode * declList,ParseNode * decl,ParseNode * initializer)5088 BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
5089                                        ParseNode* initializer)
5090 {
5091     MOZ_ASSERT(decl->isKind(PNK_NAME));
5092 
5093     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
5094     if (!initializer && declList->isKind(PNK_VAR))
5095         return true;
5096 
5097     auto emitRhs = [initializer, declList](BytecodeEmitter* bce, const NameLocation&, bool) {
5098         if (!initializer) {
5099             // Lexical declarations are initialized to undefined without an
5100             // initializer.
5101             MOZ_ASSERT(declList->isKind(PNK_LET),
5102                        "var declarations without initializers handled above, "
5103                        "and const declarations must have initializers");
5104             return bce->emit1(JSOP_UNDEFINED);
5105         }
5106 
5107         MOZ_ASSERT(initializer);
5108         return bce->emitTree(initializer);
5109     };
5110 
5111     if (!emitInitializeName(decl, emitRhs))
5112         return false;
5113 
5114     // Pop the RHS.
5115     return emit1(JSOP_POP);
5116 }
5117 
5118 static bool
EmitAssignmentRhs(BytecodeEmitter * bce,ParseNode * rhs,uint8_t offset)5119 EmitAssignmentRhs(BytecodeEmitter* bce, ParseNode* rhs, uint8_t offset)
5120 {
5121     // If there is a RHS tree, emit the tree.
5122     if (rhs)
5123         return bce->emitTree(rhs);
5124 
5125     // Otherwise the RHS value to assign is already on the stack, i.e., the
5126     // next enumeration value in a for-in or for-of loop. Depending on how
5127     // many other values have been pushed on the stack, we need to get the
5128     // already-pushed RHS value.
5129     if (offset != 1 && !bce->emit2(JSOP_PICK, offset - 1))
5130         return false;
5131 
5132     return true;
5133 }
5134 
5135 bool
emitAssignment(ParseNode * lhs,JSOp op,ParseNode * rhs)5136 BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
5137 {
5138     // Name assignments are handled separately because choosing ops and when
5139     // to emit BINDNAME is involved and should avoid duplication.
5140     if (lhs->isKind(PNK_NAME)) {
5141         auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc,
5142                                       bool emittedBindOp)
5143         {
5144             // For compound assignments, first get the LHS value, then emit
5145             // the RHS and the op.
5146             if (op != JSOP_NOP) {
5147                 if (lhsLoc.kind() == NameLocation::Kind::Dynamic) {
5148                     // For dynamic accesses we can do better than a GETNAME
5149                     // since the assignment already emitted a BINDNAME on the
5150                     // top of the stack. As an optimization, use that to get
5151                     // the name.
5152                     if (!bce->emit1(JSOP_DUP))
5153                         return false;
5154                     if (!bce->emitAtomOp(lhs, JSOP_GETXPROP))
5155                         return false;
5156                 } else {
5157                     if (!bce->emitGetNameAtLocation(lhs->name(), lhsLoc))
5158                         return false;
5159                 }
5160             }
5161 
5162             // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on
5163             // the top of the stack and we need to pick the right RHS value.
5164             if (!EmitAssignmentRhs(bce, rhs, emittedBindOp ? 2 : 1))
5165                 return false;
5166 
5167             // Emit the compound assignment op if there is one.
5168             if (op != JSOP_NOP && !bce->emit1(op))
5169                 return false;
5170 
5171             return true;
5172         };
5173 
5174         return emitSetName(lhs, emitRhs);
5175     }
5176 
5177     // Deal with non-name assignments.
5178     uint32_t atomIndex = (uint32_t) -1;
5179     uint8_t offset = 1;
5180 
5181     switch (lhs->getKind()) {
5182       case PNK_DOT:
5183         if (lhs->as<PropertyAccess>().isSuper()) {
5184             if (!emitSuperPropLHS(&lhs->as<PropertyAccess>().expression()))
5185                 return false;
5186             offset += 2;
5187         } else {
5188             if (!emitTree(lhs->expr()))
5189                 return false;
5190             offset += 1;
5191         }
5192         if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
5193             return false;
5194         break;
5195       case PNK_ELEM: {
5196         MOZ_ASSERT(lhs->isArity(PN_BINARY));
5197         EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign;
5198         if (lhs->as<PropertyByValue>().isSuper()) {
5199             if (!emitSuperElemOperands(lhs, opt))
5200                 return false;
5201             offset += 3;
5202         } else {
5203             if (!emitElemOperands(lhs, opt))
5204                 return false;
5205             offset += 2;
5206         }
5207         break;
5208       }
5209       case PNK_ARRAY:
5210       case PNK_OBJECT:
5211         break;
5212       case PNK_CALL:
5213         if (!emitTree(lhs))
5214             return false;
5215 
5216         // Assignment to function calls is forbidden, but we have to make the
5217         // call first.  Now we can throw.
5218         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS))
5219             return false;
5220 
5221         // Rebalance the stack to placate stack-depth assertions.
5222         if (!emit1(JSOP_POP))
5223             return false;
5224         break;
5225       default:
5226         MOZ_ASSERT(0);
5227     }
5228 
5229     if (op != JSOP_NOP) {
5230         MOZ_ASSERT(rhs);
5231         switch (lhs->getKind()) {
5232           case PNK_DOT: {
5233             JSOp getOp;
5234             if (lhs->as<PropertyAccess>().isSuper()) {
5235                 if (!emit1(JSOP_DUP2))
5236                     return false;
5237                 getOp = JSOP_GETPROP_SUPER;
5238             } else {
5239                 if (!emit1(JSOP_DUP))
5240                     return false;
5241                 bool isLength = (lhs->pn_atom == cx->names().length);
5242                 getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
5243             }
5244             if (!emitIndex32(getOp, atomIndex))
5245                 return false;
5246             break;
5247           }
5248           case PNK_ELEM: {
5249             JSOp elemOp;
5250             if (lhs->as<PropertyByValue>().isSuper()) {
5251                 if (!emitDupAt(2))
5252                     return false;
5253                 if (!emitDupAt(2))
5254                     return false;
5255                 if (!emitDupAt(2))
5256                     return false;
5257                 elemOp = JSOP_GETELEM_SUPER;
5258             } else {
5259                 if (!emit1(JSOP_DUP2))
5260                     return false;
5261                 elemOp = JSOP_GETELEM;
5262             }
5263             if (!emitElemOpBase(elemOp))
5264                 return false;
5265             break;
5266           }
5267           case PNK_CALL:
5268             // We just emitted a JSOP_THROWMSG and popped the call's return
5269             // value.  Push a random value to make sure the stack depth is
5270             // correct.
5271             if (!emit1(JSOP_NULL))
5272                 return false;
5273             break;
5274           default:;
5275         }
5276     }
5277 
5278     if (!EmitAssignmentRhs(this, rhs, offset))
5279         return false;
5280 
5281     /* If += etc., emit the binary operator with a source note. */
5282     if (op != JSOP_NOP) {
5283         if (!newSrcNote(SRC_ASSIGNOP))
5284             return false;
5285         if (!emit1(op))
5286             return false;
5287     }
5288 
5289     /* Finally, emit the specialized assignment bytecode. */
5290     switch (lhs->getKind()) {
5291       case PNK_DOT: {
5292         JSOp setOp = lhs->as<PropertyAccess>().isSuper() ?
5293                        (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) :
5294                        (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP);
5295         if (!emitIndexOp(setOp, atomIndex))
5296             return false;
5297         break;
5298       }
5299       case PNK_CALL:
5300         // We threw above, so nothing to do here.
5301         break;
5302       case PNK_ELEM: {
5303         JSOp setOp = lhs->as<PropertyByValue>().isSuper() ?
5304                        sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER :
5305                        sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
5306         if (!emit1(setOp))
5307             return false;
5308         break;
5309       }
5310       case PNK_ARRAY:
5311       case PNK_OBJECT:
5312         if (!emitDestructuringOps(lhs, DestructuringAssignment))
5313             return false;
5314         break;
5315       default:
5316         MOZ_ASSERT(0);
5317     }
5318     return true;
5319 }
5320 
5321 bool
getConstantValue(ExclusiveContext * cx,AllowConstantObjects allowObjects,MutableHandleValue vp,Value * compare,size_t ncompare,NewObjectKind newKind)5322 ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObjects,
5323                             MutableHandleValue vp, Value* compare, size_t ncompare,
5324                             NewObjectKind newKind)
5325 {
5326     MOZ_ASSERT(newKind == TenuredObject || newKind == SingletonObject);
5327 
5328     switch (getKind()) {
5329       case PNK_NUMBER:
5330         vp.setNumber(pn_dval);
5331         return true;
5332       case PNK_TEMPLATE_STRING:
5333       case PNK_STRING:
5334         vp.setString(pn_atom);
5335         return true;
5336       case PNK_TRUE:
5337         vp.setBoolean(true);
5338         return true;
5339       case PNK_FALSE:
5340         vp.setBoolean(false);
5341         return true;
5342       case PNK_NULL:
5343         vp.setNull();
5344         return true;
5345       case PNK_CALLSITEOBJ:
5346       case PNK_ARRAY: {
5347         unsigned count;
5348         ParseNode* pn;
5349 
5350         if (allowObjects == DontAllowObjects) {
5351             vp.setMagic(JS_GENERIC_MAGIC);
5352             return true;
5353         }
5354 
5355         ObjectGroup::NewArrayKind arrayKind = ObjectGroup::NewArrayKind::Normal;
5356         if (allowObjects == ForCopyOnWriteArray) {
5357             arrayKind = ObjectGroup::NewArrayKind::CopyOnWrite;
5358             allowObjects = DontAllowObjects;
5359         }
5360 
5361         if (getKind() == PNK_CALLSITEOBJ) {
5362             count = pn_count - 1;
5363             pn = pn_head->pn_next;
5364         } else {
5365             MOZ_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
5366             count = pn_count;
5367             pn = pn_head;
5368         }
5369 
5370         AutoValueVector values(cx);
5371         if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), count))
5372             return false;
5373         size_t idx;
5374         for (idx = 0; pn; idx++, pn = pn->pn_next) {
5375             if (!pn->getConstantValue(cx, allowObjects, values[idx], values.begin(), idx))
5376                 return false;
5377             if (values[idx].isMagic(JS_GENERIC_MAGIC)) {
5378                 vp.setMagic(JS_GENERIC_MAGIC);
5379                 return true;
5380             }
5381         }
5382         MOZ_ASSERT(idx == count);
5383 
5384         JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
5385                                                     newKind, arrayKind);
5386         if (!obj)
5387             return false;
5388 
5389         if (!CombineArrayElementTypes(cx, obj, compare, ncompare))
5390             return false;
5391 
5392         vp.setObject(*obj);
5393         return true;
5394       }
5395       case PNK_OBJECT: {
5396         MOZ_ASSERT(isOp(JSOP_NEWINIT));
5397         MOZ_ASSERT(!(pn_xflags & PNX_NONCONST));
5398 
5399         if (allowObjects == DontAllowObjects) {
5400             vp.setMagic(JS_GENERIC_MAGIC);
5401             return true;
5402         }
5403         MOZ_ASSERT(allowObjects == AllowObjects);
5404 
5405         Rooted<IdValueVector> properties(cx, IdValueVector(cx));
5406 
5407         RootedValue value(cx), idvalue(cx);
5408         for (ParseNode* pn = pn_head; pn; pn = pn->pn_next) {
5409             if (!pn->pn_right->getConstantValue(cx, allowObjects, &value))
5410                 return false;
5411             if (value.isMagic(JS_GENERIC_MAGIC)) {
5412                 vp.setMagic(JS_GENERIC_MAGIC);
5413                 return true;
5414             }
5415 
5416             ParseNode* pnid = pn->pn_left;
5417             if (pnid->isKind(PNK_NUMBER)) {
5418                 idvalue = NumberValue(pnid->pn_dval);
5419             } else {
5420                 MOZ_ASSERT(pnid->isKind(PNK_OBJECT_PROPERTY_NAME) || pnid->isKind(PNK_STRING));
5421                 MOZ_ASSERT(pnid->pn_atom != cx->names().proto);
5422                 idvalue = StringValue(pnid->pn_atom);
5423             }
5424 
5425             RootedId id(cx);
5426             if (!ValueToId<CanGC>(cx, idvalue, &id))
5427                 return false;
5428 
5429             if (!properties.append(IdValuePair(id, value)))
5430                 return false;
5431         }
5432 
5433         JSObject* obj = ObjectGroup::newPlainObject(cx, properties.begin(), properties.length(),
5434                                                     newKind);
5435         if (!obj)
5436             return false;
5437 
5438         if (!CombinePlainObjectPropertyTypes(cx, obj, compare, ncompare))
5439             return false;
5440 
5441         vp.setObject(*obj);
5442         return true;
5443       }
5444       default:
5445         MOZ_CRASH("Unexpected node");
5446     }
5447     return false;
5448 }
5449 
5450 bool
emitSingletonInitialiser(ParseNode * pn)5451 BytecodeEmitter::emitSingletonInitialiser(ParseNode* pn)
5452 {
5453     NewObjectKind newKind = (pn->getKind() == PNK_OBJECT) ? SingletonObject : TenuredObject;
5454 
5455     RootedValue value(cx);
5456     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value, nullptr, 0, newKind))
5457         return false;
5458 
5459     MOZ_ASSERT_IF(newKind == SingletonObject, value.toObject().isSingleton());
5460 
5461     ObjectBox* objbox = parser->newObjectBox(&value.toObject());
5462     if (!objbox)
5463         return false;
5464 
5465     return emitObjectOp(objbox, JSOP_OBJECT);
5466 }
5467 
5468 bool
emitCallSiteObject(ParseNode * pn)5469 BytecodeEmitter::emitCallSiteObject(ParseNode* pn)
5470 {
5471     RootedValue value(cx);
5472     if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value))
5473         return false;
5474 
5475     MOZ_ASSERT(value.isObject());
5476 
5477     ObjectBox* objbox1 = parser->newObjectBox(&value.toObject());
5478     if (!objbox1)
5479         return false;
5480 
5481     if (!pn->as<CallSiteNode>().getRawArrayValue(cx, &value))
5482         return false;
5483 
5484     MOZ_ASSERT(value.isObject());
5485 
5486     ObjectBox* objbox2 = parser->newObjectBox(&value.toObject());
5487     if (!objbox2)
5488         return false;
5489 
5490     return emitObjectPairOp(objbox1, objbox2, JSOP_CALLSITEOBJ);
5491 }
5492 
5493 /* See the SRC_FOR source note offsetBias comments later in this file. */
5494 JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
5495 JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
5496 
5497 namespace {
5498 
5499 class EmitLevelManager
5500 {
5501     BytecodeEmitter* bce;
5502   public:
EmitLevelManager(BytecodeEmitter * bce)5503     explicit EmitLevelManager(BytecodeEmitter* bce) : bce(bce) { bce->emitLevel++; }
~EmitLevelManager()5504     ~EmitLevelManager() { bce->emitLevel--; }
5505 };
5506 
5507 } /* anonymous namespace */
5508 
5509 bool
emitCatch(ParseNode * pn)5510 BytecodeEmitter::emitCatch(ParseNode* pn)
5511 {
5512     // We must be nested under a try-finally statement.
5513     TryFinallyControl& controlInfo = innermostNestableControl->as<TryFinallyControl>();
5514 
5515     /* Pick up the pending exception and bind it to the catch variable. */
5516     if (!emit1(JSOP_EXCEPTION))
5517         return false;
5518 
5519     /*
5520      * Dup the exception object if there is a guard for rethrowing to use
5521      * it later when rethrowing or in other catches.
5522      */
5523     if (pn->pn_kid2 && !emit1(JSOP_DUP))
5524         return false;
5525 
5526     ParseNode* pn2 = pn->pn_kid1;
5527     switch (pn2->getKind()) {
5528       case PNK_ARRAY:
5529       case PNK_OBJECT:
5530         if (!emitDestructuringOps(pn2, DestructuringDeclaration))
5531             return false;
5532         if (!emit1(JSOP_POP))
5533             return false;
5534         break;
5535 
5536       case PNK_NAME:
5537         if (!emitLexicalInitialization(pn2))
5538             return false;
5539         if (!emit1(JSOP_POP))
5540             return false;
5541         break;
5542 
5543       default:
5544         MOZ_ASSERT(0);
5545     }
5546 
5547     // If there is a guard expression, emit it and arrange to jump to the next
5548     // catch block if the guard expression is false.
5549     if (pn->pn_kid2) {
5550         if (!emitTree(pn->pn_kid2))
5551             return false;
5552 
5553         // If the guard expression is false, fall through, pop the block scope,
5554         // and jump to the next catch block.  Otherwise jump over that code and
5555         // pop the dupped exception.
5556         JumpList guardCheck;
5557         if (!emitJump(JSOP_IFNE, &guardCheck))
5558             return false;
5559 
5560         {
5561             NonLocalExitControl nle(this);
5562 
5563             // Move exception back to cx->exception to prepare for
5564             // the next catch.
5565             if (!emit1(JSOP_THROWING))
5566                 return false;
5567 
5568             // Leave the scope for this catch block.
5569             if (!nle.prepareForNonLocalJump(&controlInfo))
5570                 return false;
5571 
5572             // Jump to the next handler added by emitTry.
5573             if (!emitJump(JSOP_GOTO, &controlInfo.guardJump))
5574                 return false;
5575         }
5576 
5577         // Back to normal control flow.
5578         if (!emitJumpTargetAndPatch(guardCheck))
5579             return false;
5580 
5581         // Pop duplicated exception object as we no longer need it.
5582         if (!emit1(JSOP_POP))
5583             return false;
5584     }
5585 
5586     /* Emit the catch body. */
5587     return emitTree(pn->pn_kid3);
5588 }
5589 
5590 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
5591 // comment on EmitSwitch.
5592 MOZ_NEVER_INLINE bool
emitTry(ParseNode * pn)5593 BytecodeEmitter::emitTry(ParseNode* pn)
5594 {
5595     // Track jumps-over-catches and gosubs-to-finally for later fixup.
5596     //
5597     // When a finally block is active, non-local jumps (including
5598     // jumps-over-catches) result in a GOSUB being written into the bytecode
5599     // stream and fixed-up later.
5600     //
5601     TryFinallyControl controlInfo(this, pn->pn_kid3 ? StatementKind::Finally : StatementKind::Try);
5602 
5603     // Since an exception can be thrown at any place inside the try block,
5604     // we need to restore the stack and the scope chain before we transfer
5605     // the control to the exception handler.
5606     //
5607     // For that we store in a try note associated with the catch or
5608     // finally block the stack depth upon the try entry. The interpreter
5609     // uses this depth to properly unwind the stack and the scope chain.
5610     //
5611     int depth = stackDepth;
5612 
5613     // Record the try location, then emit the try block.
5614     unsigned noteIndex;
5615     if (!newSrcNote(SRC_TRY, &noteIndex))
5616         return false;
5617     if (!emit1(JSOP_TRY))
5618         return false;
5619 
5620     ptrdiff_t tryStart = offset();
5621     if (!emitTree(pn->pn_kid1))
5622         return false;
5623     MOZ_ASSERT(depth == stackDepth);
5624 
5625     // GOSUB to finally, if present.
5626     if (pn->pn_kid3) {
5627         if (!emitJump(JSOP_GOSUB, &controlInfo.gosubs))
5628             return false;
5629     }
5630 
5631     // Source note points to the jump at the end of the try block.
5632     if (!setSrcNoteOffset(noteIndex, 0, offset() - tryStart + JSOP_TRY_LENGTH))
5633         return false;
5634 
5635     // Emit jump over catch and/or finally.
5636     JumpList catchJump;
5637     if (!emitJump(JSOP_GOTO, &catchJump))
5638         return false;
5639 
5640     JumpTarget tryEnd;
5641     if (!emitJumpTarget(&tryEnd))
5642         return false;
5643 
5644     // If this try has a catch block, emit it.
5645     ParseNode* catchList = pn->pn_kid2;
5646     if (catchList) {
5647         MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
5648 
5649         // The emitted code for a catch block looks like:
5650         //
5651         // [pushlexicalenv]             only if any local aliased
5652         // exception
5653         // if there is a catchguard:
5654         //   dup
5655         // setlocal 0; pop              assign or possibly destructure exception
5656         // if there is a catchguard:
5657         //   < catchguard code >
5658         //   ifne POST
5659         //   debugleaveblock
5660         //   [poplexicalenv]            only if any local aliased
5661         //   throwing                   pop exception to cx->exception
5662         //   goto <next catch block>
5663         //   POST: pop
5664         // < catch block contents >
5665         // debugleaveblock
5666         // [poplexicalenv]              only if any local aliased
5667         // goto <end of catch blocks>   non-local; finally applies
5668         //
5669         // If there's no catch block without a catchguard, the last <next catch
5670         // block> points to rethrow code.  This code will [gosub] to the finally
5671         // code if appropriate, and is also used for the catch-all trynote for
5672         // capturing exceptions thrown from catch{} blocks.
5673         //
5674         for (ParseNode* pn3 = catchList->pn_head; pn3; pn3 = pn3->pn_next) {
5675             MOZ_ASSERT(this->stackDepth == depth);
5676 
5677             // Clear the frame's return value that might have been set by the
5678             // try block:
5679             //
5680             //   eval("try { 1; throw 2 } catch(e) {}"); // undefined, not 1
5681             if (!emit1(JSOP_UNDEFINED))
5682                 return false;
5683             if (!emit1(JSOP_SETRVAL))
5684                 return false;
5685 
5686             // Emit the lexical scope and catch body.
5687             MOZ_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
5688             if (!emitTree(pn3))
5689                 return false;
5690 
5691             // gosub <finally>, if required.
5692             if (pn->pn_kid3) {
5693                 if (!emitJump(JSOP_GOSUB, &controlInfo.gosubs))
5694                     return false;
5695                 MOZ_ASSERT(this->stackDepth == depth);
5696             }
5697 
5698             // Jump over the remaining catch blocks.  This will get fixed
5699             // up to jump to after catch/finally.
5700             if (!emitJump(JSOP_GOTO, &catchJump))
5701                 return false;
5702 
5703             // If this catch block had a guard clause, patch the guard jump to
5704             // come here.
5705             if (controlInfo.guardJump.offset != -1) {
5706                 if (!emitJumpTargetAndPatch(controlInfo.guardJump))
5707                     return false;
5708                 controlInfo.guardJump.offset = -1;
5709 
5710                 // If this catch block is the last one, rethrow, delegating
5711                 // execution of any finally block to the exception handler.
5712                 if (!pn3->pn_next) {
5713                     if (!emit1(JSOP_EXCEPTION))
5714                         return false;
5715                     if (!emit1(JSOP_THROW))
5716                         return false;
5717                 }
5718             }
5719         }
5720     }
5721 
5722     MOZ_ASSERT(this->stackDepth == depth);
5723 
5724     // Emit the finally handler, if there is one.
5725     JumpTarget finallyStart{ 0 };
5726     if (pn->pn_kid3) {
5727         if (!emitJumpTarget(&finallyStart))
5728             return false;
5729 
5730         // Fix up the gosubs that might have been emitted before non-local
5731         // jumps to the finally code.
5732         patchJumpsToTarget(controlInfo.gosubs, finallyStart);
5733 
5734         // Indicate that we're emitting a subroutine body.
5735         controlInfo.setEmittingSubroutine();
5736         if (!updateSourceCoordNotes(pn->pn_kid3->pn_pos.begin))
5737             return false;
5738         if (!emit1(JSOP_FINALLY))
5739             return false;
5740         if (!emit1(JSOP_GETRVAL))
5741             return false;
5742 
5743         // Clear the frame's return value to make break/continue return
5744         // correct value even if there's no other statement before them:
5745         //
5746         //   eval("x: try { 1 } finally { break x; }");  // undefined, not 1
5747         if (!emit1(JSOP_UNDEFINED))
5748             return false;
5749         if (!emit1(JSOP_SETRVAL))
5750             return false;
5751 
5752         if (!emitTree(pn->pn_kid3))
5753             return false;
5754         if (!emit1(JSOP_SETRVAL))
5755             return false;
5756         if (!emit1(JSOP_RETSUB))
5757             return false;
5758         hasTryFinally = true;
5759         MOZ_ASSERT(this->stackDepth == depth);
5760     }
5761 
5762     // ReconstructPCStack needs a NOP here to mark the end of the last catch block.
5763     if (!emit1(JSOP_NOP))
5764         return false;
5765 
5766     // Fix up the end-of-try/catch jumps to come here.
5767     if (!emitJumpTargetAndPatch(catchJump))
5768         return false;
5769 
5770     // Add the try note last, to let post-order give us the right ordering
5771     // (first to last for a given nesting level, inner to outer by level).
5772     if (catchList && !tryNoteList.append(JSTRY_CATCH, depth, tryStart, tryEnd.offset))
5773         return false;
5774 
5775     // If we've got a finally, mark try+catch region with additional
5776     // trynote to catch exceptions (re)thrown from a catch block or
5777     // for the try{}finally{} case.
5778     if (pn->pn_kid3 && !tryNoteList.append(JSTRY_FINALLY, depth, tryStart, finallyStart.offset))
5779         return false;
5780 
5781     return true;
5782 }
5783 
5784 bool
emitIf(ParseNode * pn)5785 BytecodeEmitter::emitIf(ParseNode* pn)
5786 {
5787     IfThenElseEmitter ifThenElse(this);
5788 
5789   if_again:
5790     /* Emit code for the condition before pushing stmtInfo. */
5791     if (!emitConditionallyExecutedTree(pn->pn_kid1))
5792         return false;
5793 
5794     ParseNode* elseNode = pn->pn_kid3;
5795     if (elseNode) {
5796         if (!ifThenElse.emitIfElse())
5797             return false;
5798     } else {
5799         if (!ifThenElse.emitIf())
5800             return false;
5801     }
5802 
5803     /* Emit code for the then part. */
5804     if (!emitConditionallyExecutedTree(pn->pn_kid2))
5805         return false;
5806 
5807     if (elseNode) {
5808         if (!ifThenElse.emitElse())
5809             return false;
5810 
5811         if (elseNode->isKind(PNK_IF)) {
5812             pn = elseNode;
5813             goto if_again;
5814         }
5815 
5816         /* Emit code for the else part. */
5817         if (!emitConditionallyExecutedTree(elseNode))
5818             return false;
5819     }
5820 
5821     if (!ifThenElse.emitEnd())
5822         return false;
5823 
5824     return true;
5825 }
5826 
5827 bool
emitHoistedFunctionsInList(ParseNode * list)5828 BytecodeEmitter::emitHoistedFunctionsInList(ParseNode* list)
5829 {
5830     MOZ_ASSERT(list->pn_xflags & PNX_FUNCDEFS);
5831 
5832     for (ParseNode* pn = list->pn_head; pn; pn = pn->pn_next) {
5833         ParseNode* maybeFun = pn;
5834 
5835         if (!sc->strict()) {
5836             while (maybeFun->isKind(PNK_LABEL))
5837                 maybeFun = maybeFun->as<LabeledStatement>().statement();
5838         }
5839 
5840         if (maybeFun->isKind(PNK_FUNCTION) && maybeFun->functionIsHoisted()) {
5841             if (!emitTree(maybeFun))
5842                 return false;
5843         }
5844     }
5845 
5846     return true;
5847 }
5848 
5849 bool
emitLexicalScopeBody(ParseNode * body,EmitLineNumberNote emitLineNote)5850 BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote)
5851 {
5852     if (body->isKind(PNK_STATEMENTLIST) && body->pn_xflags & PNX_FUNCDEFS) {
5853         // This block contains function statements whose definitions are
5854         // hoisted to the top of the block. Emit these as a separate pass
5855         // before the rest of the block.
5856         if (!emitHoistedFunctionsInList(body))
5857             return false;
5858     }
5859 
5860     // Line notes were updated by emitLexicalScope.
5861     return emitTree(body, emitLineNote);
5862 }
5863 
5864 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
5865 // the comment on emitSwitch.
5866 MOZ_NEVER_INLINE bool
emitLexicalScope(ParseNode * pn)5867 BytecodeEmitter::emitLexicalScope(ParseNode* pn)
5868 {
5869     MOZ_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
5870 
5871     TDZCheckCache tdzCache(this);
5872 
5873     ParseNode* body = pn->scopeBody();
5874     if (pn->isEmptyScope())
5875         return emitLexicalScopeBody(body);
5876 
5877     // Update line number notes before emitting TDZ poison in
5878     // EmitterScope::enterLexical to avoid spurious pausing on seemingly
5879     // non-effectful lines in Debugger.
5880     //
5881     // For example, consider the following code.
5882     //
5883     // L1: {
5884     // L2:   let x = 42;
5885     // L3: }
5886     //
5887     // If line number notes were not updated before the TDZ poison, the TDZ
5888     // poison bytecode sequence of 'uninitialized; initlexical' will have line
5889     // number L1, and the Debugger will pause there.
5890     if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
5891         ParseNode* pnForPos = body;
5892         if (body->isKind(PNK_STATEMENTLIST) && body->pn_head)
5893             pnForPos = body->pn_head;
5894         if (!updateLineNumberNotes(pnForPos->pn_pos.begin))
5895             return false;
5896     }
5897 
5898     EmitterScope emitterScope(this);
5899     ScopeKind kind;
5900     if (body->isKind(PNK_CATCH))
5901         kind = body->pn_kid1->isKind(PNK_NAME) ? ScopeKind::SimpleCatch : ScopeKind::Catch;
5902     else
5903         kind = ScopeKind::Lexical;
5904 
5905     if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
5906         return false;
5907 
5908     if (body->isKind(PNK_FOR)) {
5909         // for loops need to emit {FRESHEN,RECREATE}LEXICALENV if there are
5910         // lexical declarations in the head. Signal this by passing a
5911         // non-nullptr lexical scope.
5912         if (!emitFor(body, &emitterScope))
5913             return false;
5914     } else {
5915         if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE))
5916             return false;
5917     }
5918 
5919     return emitterScope.leave(this);
5920 }
5921 
5922 bool
emitWith(ParseNode * pn)5923 BytecodeEmitter::emitWith(ParseNode* pn)
5924 {
5925     if (!emitTree(pn->pn_left))
5926         return false;
5927 
5928     EmitterScope emitterScope(this);
5929     if (!emitterScope.enterWith(this))
5930         return false;
5931 
5932     if (!emitTree(pn->pn_right))
5933         return false;
5934 
5935     return emitterScope.leave(this);
5936 }
5937 
5938 bool
emitRequireObjectCoercible()5939 BytecodeEmitter::emitRequireObjectCoercible()
5940 {
5941     // For simplicity, handle this in self-hosted code, at cost of 13 bytes of
5942     // bytecode versus 1 byte for a dedicated opcode.  As more places need this
5943     // behavior, we may want to reconsider this tradeoff.
5944 
5945 #ifdef DEBUG
5946     auto depth = this->stackDepth;
5947 #endif
5948     MOZ_ASSERT(depth > 0);                 // VAL
5949     if (!emit1(JSOP_DUP))                  // VAL VAL
5950         return false;
5951 
5952     // Note that "intrinsic" is a misnomer: we're calling a *self-hosted*
5953     // function that's not an intrinsic!  But it nonetheless works as desired.
5954     if (!emitAtomOp(cx->names().RequireObjectCoercible,
5955                     JSOP_GETINTRINSIC))    // VAL VAL REQUIREOBJECTCOERCIBLE
5956     {
5957         return false;
5958     }
5959     if (!emit1(JSOP_UNDEFINED))            // VAL VAL REQUIREOBJECTCOERCIBLE UNDEFINED
5960         return false;
5961     if (!emit2(JSOP_PICK, 2))              // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
5962         return false;
5963     if (!emitCall(JSOP_CALL, 1))           // VAL IGNORED
5964         return false;
5965     checkTypeSet(JSOP_CALL);
5966 
5967     if (!emit1(JSOP_POP))                  // VAL
5968         return false;
5969 
5970     MOZ_ASSERT(depth == this->stackDepth);
5971     return true;
5972 }
5973 
5974 bool
emitIterator()5975 BytecodeEmitter::emitIterator()
5976 {
5977     // Convert iterable to iterator.
5978     if (!emit1(JSOP_DUP))                                         // OBJ OBJ
5979         return false;
5980     if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator)))   // OBJ OBJ @@ITERATOR
5981         return false;
5982     if (!emitElemOpBase(JSOP_CALLELEM))                           // OBJ ITERFN
5983         return false;
5984     if (!emit1(JSOP_SWAP))                                        // ITERFN OBJ
5985         return false;
5986     if (!emitCall(JSOP_CALLITER, 0))                              // ITER
5987         return false;
5988     checkTypeSet(JSOP_CALLITER);
5989     if (!emitCheckIsObj(CheckIsObjectKind::GetIterator))          // ITER
5990         return false;
5991     return true;
5992 }
5993 
5994 bool
emitSpread(bool allowSelfHosted)5995 BytecodeEmitter::emitSpread(bool allowSelfHosted)
5996 {
5997     LoopControl loopInfo(this, StatementKind::Spread);
5998 
5999     // Jump down to the loop condition to minimize overhead assuming at least
6000     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
6001     // find the loop-closing jump.
6002     unsigned noteIndex;
6003     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
6004         return false;
6005 
6006     // Jump down to the loop condition to minimize overhead, assuming at least
6007     // one iteration.  (This is also what we do for loops; whether this
6008     // assumption holds for spreads is an unanswered question.)
6009     JumpList initialJump;
6010     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ARR I (during the goto)
6011         return false;
6012 
6013     JumpTarget top{ -1 };
6014     if (!emitLoopHead(nullptr, &top))                     // ITER ARR I
6015         return false;
6016 
6017     // When we enter the goto above, we have ITER ARR I on the stack.  But when
6018     // we reach this point on the loop backedge (if spreading produces at least
6019     // one value), we've additionally pushed a RESULT iteration value.
6020     // Increment manually to reflect this.
6021     this->stackDepth++;
6022 
6023     JumpList beq;
6024     JumpTarget breakTarget{ -1 };
6025     {
6026 #ifdef DEBUG
6027         auto loopDepth = this->stackDepth;
6028 #endif
6029 
6030         // Emit code to assign result.value to the iteration variable.
6031         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER ARR I VALUE
6032             return false;
6033         if (!emit1(JSOP_INITELEM_INC))                    // ITER ARR (I+1)
6034             return false;
6035 
6036         MOZ_ASSERT(this->stackDepth == loopDepth - 1);
6037 
6038         // Spread operations can't contain |continue|, so don't bother setting loop
6039         // and enclosing "update" offsets, as we do with for-loops.
6040 
6041         // COME FROM the beginning of the loop to here.
6042         if (!emitLoopEntry(nullptr, initialJump))         // ITER ARR I
6043             return false;
6044 
6045         if (!emitDupAt(2))                                // ITER ARR I ITER
6046             return false;
6047         if (!emitIteratorNext(nullptr, allowSelfHosted))  // ITER ARR I RESULT
6048             return false;
6049         if (!emit1(JSOP_DUP))                             // ITER ARR I RESULT RESULT
6050             return false;
6051         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // ITER ARR I RESULT DONE?
6052             return false;
6053 
6054         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget)) // ITER ARR I RESULT
6055             return false;
6056 
6057         MOZ_ASSERT(this->stackDepth == loopDepth);
6058     }
6059 
6060     // Let Ion know where the closing jump of this loop is.
6061     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
6062         return false;
6063 
6064     // No breaks or continues should occur in spreads.
6065     MOZ_ASSERT(loopInfo.breaks.offset == -1);
6066     MOZ_ASSERT(loopInfo.continues.offset == -1);
6067 
6068     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
6069         return false;
6070 
6071     if (!emit2(JSOP_PICK, 3))                             // ARR FINAL_INDEX RESULT ITER
6072         return false;
6073 
6074     return emitUint16Operand(JSOP_POPN, 2);               // ARR FINAL_INDEX
6075 }
6076 
6077 bool
emitInitializeForInOrOfTarget(ParseNode * forHead)6078 BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
6079 {
6080     MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
6081     MOZ_ASSERT(forHead->isArity(PN_TERNARY));
6082 
6083     MOZ_ASSERT(this->stackDepth >= 1,
6084                "must have a per-iteration value for initializing");
6085 
6086     ParseNode* target = forHead->pn_kid1;
6087     MOZ_ASSERT(!forHead->pn_kid2);
6088 
6089     // If the for-in/of loop didn't have a variable declaration, per-loop
6090     // initialization is just assigning the iteration value to a target
6091     // expression.
6092     if (!parser->handler.isDeclarationList(target))
6093         return emitAssignment(target, JSOP_NOP, nullptr); // ... ITERVAL
6094 
6095     // Otherwise, per-loop initialization is (possibly) declaration
6096     // initialization.  If the declaration is a lexical declaration, it must be
6097     // initialized.  If the declaration is a variable declaration, an
6098     // assignment to that name (which does *not* necessarily assign to the
6099     // variable!) must be generated.
6100 
6101     if (!updateSourceCoordNotes(target->pn_pos.begin))
6102         return false;
6103 
6104     MOZ_ASSERT(target->isForLoopDeclaration());
6105     target = parser->handler.singleBindingFromDeclaration(target);
6106 
6107     if (target->isKind(PNK_NAME)) {
6108         auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
6109                                       bool emittedBindOp)
6110         {
6111             if (emittedBindOp) {
6112                 // Per-iteration initialization in for-in/of loops computes the
6113                 // iteration value *before* initializing.  Thus the
6114                 // initializing value may be buried under a bind-specific value
6115                 // on the stack.  Swap it to the top of the stack.
6116                 MOZ_ASSERT(bce->stackDepth >= 2);
6117                 return bce->emit1(JSOP_SWAP);
6118             }
6119 
6120             // In cases of emitting a frame slot or environment slot,
6121             // nothing needs be done.
6122             MOZ_ASSERT(bce->stackDepth >= 1);
6123             return true;
6124         };
6125 
6126         // The caller handles removing the iteration value from the stack.
6127         return emitInitializeName(target, emitSwapScopeAndRhs);
6128     }
6129 
6130     MOZ_ASSERT(!target->isKind(PNK_ASSIGN),
6131                "for-in/of loop destructuring declarations can't have initializers");
6132 
6133     MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
6134     return emitDestructuringOps(target, DestructuringDeclaration);
6135 }
6136 
6137 bool
emitForOf(ParseNode * forOfLoop,EmitterScope * headLexicalEmitterScope)6138 BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope)
6139 {
6140     MOZ_ASSERT(forOfLoop->isKind(PNK_FOR));
6141     MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
6142 
6143     ParseNode* forOfHead = forOfLoop->pn_left;
6144     MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
6145     MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
6146 
6147     // Evaluate the expression being iterated.
6148     ParseNode* forHeadExpr = forOfHead->pn_kid3;
6149     if (!emitTree(forHeadExpr))                           // ITERABLE
6150         return false;
6151     if (!emitIterator())                                  // ITER
6152         return false;
6153 
6154     // For-of loops have both the iterator and the value on the stack. Push
6155     // undefined to balance the stack.
6156     if (!emit1(JSOP_UNDEFINED))                           // ITER RESULT
6157         return false;
6158 
6159     LoopControl loopInfo(this, StatementKind::ForOfLoop);
6160 
6161     // Annotate so IonMonkey can find the loop-closing jump.
6162     unsigned noteIndex;
6163     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
6164         return false;
6165 
6166     JumpList initialJump;
6167     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER RESULT
6168         return false;
6169 
6170     JumpTarget top{ -1 };
6171     if (!emitLoopHead(nullptr, &top))                     // ITER RESULT
6172         return false;
6173 
6174     // If the loop had an escaping lexical declaration, replace the current
6175     // environment with an dead zoned one to implement TDZ semantics.
6176     if (headLexicalEmitterScope) {
6177         // The environment chain only includes an environment for the for-of
6178         // loop head *if* a scope binding is captured, thereby requiring
6179         // recreation each iteration. If a lexical scope exists for the head,
6180         // it must be the innermost one. If that scope has closed-over
6181         // bindings inducing an environment, recreate the current environment.
6182         DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
6183         MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
6184         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
6185         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
6186 
6187         if (headLexicalEmitterScope->hasEnvironment()) {
6188             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER RESULT
6189                 return false;
6190         }
6191 
6192         // For uncaptured bindings, put them back in TDZ.
6193         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
6194             return false;
6195     }
6196 
6197     JumpList beq;
6198     JumpTarget breakTarget{ -1 };
6199     {
6200 #ifdef DEBUG
6201         auto loopDepth = this->stackDepth;
6202 #endif
6203 
6204         // Emit code to assign result.value to the iteration variable.
6205         if (!emit1(JSOP_DUP))                             // ITER RESULT RESULT
6206             return false;
6207         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER RESULT VALUE
6208             return false;
6209 
6210         if (!emitInitializeForInOrOfTarget(forOfHead))    // ITER RESULT VALUE
6211             return false;
6212 
6213         if (!emit1(JSOP_POP))                             // ITER RESULT
6214             return false;
6215 
6216         MOZ_ASSERT(this->stackDepth == loopDepth,
6217                    "the stack must be balanced around the initializing "
6218                    "operation");
6219 
6220         // Perform the loop body.
6221         ParseNode* forBody = forOfLoop->pn_right;
6222         if (!emitTree(forBody))                           // ITER RESULT
6223             return false;
6224 
6225         // Set offset for continues.
6226         loopInfo.continueTarget = { offset() };
6227 
6228         if (!emitLoopEntry(forHeadExpr, initialJump))     // ITER RESULT
6229             return false;
6230 
6231         if (!emit1(JSOP_POP))                             // ITER
6232             return false;
6233         if (!emit1(JSOP_DUP))                             // ITER ITER
6234             return false;
6235 
6236         if (!emitIteratorNext(forOfHead))                 // ITER RESULT
6237             return false;
6238         if (!emit1(JSOP_DUP))                             // ITER RESULT RESULT
6239             return false;
6240         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // ITER RESULT DONE?
6241             return false;
6242 
6243         if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
6244             return false;                                 // ITER RESULT
6245 
6246         MOZ_ASSERT(this->stackDepth == loopDepth);
6247     }
6248 
6249     // Let Ion know where the closing jump of this loop is.
6250     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
6251         return false;
6252 
6253     if (!loopInfo.patchBreaksAndContinues(this))
6254         return false;
6255 
6256     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
6257         return false;
6258 
6259     return emitUint16Operand(JSOP_POPN, 2);               //
6260 }
6261 
6262 bool
emitForIn(ParseNode * forInLoop,EmitterScope * headLexicalEmitterScope)6263 BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
6264 {
6265     MOZ_ASSERT(forInLoop->isKind(PNK_FOR));
6266     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
6267     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
6268 
6269     ParseNode* forInHead = forInLoop->pn_left;
6270     MOZ_ASSERT(forInHead->isKind(PNK_FORIN));
6271     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
6272 
6273     // Annex B: Evaluate the var-initializer expression if present.
6274     // |for (var i = initializer in expr) { ... }|
6275     ParseNode* forInTarget = forInHead->pn_kid1;
6276     if (parser->handler.isDeclarationList(forInTarget)) {
6277         ParseNode* decl = parser->handler.singleBindingFromDeclaration(forInTarget);
6278         if (decl->isKind(PNK_NAME)) {
6279             if (ParseNode* initializer = decl->expr()) {
6280                 MOZ_ASSERT(forInTarget->isKind(PNK_VAR),
6281                            "for-in initializers are only permitted for |var| declarations");
6282 
6283                 if (!updateSourceCoordNotes(decl->pn_pos.begin))
6284                     return false;
6285 
6286                 auto emitRhs = [initializer](BytecodeEmitter* bce, const NameLocation&, bool) {
6287                     return bce->emitTree(initializer);
6288                 };
6289 
6290                 if (!emitInitializeName(decl, emitRhs))
6291                     return false;
6292 
6293                 // Pop the initializer.
6294                 if (!emit1(JSOP_POP))
6295                     return false;
6296             }
6297         }
6298     }
6299 
6300     // Evaluate the expression being iterated.
6301     ParseNode* expr = forInHead->pn_kid3;
6302     if (!emitTree(expr))                                  // EXPR
6303         return false;
6304 
6305     // Convert the value to the appropriate sort of iterator object for the
6306     // loop variant (for-in, for-each-in, or destructuring for-in).
6307     unsigned iflags = forInLoop->pn_iflags;
6308     MOZ_ASSERT(0 == (iflags & ~(JSITER_FOREACH | JSITER_ENUMERATE)));
6309     if (!emit2(JSOP_ITER, AssertedCast<uint8_t>(iflags))) // ITER
6310         return false;
6311 
6312     // For-in loops have both the iterator and the value on the stack. Push
6313     // undefined to balance the stack.
6314     if (!emit1(JSOP_UNDEFINED))                           // ITER ITERVAL
6315         return false;
6316 
6317     LoopControl loopInfo(this, StatementKind::ForInLoop);
6318 
6319     /* Annotate so IonMonkey can find the loop-closing jump. */
6320     unsigned noteIndex;
6321     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
6322         return false;
6323 
6324     // Jump down to the loop condition to minimize overhead (assuming at least
6325     // one iteration, just like the other loop forms).
6326     JumpList initialJump;
6327     if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ITERVAL
6328         return false;
6329 
6330     JumpTarget top{ -1 };
6331     if (!emitLoopHead(nullptr, &top))                     // ITER ITERVAL
6332         return false;
6333 
6334     // If the loop had an escaping lexical declaration, replace the current
6335     // environment with an dead zoned one to implement TDZ semantics.
6336     if (headLexicalEmitterScope) {
6337         // The environment chain only includes an environment for the for-in
6338         // loop head *if* a scope binding is captured, thereby requiring
6339         // recreation each iteration. If a lexical scope exists for the head,
6340         // it must be the innermost one. If that scope has closed-over
6341         // bindings inducing an environment, recreate the current environment.
6342         MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
6343         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
6344         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
6345 
6346         if (headLexicalEmitterScope->hasEnvironment()) {
6347             if (!emit1(JSOP_RECREATELEXICALENV))          // ITER ITERVAL
6348                 return false;
6349         }
6350 
6351         // For uncaptured bindings, put them back in TDZ.
6352         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
6353             return false;
6354     }
6355 
6356     {
6357 #ifdef DEBUG
6358         auto loopDepth = this->stackDepth;
6359 #endif
6360         MOZ_ASSERT(loopDepth >= 2);
6361 
6362         if (!emitInitializeForInOrOfTarget(forInHead))    // ITER ITERVAL
6363             return false;
6364 
6365         MOZ_ASSERT(this->stackDepth == loopDepth,
6366                    "iterator and iterval must be left on the stack");
6367     }
6368 
6369     // Perform the loop body.
6370     ParseNode* forBody = forInLoop->pn_right;
6371     if (!emitTree(forBody))                               // ITER ITERVAL
6372         return false;
6373 
6374     // Set offset for continues.
6375     loopInfo.continueTarget = { offset() };
6376 
6377     if (!emitLoopEntry(nullptr, initialJump))             // ITER ITERVAL
6378         return false;
6379     if (!emit1(JSOP_POP))                                 // ITER
6380         return false;
6381     if (!emit1(JSOP_MOREITER))                            // ITER NEXTITERVAL?
6382         return false;
6383     if (!emit1(JSOP_ISNOITER))                            // ITER NEXTITERVAL? ISNOITER
6384         return false;
6385 
6386     JumpList beq;
6387     JumpTarget breakTarget{ -1 };
6388     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
6389         return false;                                     // ITER NEXTITERVAL
6390 
6391     // Set the srcnote offset so we can find the closing jump.
6392     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
6393         return false;
6394 
6395     if (!loopInfo.patchBreaksAndContinues(this))
6396         return false;
6397 
6398     // Pop the enumeration value.
6399     if (!emit1(JSOP_POP))                                 // ITER
6400         return false;
6401 
6402     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, offset()))
6403         return false;
6404 
6405     return emit1(JSOP_ENDITER);                           //
6406 }
6407 
6408 /* C-style `for (init; cond; update) ...` loop. */
6409 bool
emitCStyleFor(ParseNode * pn,EmitterScope * headLexicalEmitterScope)6410 BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
6411 {
6412     LoopControl loopInfo(this, StatementKind::ForLoop);
6413 
6414     ParseNode* forHead = pn->pn_left;
6415     ParseNode* forBody = pn->pn_right;
6416 
6417     // If the head of this for-loop declared any lexical variables, the parser
6418     // wrapped this PNK_FOR node in a PNK_LEXICALSCOPE representing the
6419     // implicit scope of those variables. By the time we get here, we have
6420     // already entered that scope. So far, so good.
6421     //
6422     // ### Scope freshening
6423     //
6424     // Each iteration of a `for (let V...)` loop creates a fresh loop variable
6425     // binding for V, even if the loop is a C-style `for(;;)` loop:
6426     //
6427     //     var funcs = [];
6428     //     for (let i = 0; i < 2; i++)
6429     //         funcs.push(function() { return i; });
6430     //     assertEq(funcs[0](), 0);  // the two closures capture...
6431     //     assertEq(funcs[1](), 1);  // ...two different `i` bindings
6432     //
6433     // This is implemented by "freshening" the implicit block -- changing the
6434     // scope chain to a fresh clone of the instantaneous block object -- each
6435     // iteration, just before evaluating the "update" in for(;;) loops.
6436     //
6437     // No freshening occurs in `for (const ...;;)` as there's no point: you
6438     // can't reassign consts. This is observable through the Debugger API. (The
6439     // ES6 spec also skips cloning the environment in this case.)
6440     bool forLoopRequiresFreshening = false;
6441     if (ParseNode* init = forHead->pn_kid1) {
6442         // Emit the `init` clause, whether it's an expression or a variable
6443         // declaration. (The loop variables were hoisted into an enclosing
6444         // scope, but we still need to emit code for the initializers.)
6445         if (!updateSourceCoordNotes(init->pn_pos.begin))
6446             return false;
6447         if (!emitTree(init))
6448             return false;
6449 
6450         if (!init->isForLoopDeclaration()) {
6451             // 'init' is an expression, not a declaration. emitTree left its
6452             // value on the stack.
6453             if (!emit1(JSOP_POP))
6454                 return false;
6455         }
6456 
6457         // ES 13.7.4.8 step 2. The initial freshening.
6458         //
6459         // If an initializer let-declaration may be captured during loop iteration,
6460         // the current scope has an environment.  If so, freshen the current
6461         // environment to expose distinct bindings for each loop iteration.
6462         forLoopRequiresFreshening = init->isKind(PNK_LET) && headLexicalEmitterScope;
6463         if (forLoopRequiresFreshening) {
6464             // The environment chain only includes an environment for the for(;;)
6465             // loop head's let-declaration *if* a scope binding is captured, thus
6466             // requiring a fresh environment each iteration. If a lexical scope
6467             // exists for the head, it must be the innermost one. If that scope
6468             // has closed-over bindings inducing an environment, recreate the
6469             // current environment.
6470             MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
6471             MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
6472 
6473             if (headLexicalEmitterScope->hasEnvironment()) {
6474                 if (!emit1(JSOP_FRESHENLEXICALENV))
6475                     return false;
6476             }
6477         }
6478     }
6479 
6480     /*
6481      * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
6482      * Use tmp to hold the biased srcnote "top" offset, which differs
6483      * from the top local variable by the length of the JSOP_GOTO
6484      * emitted in between tmp and top if this loop has a condition.
6485      */
6486     unsigned noteIndex;
6487     if (!newSrcNote(SRC_FOR, &noteIndex))
6488         return false;
6489     if (!emit1(JSOP_NOP))
6490         return false;
6491     ptrdiff_t tmp = offset();
6492 
6493     JumpList jmp;
6494     if (forHead->pn_kid2) {
6495         /* Goto the loop condition, which branches back to iterate. */
6496         if (!emitJump(JSOP_GOTO, &jmp))
6497             return false;
6498     }
6499 
6500     /* Emit code for the loop body. */
6501     JumpTarget top{ -1 };
6502     if (!emitLoopHead(forBody, &top))
6503         return false;
6504     if (jmp.offset == -1 && !emitLoopEntry(forBody, jmp))
6505         return false;
6506 
6507     if (!emitConditionallyExecutedTree(forBody))
6508         return false;
6509 
6510     // Set loop and enclosing "update" offsets, for continue.  Note that we
6511     // continue to immediately *before* the block-freshening: continuing must
6512     // refresh the block.
6513     if (!emitJumpTarget(&loopInfo.continueTarget))
6514         return false;
6515 
6516     // ES 13.7.4.8 step 3.e. The per-iteration freshening.
6517     if (forLoopRequiresFreshening) {
6518         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
6519         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
6520 
6521         if (headLexicalEmitterScope->hasEnvironment()) {
6522             if (!emit1(JSOP_FRESHENLEXICALENV))
6523                 return false;
6524         }
6525     }
6526 
6527     // Check for update code to do before the condition (if any).
6528     // The update code may not be executed at all; it needs its own TDZ cache.
6529     if (ParseNode* update = forHead->pn_kid3) {
6530         TDZCheckCache tdzCache(this);
6531 
6532         if (!updateSourceCoordNotes(update->pn_pos.begin))
6533             return false;
6534         if (!emitTree(update))
6535             return false;
6536         if (!emit1(JSOP_POP))
6537             return false;
6538 
6539         /* Restore the absolute line number for source note readers. */
6540         uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.end);
6541         if (currentLine() != lineNum) {
6542             if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum)))
6543                 return false;
6544             current->currentLine = lineNum;
6545             current->lastColumn = 0;
6546         }
6547     }
6548 
6549     ptrdiff_t tmp3 = offset();
6550 
6551     if (forHead->pn_kid2) {
6552         /* Fix up the goto from top to target the loop condition. */
6553         MOZ_ASSERT(jmp.offset >= 0);
6554         if (!emitLoopEntry(forHead->pn_kid2, jmp))
6555             return false;
6556 
6557         if (!emitTree(forHead->pn_kid2))
6558             return false;
6559     } else if (!forHead->pn_kid3) {
6560         // If there is no condition clause and no update clause, mark
6561         // the loop-ending "goto" with the location of the "for".
6562         // This ensures that the debugger will stop on each loop
6563         // iteration.
6564         if (!updateSourceCoordNotes(pn->pn_pos.begin))
6565             return false;
6566     }
6567 
6568     /* Set the first note offset so we can find the loop condition. */
6569     if (!setSrcNoteOffset(noteIndex, 0, tmp3 - tmp))
6570         return false;
6571     if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTarget.offset - tmp))
6572         return false;
6573 
6574     /* If no loop condition, just emit a loop-closing jump. */
6575     JumpList beq;
6576     JumpTarget breakTarget{ -1 };
6577     if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
6578         return false;
6579 
6580     /* The third note offset helps us find the loop-closing jump. */
6581     if (!setSrcNoteOffset(noteIndex, 2, beq.offset - tmp))
6582         return false;
6583 
6584     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
6585         return false;
6586 
6587     if (!loopInfo.patchBreaksAndContinues(this))
6588         return false;
6589 
6590     return true;
6591 }
6592 
6593 bool
emitFor(ParseNode * pn,EmitterScope * headLexicalEmitterScope)6594 BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
6595 {
6596     MOZ_ASSERT(pn->isKind(PNK_FOR));
6597 
6598     if (pn->pn_left->isKind(PNK_FORHEAD))
6599         return emitCStyleFor(pn, headLexicalEmitterScope);
6600 
6601     if (!updateLineNumberNotes(pn->pn_pos.begin))
6602         return false;
6603 
6604     if (pn->pn_left->isKind(PNK_FORIN))
6605         return emitForIn(pn, headLexicalEmitterScope);
6606 
6607     MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF));
6608     return emitForOf(pn, headLexicalEmitterScope);
6609 }
6610 
6611 bool
emitComprehensionForInOrOfVariables(ParseNode * pn,bool * lexicalScope)6612 BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexicalScope)
6613 {
6614     // ES6 specifies that lexical for-loop variables get a fresh binding each
6615     // iteration, and that evaluation of the expression looped over occurs with
6616     // these variables dead zoned.  But these rules only apply to *standard*
6617     // for-in/of loops, and we haven't extended these requirements to
6618     // comprehension syntax.
6619 
6620     *lexicalScope = pn->isKind(PNK_LEXICALSCOPE);
6621     if (*lexicalScope) {
6622         // This is initially-ES7-tracked syntax, now with considerably murkier
6623         // outlook. The scope work is done by the caller by instantiating an
6624         // EmitterScope. There's nothing to do here.
6625     } else {
6626         // This is legacy comprehension syntax.  We'll have PNK_LET here, using
6627         // a lexical scope provided by/for the entire comprehension.  Name
6628         // analysis assumes declarations initialize lets, but as we're handling
6629         // this declaration manually, we must also initialize manually to avoid
6630         // triggering dead zone checks.
6631         MOZ_ASSERT(pn->isKind(PNK_LET));
6632         MOZ_ASSERT(pn->pn_count == 1);
6633 
6634         if (!emitDeclarationList(pn))
6635             return false;
6636     }
6637 
6638     return true;
6639 }
6640 
6641 bool
emitComprehensionForOf(ParseNode * pn)6642 BytecodeEmitter::emitComprehensionForOf(ParseNode* pn)
6643 {
6644     MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
6645 
6646     ParseNode* forHead = pn->pn_left;
6647     MOZ_ASSERT(forHead->isKind(PNK_FOROF));
6648 
6649     ParseNode* forHeadExpr = forHead->pn_kid3;
6650     ParseNode* forBody = pn->pn_right;
6651 
6652     ParseNode* loopDecl = forHead->pn_kid1;
6653     bool lexicalScope = false;
6654     if (!emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
6655         return false;
6656 
6657     // For-of loops run with two values on the stack: the iterator and the
6658     // current result object.
6659 
6660     // Evaluate the expression to the right of 'of'.
6661     if (!emitTree(forHeadExpr))                // EXPR
6662         return false;
6663     if (!emitIterator())                       // ITER
6664         return false;
6665 
6666     // Push a dummy result so that we properly enter iteration midstream.
6667     if (!emit1(JSOP_UNDEFINED))                // ITER RESULT
6668         return false;
6669 
6670     // Enter the block before the loop body, after evaluating the obj.
6671     // Initialize let bindings with undefined when entering, as the name
6672     // assigned to is a plain assignment.
6673     TDZCheckCache tdzCache(this);
6674     Maybe<EmitterScope> emitterScope;
6675     ParseNode* loopVariableName;
6676     if (lexicalScope) {
6677         loopVariableName = parser->handler.singleBindingFromDeclaration(loopDecl->pn_expr);
6678         emitterScope.emplace(this);
6679         if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
6680             return false;
6681     } else {
6682         loopVariableName = parser->handler.singleBindingFromDeclaration(loopDecl);
6683     }
6684 
6685     LoopControl loopInfo(this, StatementKind::ForOfLoop);
6686 
6687     // Jump down to the loop condition to minimize overhead assuming at least
6688     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
6689     // find the loop-closing jump.
6690     unsigned noteIndex;
6691     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
6692         return false;
6693     JumpList jmp;
6694     if (!emitJump(JSOP_GOTO, &jmp))
6695         return false;
6696 
6697     JumpTarget top{ -1 };
6698     if (!emitLoopHead(nullptr, &top))
6699         return false;
6700 
6701 #ifdef DEBUG
6702     int loopDepth = this->stackDepth;
6703 #endif
6704 
6705     // Emit code to assign result.value to the iteration variable.
6706     if (!emit1(JSOP_DUP))                                 // ITER RESULT RESULT
6707         return false;
6708     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ITER RESULT VALUE
6709         return false;
6710     if (!emitAssignment(loopVariableName, JSOP_NOP, nullptr)) // ITER RESULT VALUE
6711         return false;
6712     if (!emit1(JSOP_POP))                                 // ITER RESULT
6713         return false;
6714 
6715     // The stack should be balanced around the assignment opcode sequence.
6716     MOZ_ASSERT(this->stackDepth == loopDepth);
6717 
6718     // Emit code for the loop body.
6719     if (!emitTree(forBody))
6720         return false;
6721 
6722     // Set offset for continues.
6723     loopInfo.continueTarget = { offset() };
6724 
6725     if (!emitLoopEntry(forHeadExpr, jmp))
6726         return false;
6727 
6728     if (!emit1(JSOP_POP))                                 // ITER
6729         return false;
6730     if (!emit1(JSOP_DUP))                                 // ITER ITER
6731         return false;
6732     if (!emitIteratorNext(forHead))                       // ITER RESULT
6733         return false;
6734     if (!emit1(JSOP_DUP))                                 // ITER RESULT RESULT
6735         return false;
6736     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // ITER RESULT DONE?
6737         return false;
6738 
6739     JumpList beq;
6740     JumpTarget breakTarget{ -1 };
6741     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget)) // ITER RESULT
6742         return false;
6743 
6744     MOZ_ASSERT(this->stackDepth == loopDepth);
6745 
6746     // Let Ion know where the closing jump of this loop is.
6747     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
6748         return false;
6749 
6750     if (!loopInfo.patchBreaksAndContinues(this))
6751         return false;
6752 
6753     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
6754         return false;
6755 
6756     if (emitterScope) {
6757         if (!emitterScope->leave(this))
6758             return false;
6759         emitterScope.reset();
6760     }
6761 
6762     // Pop the result and the iter.
6763     return emitUint16Operand(JSOP_POPN, 2);               //
6764 }
6765 
6766 bool
emitComprehensionForIn(ParseNode * pn)6767 BytecodeEmitter::emitComprehensionForIn(ParseNode* pn)
6768 {
6769     MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
6770 
6771     ParseNode* forHead = pn->pn_left;
6772     MOZ_ASSERT(forHead->isKind(PNK_FORIN));
6773 
6774     ParseNode* forBody = pn->pn_right;
6775 
6776     ParseNode* loopDecl = forHead->pn_kid1;
6777     bool lexicalScope = false;
6778     if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
6779         return false;
6780 
6781     // Evaluate the expression to the right of 'in'.
6782     if (!emitTree(forHead->pn_kid3))
6783         return false;
6784 
6785     /*
6786      * Emit a bytecode to convert top of stack value to the iterator
6787      * object depending on the loop variant (for-in, for-each-in, or
6788      * destructuring for-in).
6789      */
6790     MOZ_ASSERT(pn->isOp(JSOP_ITER));
6791     if (!emit2(JSOP_ITER, (uint8_t) pn->pn_iflags))
6792         return false;
6793 
6794     // For-in loops have both the iterator and the value on the stack. Push
6795     // undefined to balance the stack.
6796     if (!emit1(JSOP_UNDEFINED))
6797         return false;
6798 
6799     // Enter the block before the loop body, after evaluating the obj.
6800     // Initialize let bindings with undefined when entering, as the name
6801     // assigned to is a plain assignment.
6802     TDZCheckCache tdzCache(this);
6803     Maybe<EmitterScope> emitterScope;
6804     if (lexicalScope) {
6805         emitterScope.emplace(this);
6806         if (!emitterScope->enterComprehensionFor(this, loopDecl->scopeBindings()))
6807             return false;
6808     }
6809 
6810     LoopControl loopInfo(this, StatementKind::ForInLoop);
6811 
6812     /* Annotate so IonMonkey can find the loop-closing jump. */
6813     unsigned noteIndex;
6814     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
6815         return false;
6816 
6817     /*
6818      * Jump down to the loop condition to minimize overhead assuming at
6819      * least one iteration, as the other loop forms do.
6820      */
6821     JumpList jmp;
6822     if (!emitJump(JSOP_GOTO, &jmp))
6823         return false;
6824 
6825     JumpTarget top{ -1 };
6826     if (!emitLoopHead(nullptr, &top))
6827         return false;
6828 
6829 #ifdef DEBUG
6830     int loopDepth = this->stackDepth;
6831 #endif
6832 
6833     // Emit code to assign the enumeration value to the left hand side, but
6834     // also leave it on the stack.
6835     if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr))
6836         return false;
6837 
6838     /* The stack should be balanced around the assignment opcode sequence. */
6839     MOZ_ASSERT(this->stackDepth == loopDepth);
6840 
6841     /* Emit code for the loop body. */
6842     if (!emitTree(forBody))
6843         return false;
6844 
6845     // Set offset for continues.
6846     loopInfo.continueTarget = { offset() };
6847 
6848     if (!emitLoopEntry(nullptr, jmp))
6849         return false;
6850     if (!emit1(JSOP_POP))
6851         return false;
6852     if (!emit1(JSOP_MOREITER))
6853         return false;
6854     if (!emit1(JSOP_ISNOITER))
6855         return false;
6856     JumpList beq;
6857     JumpTarget breakTarget{ -1 };
6858     if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
6859         return false;
6860 
6861     /* Set the srcnote offset so we can find the closing jump. */
6862     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
6863         return false;
6864 
6865     if (!loopInfo.patchBreaksAndContinues(this))
6866         return false;
6867 
6868     // Pop the enumeration value.
6869     if (!emit1(JSOP_POP))
6870         return false;
6871 
6872     JumpTarget endIter{ offset() };
6873     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, endIter.offset))
6874         return false;
6875     if (!emit1(JSOP_ENDITER))
6876         return false;
6877 
6878     if (emitterScope) {
6879         if (!emitterScope->leave(this))
6880             return false;
6881         emitterScope.reset();
6882     }
6883 
6884     return true;
6885 }
6886 
6887 bool
emitComprehensionFor(ParseNode * compFor)6888 BytecodeEmitter::emitComprehensionFor(ParseNode* compFor)
6889 {
6890     MOZ_ASSERT(compFor->pn_left->isKind(PNK_FORIN) ||
6891                compFor->pn_left->isKind(PNK_FOROF));
6892 
6893     if (!updateLineNumberNotes(compFor->pn_pos.begin))
6894         return false;
6895 
6896     return compFor->pn_left->isKind(PNK_FORIN)
6897            ? emitComprehensionForIn(compFor)
6898            : emitComprehensionForOf(compFor);
6899 }
6900 
6901 MOZ_NEVER_INLINE bool
emitFunction(ParseNode * pn,bool needsProto)6902 BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
6903 {
6904     FunctionBox* funbox = pn->pn_funbox;
6905     RootedFunction fun(cx, funbox->function());
6906     RootedAtom name(cx, fun->name());
6907     MOZ_ASSERT_IF(fun->isInterpretedLazy(), fun->lazyScript());
6908     MOZ_ASSERT_IF(pn->isOp(JSOP_FUNWITHPROTO), needsProto);
6909 
6910     /*
6911      * Set the |wasEmitted| flag in the funbox once the function has been
6912      * emitted. Function definitions that need hoisting to the top of the
6913      * function will be seen by emitFunction in two places.
6914      */
6915     if (funbox->wasEmitted && pn->functionIsHoisted()) {
6916         // Annex B block-scoped functions are hoisted like any other
6917         // block-scoped function to the top of their scope. When their
6918         // definitions are seen for the second time, we need to emit the
6919         // assignment that assigns the function to the outer 'var' binding.
6920         if (funbox->isAnnexB) {
6921             auto emitRhs = [&name](BytecodeEmitter* bce, const NameLocation&, bool) {
6922                 // The RHS is the value of the lexically bound name in the
6923                 // innermost scope.
6924                 return bce->emitGetName(name);
6925             };
6926 
6927             // Get the location of the 'var' binding in the body scope. The
6928             // name must be found, else there is a bug in the Annex B handling
6929             // in Parser.
6930             //
6931             // In sloppy eval contexts, this location is dynamic.
6932             Maybe<NameLocation> lhsLoc = locationOfNameBoundInScope(name, varEmitterScope);
6933 
6934             // If there are parameter expressions, the var name could be a
6935             // parameter.
6936             if (!lhsLoc && sc->isFunctionBox() && sc->asFunctionBox()->hasExtraBodyVarScope())
6937                 lhsLoc = locationOfNameBoundInScope(name, varEmitterScope->enclosingInFrame());
6938 
6939             if (!lhsLoc) {
6940                 lhsLoc = Some(NameLocation::DynamicAnnexBVar());
6941             } else {
6942                 MOZ_ASSERT(lhsLoc->bindingKind() == BindingKind::Var ||
6943                            lhsLoc->bindingKind() == BindingKind::FormalParameter ||
6944                            (lhsLoc->bindingKind() == BindingKind::Let &&
6945                             sc->asFunctionBox()->hasParameterExprs));
6946             }
6947 
6948             if (!emitSetOrInitializeNameAtLocation(name, *lhsLoc, emitRhs, false))
6949                 return false;
6950             if (!emit1(JSOP_POP))
6951                 return false;
6952         }
6953 
6954         MOZ_ASSERT_IF(fun->hasScript(), fun->nonLazyScript());
6955         MOZ_ASSERT(pn->functionIsHoisted());
6956         return true;
6957     }
6958 
6959     funbox->wasEmitted = true;
6960 
6961     /*
6962      * Mark as singletons any function which will only be executed once, or
6963      * which is inner to a lambda we only expect to run once. In the latter
6964      * case, if the lambda runs multiple times then CloneFunctionObject will
6965      * make a deep clone of its contents.
6966      */
6967     if (fun->isInterpreted()) {
6968         bool singleton = checkRunOnceContext();
6969         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
6970             return false;
6971 
6972         SharedContext* outersc = sc;
6973         if (fun->isInterpretedLazy()) {
6974             // We need to update the static scope chain regardless of whether
6975             // the LazyScript has already been initialized, due to the case
6976             // where we previously successfully compiled an inner function's
6977             // lazy script but failed to compile the outer script after the
6978             // fact. If we attempt to compile the outer script again, the
6979             // static scope chain will be newly allocated and will mismatch
6980             // the previously compiled LazyScript's.
6981             ScriptSourceObject* source = &script->sourceObject()->as<ScriptSourceObject>();
6982             fun->lazyScript()->setEnclosingScopeAndSource(innermostScope(), source);
6983             if (emittingRunOnceLambda)
6984                 fun->lazyScript()->setTreatAsRunOnce();
6985         } else {
6986             MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
6987 
6988             // Inherit most things (principals, version, etc) from the
6989             // parent.  Use default values for the rest.
6990             Rooted<JSScript*> parent(cx, script);
6991             MOZ_ASSERT(parent->getVersion() == parser->options().version);
6992             MOZ_ASSERT(parent->mutedErrors() == parser->options().mutedErrors());
6993             const TransitiveCompileOptions& transitiveOptions = parser->options();
6994             CompileOptions options(cx, transitiveOptions);
6995 
6996             Rooted<JSObject*> sourceObject(cx, script->sourceObject());
6997             Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
6998                                                           funbox->bufStart, funbox->bufEnd));
6999             if (!script)
7000                 return false;
7001 
7002             BytecodeEmitter bce2(this, parser, funbox, script, /* lazyScript = */ nullptr,
7003                                  pn->pn_pos, emitterMode);
7004             if (!bce2.init())
7005                 return false;
7006 
7007             /* We measured the max scope depth when we parsed the function. */
7008             if (!bce2.emitFunctionScript(pn->pn_body))
7009                 return false;
7010 
7011             if (funbox->isLikelyConstructorWrapper())
7012                 script->setLikelyConstructorWrapper();
7013         }
7014 
7015         if (outersc->isFunctionBox())
7016             outersc->asFunctionBox()->setHasInnerFunctions();
7017     } else {
7018         MOZ_ASSERT(IsAsmJSModule(fun));
7019     }
7020 
7021     /* Make the function object a literal in the outer script's pool. */
7022     unsigned index = objectList.add(pn->pn_funbox);
7023 
7024     /* Non-hoisted functions simply emit their respective op. */
7025     if (!pn->functionIsHoisted()) {
7026         /* JSOP_LAMBDA_ARROW is always preceded by a new.target */
7027         MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW));
7028         if (funbox->isAsync()) {
7029             MOZ_ASSERT(!needsProto);
7030             return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow());
7031         }
7032 
7033         if (fun->isArrow()) {
7034             if (sc->allowNewTarget()) {
7035                 if (!emit1(JSOP_NEWTARGET))
7036                     return false;
7037             } else {
7038                 if (!emit1(JSOP_NULL))
7039                     return false;
7040             }
7041         }
7042 
7043         if (needsProto) {
7044             MOZ_ASSERT(pn->getOp() == JSOP_FUNWITHPROTO || pn->getOp() == JSOP_LAMBDA);
7045             pn->setOp(JSOP_FUNWITHPROTO);
7046         }
7047 
7048         if (pn->getOp() == JSOP_DEFFUN) {
7049             if (!emitIndex32(JSOP_LAMBDA, index))
7050                 return false;
7051             return emit1(JSOP_DEFFUN);
7052         }
7053 
7054         return emitIndex32(pn->getOp(), index);
7055     }
7056 
7057     MOZ_ASSERT(!needsProto);
7058 
7059     bool topLevelFunction;
7060     if (sc->isFunctionBox() || (sc->isEvalContext() && sc->strict())) {
7061         // No nested functions inside other functions are top-level.
7062         topLevelFunction = false;
7063     } else {
7064         // In sloppy eval scripts, top-level functions in are accessed
7065         // dynamically. In global and module scripts, top-level functions are
7066         // those bound in the var scope.
7067         NameLocation loc = lookupName(name);
7068         topLevelFunction = loc.kind() == NameLocation::Kind::Dynamic ||
7069                            loc.bindingKind() == BindingKind::Var;
7070     }
7071 
7072     if (topLevelFunction) {
7073         if (sc->isModuleContext()) {
7074             // For modules, we record the function and instantiate the binding
7075             // during ModuleDeclarationInstantiation(), before the script is run.
7076 
7077             RootedModuleObject module(cx, sc->asModuleContext()->module());
7078             if (!module->noteFunctionDeclaration(cx, name, fun))
7079                 return false;
7080         } else {
7081             MOZ_ASSERT(sc->isGlobalContext() || sc->isEvalContext());
7082             MOZ_ASSERT(pn->getOp() == JSOP_NOP);
7083             switchToPrologue();
7084             if (funbox->isAsync()) {
7085                 if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow()))
7086                     return false;
7087             } else {
7088                 if (!emitIndex32(JSOP_LAMBDA, index))
7089                     return false;
7090             }
7091             if (!emit1(JSOP_DEFFUN))
7092                 return false;
7093             if (!updateSourceCoordNotes(pn->pn_pos.begin))
7094                 return false;
7095             switchToMain();
7096         }
7097     } else {
7098         // For functions nested within functions and blocks, make a lambda and
7099         // initialize the binding name of the function in the current scope.
7100 
7101         bool isAsync = funbox->isAsync();
7102         auto emitLambda = [index, isAsync](BytecodeEmitter* bce, const NameLocation&, bool) {
7103             if (isAsync) {
7104                 return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false,
7105                                              /* isArrow = */ false);
7106             }
7107             return bce->emitIndexOp(JSOP_LAMBDA, index);
7108         };
7109 
7110         if (!emitInitializeName(name, emitLambda))
7111             return false;
7112         if (!emit1(JSOP_POP))
7113             return false;
7114     }
7115 
7116     return true;
7117 }
7118 
7119 bool
emitAsyncWrapperLambda(unsigned index,bool isArrow)7120 BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) {
7121     if (isArrow) {
7122         if (sc->allowNewTarget()) {
7123             if (!emit1(JSOP_NEWTARGET))
7124                 return false;
7125         } else {
7126             if (!emit1(JSOP_NULL))
7127                 return false;
7128         }
7129         if (!emitIndex32(JSOP_LAMBDA_ARROW, index))
7130             return false;
7131     } else {
7132         if (!emitIndex32(JSOP_LAMBDA, index))
7133             return false;
7134     }
7135 
7136     return true;
7137 }
7138 
7139 bool
emitAsyncWrapper(unsigned index,bool needsHomeObject,bool isArrow)7140 BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow)
7141 {
7142     // needsHomeObject can be true for propertyList for extended class.
7143     // In that case push both unwrapped and wrapped function, in order to
7144     // initialize home object of unwrapped function, and set wrapped function
7145     // as a property.
7146     //
7147     //   lambda       // unwrapped
7148     //   dup          // unwrapped unwrapped
7149     //   toasync      // unwrapped wrapped
7150     //
7151     // Emitted code is surrounded by the following code.
7152     //
7153     //                    // classObj classCtor classProto
7154     //   (emitted code)   // classObj classCtor classProto unwrapped wrapped
7155     //   swap             // classObj classCtor classProto wrapped unwrapped
7156     //   inithomeobject 1 // classObj classCtor classProto wrapped unwrapped
7157     //                    //   initialize the home object of unwrapped
7158     //                    //   with classProto here
7159     //   pop              // classObj classCtor classProto wrapped
7160     //   inithiddenprop   // classObj classCtor classProto wrapped
7161     //                    //   initialize the property of the classProto
7162     //                    //   with wrapped function here
7163     //   pop              // classObj classCtor classProto
7164     //
7165     // needsHomeObject is false for other cases, push wrapped function only.
7166     if (!emitAsyncWrapperLambda(index, isArrow))
7167         return false;
7168     if (needsHomeObject) {
7169         if (!emit1(JSOP_DUP))
7170             return false;
7171     }
7172     if (!emit1(JSOP_TOASYNC))
7173         return false;
7174     return true;
7175 }
7176 
7177 bool
emitDo(ParseNode * pn)7178 BytecodeEmitter::emitDo(ParseNode* pn)
7179 {
7180     /* Emit an annotated nop so IonBuilder can recognize the 'do' loop. */
7181     unsigned noteIndex;
7182     if (!newSrcNote(SRC_WHILE, &noteIndex))
7183         return false;
7184     if (!emit1(JSOP_NOP))
7185         return false;
7186 
7187     unsigned noteIndex2;
7188     if (!newSrcNote(SRC_WHILE, &noteIndex2))
7189         return false;
7190 
7191     /* Compile the loop body. */
7192     JumpTarget top;
7193     if (!emitLoopHead(pn->pn_left, &top))
7194         return false;
7195 
7196     LoopControl loopInfo(this, StatementKind::DoLoop);
7197 
7198     JumpList empty;
7199     if (!emitLoopEntry(nullptr, empty))
7200         return false;
7201 
7202     if (!emitTree(pn->pn_left))
7203         return false;
7204 
7205     // Set the offset for continues.
7206     if (!emitJumpTarget(&loopInfo.continueTarget))
7207         return false;
7208 
7209     /* Compile the loop condition, now that continues know where to go. */
7210     if (!emitTree(pn->pn_right))
7211         return false;
7212 
7213     JumpList beq;
7214     JumpTarget breakTarget{ -1 };
7215     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
7216         return false;
7217 
7218     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
7219         return false;
7220 
7221     /*
7222      * Update the annotations with the update and back edge positions, for
7223      * IonBuilder.
7224      *
7225      * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
7226      * note gets bigger.
7227      */
7228     if (!setSrcNoteOffset(noteIndex2, 0, beq.offset - top.offset))
7229         return false;
7230     if (!setSrcNoteOffset(noteIndex, 0, 1 + (loopInfo.continueTarget.offset - top.offset)))
7231         return false;
7232 
7233     if (!loopInfo.patchBreaksAndContinues(this))
7234         return false;
7235 
7236     return true;
7237 }
7238 
7239 bool
emitWhile(ParseNode * pn)7240 BytecodeEmitter::emitWhile(ParseNode* pn)
7241 {
7242     /*
7243      * Minimize bytecodes issued for one or more iterations by jumping to
7244      * the condition below the body and closing the loop if the condition
7245      * is true with a backward branch. For iteration count i:
7246      *
7247      *  i    test at the top                 test at the bottom
7248      *  =    ===============                 ==================
7249      *  0    ifeq-pass                       goto; ifne-fail
7250      *  1    ifeq-fail; goto; ifne-pass      goto; ifne-pass; ifne-fail
7251      *  2    2*(ifeq-fail; goto); ifeq-pass  goto; 2*ifne-pass; ifne-fail
7252      *  . . .
7253      *  N    N*(ifeq-fail; goto); ifeq-pass  goto; N*ifne-pass; ifne-fail
7254      */
7255 
7256     // If we have a single-line while, like "while (x) ;", we want to
7257     // emit the line note before the initial goto, so that the
7258     // debugger sees a single entry point.  This way, if there is a
7259     // breakpoint on the line, it will only fire once; and "next"ing
7260     // will skip the whole loop.  However, for the multi-line case we
7261     // want to emit the line note after the initial goto, so that
7262     // "cont" stops on each iteration -- but without a stop before the
7263     // first iteration.
7264     if (parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin) ==
7265         parser->tokenStream.srcCoords.lineNum(pn->pn_pos.end) &&
7266         !updateSourceCoordNotes(pn->pn_pos.begin))
7267         return false;
7268 
7269     JumpTarget top{ -1 };
7270     if (!emitJumpTarget(&top))
7271         return false;
7272 
7273     LoopControl loopInfo(this, StatementKind::WhileLoop);
7274     loopInfo.continueTarget = top;
7275 
7276     unsigned noteIndex;
7277     if (!newSrcNote(SRC_WHILE, &noteIndex))
7278         return false;
7279 
7280     JumpList jmp;
7281     if (!emitJump(JSOP_GOTO, &jmp))
7282         return false;
7283 
7284     if (!emitLoopHead(pn->pn_right, &top))
7285         return false;
7286 
7287     if (!emitConditionallyExecutedTree(pn->pn_right))
7288         return false;
7289 
7290     if (!emitLoopEntry(pn->pn_left, jmp))
7291         return false;
7292     if (!emitTree(pn->pn_left))
7293         return false;
7294 
7295     JumpList beq;
7296     JumpTarget breakTarget{ -1 };
7297     if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
7298         return false;
7299 
7300     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
7301         return false;
7302 
7303     if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
7304         return false;
7305 
7306     if (!loopInfo.patchBreaksAndContinues(this))
7307         return false;
7308 
7309     return true;
7310 }
7311 
7312 bool
emitBreak(PropertyName * label)7313 BytecodeEmitter::emitBreak(PropertyName* label)
7314 {
7315     BreakableControl* target;
7316     SrcNoteType noteType;
7317     if (label) {
7318         // Any statement with the matching label may be the break target.
7319         auto hasSameLabel = [label](LabelControl* labelControl) {
7320             return labelControl->label() == label;
7321         };
7322         target = findInnermostNestableControl<LabelControl>(hasSameLabel);
7323         noteType = SRC_BREAK2LABEL;
7324     } else {
7325         auto isNotLabel = [](BreakableControl* control) {
7326             return !control->is<LabelControl>();
7327         };
7328         target = findInnermostNestableControl<BreakableControl>(isNotLabel);
7329         noteType = (target->kind() == StatementKind::Switch) ? SRC_SWITCHBREAK : SRC_BREAK;
7330     }
7331 
7332     return emitGoto(target, &target->breaks, noteType);
7333 }
7334 
7335 bool
emitContinue(PropertyName * label)7336 BytecodeEmitter::emitContinue(PropertyName* label)
7337 {
7338     LoopControl* target = nullptr;
7339     if (label) {
7340         // Find the loop statement enclosed by the matching label.
7341         NestableControl* control = innermostNestableControl;
7342         while (!control->is<LabelControl>() || control->as<LabelControl>().label() != label) {
7343             if (control->is<LoopControl>())
7344                 target = &control->as<LoopControl>();
7345             control = control->enclosing();
7346         }
7347     } else {
7348         target = findInnermostNestableControl<LoopControl>();
7349     }
7350     return emitGoto(target, &target->continues, SRC_CONTINUE);
7351 }
7352 
7353 bool
emitGetFunctionThis(ParseNode * pn)7354 BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
7355 {
7356     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
7357     MOZ_ASSERT(pn->isKind(PNK_NAME));
7358     MOZ_ASSERT(pn->name() == cx->names().dotThis);
7359 
7360     if (!emitTree(pn))
7361         return false;
7362     if (sc->needsThisTDZChecks() && !emit1(JSOP_CHECKTHIS))
7363         return false;
7364 
7365     return true;
7366 }
7367 
7368 bool
emitGetThisForSuperBase(ParseNode * pn)7369 BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn)
7370 {
7371     MOZ_ASSERT(pn->isKind(PNK_SUPERBASE));
7372     return emitGetFunctionThis(pn->pn_kid);
7373 }
7374 
7375 bool
emitThisLiteral(ParseNode * pn)7376 BytecodeEmitter::emitThisLiteral(ParseNode* pn)
7377 {
7378     MOZ_ASSERT(pn->isKind(PNK_THIS));
7379 
7380     if (ParseNode* thisName = pn->pn_kid)
7381         return emitGetFunctionThis(thisName);
7382 
7383     if (sc->thisBinding() == ThisBinding::Module)
7384         return emit1(JSOP_UNDEFINED);
7385 
7386     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
7387     return emit1(JSOP_GLOBALTHIS);
7388 }
7389 
7390 bool
emitCheckDerivedClassConstructorReturn()7391 BytecodeEmitter::emitCheckDerivedClassConstructorReturn()
7392 {
7393     MOZ_ASSERT(lookupName(cx->names().dotThis).hasKnownSlot());
7394     if (!emitGetName(cx->names().dotThis))
7395         return false;
7396     if (!emit1(JSOP_CHECKRETURN))
7397         return false;
7398     return true;
7399 }
7400 
7401 bool
emitReturn(ParseNode * pn)7402 BytecodeEmitter::emitReturn(ParseNode* pn)
7403 {
7404     if (!updateSourceCoordNotes(pn->pn_pos.begin))
7405         return false;
7406 
7407     if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
7408         if (!emitPrepareIteratorResult())
7409             return false;
7410     }
7411 
7412     /* Push a return value */
7413     if (ParseNode* pn2 = pn->pn_kid) {
7414         if (!emitTree(pn2))
7415             return false;
7416     } else {
7417         /* No explicit return value provided */
7418         if (!emit1(JSOP_UNDEFINED))
7419             return false;
7420     }
7421 
7422     if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
7423         if (!emitFinishIteratorResult(true))
7424             return false;
7425     }
7426 
7427     // We know functionBodyEndPos is set because "return" is only
7428     // valid in a function, and so we've passed through
7429     // emitFunctionScript.
7430     MOZ_ASSERT(functionBodyEndPosSet);
7431     if (!updateSourceCoordNotes(functionBodyEndPos))
7432         return false;
7433 
7434     /*
7435      * EmitNonLocalJumpFixup may add fixup bytecode to close open try
7436      * blocks having finally clauses and to exit intermingled let blocks.
7437      * We can't simply transfer control flow to our caller in that case,
7438      * because we must gosub to those finally clauses from inner to outer,
7439      * with the correct stack pointer (i.e., after popping any with,
7440      * for/in, etc., slots nested inside the finally's try).
7441      *
7442      * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
7443      * extra JSOP_RETRVAL after the fixups.
7444      */
7445     ptrdiff_t top = offset();
7446 
7447     bool isGenerator = sc->isFunctionBox() && sc->asFunctionBox()->isGenerator();
7448     bool isDerivedClassConstructor =
7449         sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
7450 
7451     if (!emit1((isGenerator || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
7452         return false;
7453 
7454     // Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
7455     // to ensure that the error is thrown while the scope-chain is still intact.
7456     if (isDerivedClassConstructor) {
7457         if (!emitCheckDerivedClassConstructorReturn())
7458             return false;
7459     }
7460 
7461     NonLocalExitControl nle(this);
7462 
7463     if (!nle.prepareForNonLocalJumpToOutermost())
7464         return false;
7465 
7466     if (isGenerator) {
7467         // We know that .generator is on the function scope, as we just exited
7468         // all nested scopes.
7469         NameLocation loc =
7470             *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, varEmitterScope);
7471         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
7472             return false;
7473         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
7474             return false;
7475     } else if (isDerivedClassConstructor) {
7476         MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
7477         if (!emit1(JSOP_RETRVAL))
7478             return false;
7479     } else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
7480         code()[top] = JSOP_SETRVAL;
7481         if (!emit1(JSOP_RETRVAL))
7482             return false;
7483     }
7484 
7485     return true;
7486 }
7487 
7488 bool
emitYield(ParseNode * pn)7489 BytecodeEmitter::emitYield(ParseNode* pn)
7490 {
7491     MOZ_ASSERT(sc->isFunctionBox());
7492 
7493     if (pn->getOp() == JSOP_YIELD) {
7494         if (sc->asFunctionBox()->isStarGenerator()) {
7495             if (!emitPrepareIteratorResult())
7496                 return false;
7497         }
7498         if (pn->pn_left) {
7499             if (!emitTree(pn->pn_left))
7500                 return false;
7501         } else {
7502             if (!emit1(JSOP_UNDEFINED))
7503                 return false;
7504         }
7505         if (sc->asFunctionBox()->isStarGenerator()) {
7506             if (!emitFinishIteratorResult(false))
7507                 return false;
7508         }
7509     } else {
7510         MOZ_ASSERT(pn->getOp() == JSOP_INITIALYIELD);
7511     }
7512 
7513     if (!emitTree(pn->pn_right))
7514         return false;
7515 
7516     if (!emitYieldOp(pn->getOp()))
7517         return false;
7518 
7519     if (pn->getOp() == JSOP_INITIALYIELD && !emit1(JSOP_POP))
7520         return false;
7521 
7522     return true;
7523 }
7524 
7525 bool
emitYieldStar(ParseNode * iter,ParseNode * gen)7526 BytecodeEmitter::emitYieldStar(ParseNode* iter, ParseNode* gen)
7527 {
7528     MOZ_ASSERT(sc->isFunctionBox());
7529     MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator());
7530 
7531     if (!emitTree(iter))                                         // ITERABLE
7532         return false;
7533     if (!emitIterator())                                         // ITER
7534         return false;
7535 
7536     // Initial send value is undefined.
7537     if (!emit1(JSOP_UNDEFINED))                                  // ITER RECEIVED
7538         return false;
7539 
7540     int depth = stackDepth;
7541     MOZ_ASSERT(depth >= 2);
7542 
7543     JumpList send;
7544     if (!emitJump(JSOP_GOTO, &send))                             // goto send
7545         return false;
7546 
7547     // Try prologue.                                             // ITER RESULT
7548     unsigned noteIndex;
7549     if (!newSrcNote(SRC_TRY, &noteIndex))
7550         return false;
7551     JumpTarget tryStart{ offset() };
7552     if (!emit1(JSOP_TRY))                                        // tryStart:
7553         return false;
7554     MOZ_ASSERT(this->stackDepth == depth);
7555 
7556     // Load the generator object.
7557     if (!emitTree(gen))                                          // ITER RESULT GENOBJ
7558         return false;
7559 
7560     // Yield RESULT as-is, without re-boxing.
7561     if (!emitYieldOp(JSOP_YIELD))                                // ITER RECEIVED
7562         return false;
7563 
7564     // Try epilogue.
7565     if (!setSrcNoteOffset(noteIndex, 0, offset() - tryStart.offset))
7566         return false;
7567     if (!emitJump(JSOP_GOTO, &send))                             // goto send
7568         return false;
7569 
7570     JumpTarget tryEnd;
7571     if (!emitJumpTarget(&tryEnd))                                // tryEnd:
7572         return false;
7573 
7574     // Catch location.
7575     stackDepth = uint32_t(depth);                                // ITER RESULT
7576     if (!emit1(JSOP_POP))                                        // ITER
7577         return false;
7578     // THROW? = 'throw' in ITER
7579     if (!emit1(JSOP_EXCEPTION))                                  // ITER EXCEPTION
7580         return false;
7581     if (!emit1(JSOP_SWAP))                                       // EXCEPTION ITER
7582         return false;
7583     if (!emit1(JSOP_DUP))                                        // EXCEPTION ITER ITER
7584         return false;
7585     if (!emitAtomOp(cx->names().throw_, JSOP_STRING))            // EXCEPTION ITER ITER "throw"
7586         return false;
7587     if (!emit1(JSOP_SWAP))                                       // EXCEPTION ITER "throw" ITER
7588         return false;
7589     if (!emit1(JSOP_IN))                                         // EXCEPTION ITER THROW?
7590         return false;
7591     // if (THROW?) goto delegate
7592     JumpList checkThrow;
7593     if (!emitJump(JSOP_IFNE, &checkThrow))                       // EXCEPTION ITER
7594         return false;
7595     if (!emit1(JSOP_POP))                                        // EXCEPTION
7596         return false;
7597     if (!emit1(JSOP_THROW))                                      // throw EXCEPTION
7598         return false;
7599 
7600     if (!emitJumpTargetAndPatch(checkThrow))                     // delegate:
7601         return false;
7602     // RESULT = ITER.throw(EXCEPTION)                            // EXCEPTION ITER
7603     stackDepth = uint32_t(depth);
7604     if (!emit1(JSOP_DUP))                                        // EXCEPTION ITER ITER
7605         return false;
7606     if (!emit1(JSOP_DUP))                                        // EXCEPTION ITER ITER ITER
7607         return false;
7608     if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP))          // EXCEPTION ITER ITER THROW
7609         return false;
7610     if (!emit1(JSOP_SWAP))                                       // EXCEPTION ITER THROW ITER
7611         return false;
7612     if (!emit2(JSOP_PICK, 3))                                    // ITER THROW ITER EXCEPTION
7613         return false;
7614     if (!emitCall(JSOP_CALL, 1, iter))                           // ITER RESULT
7615         return false;
7616     checkTypeSet(JSOP_CALL);
7617     MOZ_ASSERT(this->stackDepth == depth);
7618     JumpList checkResult;
7619     if (!emitJump(JSOP_GOTO, &checkResult))                      // goto checkResult
7620         return false;
7621 
7622     // Catch epilogue.
7623 
7624     // This is a peace offering to ReconstructPCStack.  See the note in EmitTry.
7625     if (!emit1(JSOP_NOP))
7626         return false;
7627     if (!tryNoteList.append(JSTRY_CATCH, depth, tryStart.offset + JSOP_TRY_LENGTH, tryEnd.offset))
7628         return false;
7629 
7630     // After the try/catch block: send the received value to the iterator.
7631     if (!emitJumpTargetAndPatch(send))                           // send:
7632         return false;
7633 
7634     // Send location.
7635     // result = iter.next(received)                              // ITER RECEIVED
7636     if (!emit1(JSOP_SWAP))                                       // RECEIVED ITER
7637         return false;
7638     if (!emit1(JSOP_DUP))                                        // RECEIVED ITER ITER
7639         return false;
7640     if (!emit1(JSOP_DUP))                                        // RECEIVED ITER ITER ITER
7641         return false;
7642     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))            // RECEIVED ITER ITER NEXT
7643         return false;
7644     if (!emit1(JSOP_SWAP))                                       // RECEIVED ITER NEXT ITER
7645         return false;
7646     if (!emit2(JSOP_PICK, 3))                                    // ITER NEXT ITER RECEIVED
7647         return false;
7648     if (!emitCall(JSOP_CALL, 1, iter))                           // ITER RESULT
7649         return false;
7650     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext))        // ITER RESULT
7651         return false;
7652     checkTypeSet(JSOP_CALL);
7653     MOZ_ASSERT(this->stackDepth == depth);
7654 
7655     if (!emitJumpTargetAndPatch(checkResult))                    // checkResult:
7656         return false;
7657 
7658     // if (!result.done) goto tryStart;                          // ITER RESULT
7659     if (!emit1(JSOP_DUP))                                        // ITER RESULT RESULT
7660         return false;
7661     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))             // ITER RESULT DONE
7662         return false;
7663     // if (!DONE) goto tryStart;
7664     JumpList beq;
7665     JumpTarget breakTarget{ -1 };
7666     if (!emitBackwardJump(JSOP_IFEQ, tryStart, &beq, &breakTarget)) // ITER RESULT
7667         return false;
7668 
7669     // result.value
7670     if (!emit1(JSOP_SWAP))                                       // RESULT ITER
7671         return false;
7672     if (!emit1(JSOP_POP))                                        // RESULT
7673         return false;
7674     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))            // VALUE
7675         return false;
7676 
7677     MOZ_ASSERT(this->stackDepth == depth - 1);
7678 
7679     return true;
7680 }
7681 
7682 bool
emitStatementList(ParseNode * pn)7683 BytecodeEmitter::emitStatementList(ParseNode* pn)
7684 {
7685     MOZ_ASSERT(pn->isArity(PN_LIST));
7686     for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
7687         if (!emitTree(pn2))
7688             return false;
7689     }
7690     return true;
7691 }
7692 
7693 bool
emitStatement(ParseNode * pn)7694 BytecodeEmitter::emitStatement(ParseNode* pn)
7695 {
7696     MOZ_ASSERT(pn->isKind(PNK_SEMI));
7697 
7698     ParseNode* pn2 = pn->pn_kid;
7699     if (!pn2)
7700         return true;
7701 
7702     if (!updateSourceCoordNotes(pn->pn_pos.begin))
7703         return false;
7704 
7705     /*
7706      * Top-level or called-from-a-native JS_Execute/EvaluateScript,
7707      * debugger, and eval frames may need the value of the ultimate
7708      * expression statement as the script's result, despite the fact
7709      * that it appears useless to the compiler.
7710      *
7711      * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
7712      * calling JS_Compile* to suppress JSOP_SETRVAL.
7713      */
7714     bool wantval = false;
7715     bool useful = false;
7716     if (sc->isFunctionBox())
7717         MOZ_ASSERT(!script->noScriptRval());
7718     else
7719         useful = wantval = !script->noScriptRval();
7720 
7721     /* Don't eliminate expressions with side effects. */
7722     if (!useful) {
7723         if (!checkSideEffects(pn2, &useful))
7724             return false;
7725 
7726         /*
7727          * Don't eliminate apparently useless expressions if they are labeled
7728          * expression statements. The startOffset() test catches the case
7729          * where we are nesting in emitTree for a labeled compound statement.
7730          */
7731         if (innermostNestableControl &&
7732             innermostNestableControl->is<LabelControl>() &&
7733             innermostNestableControl->as<LabelControl>().startOffset() >= offset())
7734         {
7735             useful = true;
7736         }
7737     }
7738 
7739     if (useful) {
7740         JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
7741         MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
7742         if (!emitTree(pn2))
7743             return false;
7744         if (!emit1(op))
7745             return false;
7746     } else if (pn->isDirectivePrologueMember()) {
7747         // Don't complain about directive prologue members; just don't emit
7748         // their code.
7749     } else {
7750         if (JSAtom* atom = pn->isStringExprStatement()) {
7751             // Warn if encountering a non-directive prologue member string
7752             // expression statement, that is inconsistent with the current
7753             // directive prologue.  That is, a script *not* starting with
7754             // "use strict" should warn for any "use strict" statements seen
7755             // later in the script, because such statements are misleading.
7756             const char* directive = nullptr;
7757             if (atom == cx->names().useStrict) {
7758                 if (!sc->strictScript)
7759                     directive = js_useStrict_str;
7760             } else if (atom == cx->names().useAsm) {
7761                 if (sc->isFunctionBox()) {
7762                     if (IsAsmJSModule(sc->asFunctionBox()->function()))
7763                         directive = js_useAsm_str;
7764                 }
7765             }
7766 
7767             if (directive) {
7768                 if (!reportStrictWarning(pn2, JSMSG_CONTRARY_NONDIRECTIVE, directive))
7769                     return false;
7770             }
7771         } else {
7772             current->currentLine = parser->tokenStream.srcCoords.lineNum(pn2->pn_pos.begin);
7773             current->lastColumn = 0;
7774             if (!reportStrictWarning(pn2, JSMSG_USELESS_EXPR))
7775                 return false;
7776         }
7777     }
7778 
7779     return true;
7780 }
7781 
7782 bool
emitDeleteName(ParseNode * node)7783 BytecodeEmitter::emitDeleteName(ParseNode* node)
7784 {
7785     MOZ_ASSERT(node->isKind(PNK_DELETENAME));
7786     MOZ_ASSERT(node->isArity(PN_UNARY));
7787 
7788     ParseNode* nameExpr = node->pn_kid;
7789     MOZ_ASSERT(nameExpr->isKind(PNK_NAME));
7790 
7791     return emitAtomOp(nameExpr, JSOP_DELNAME);
7792 }
7793 
7794 bool
emitDeleteProperty(ParseNode * node)7795 BytecodeEmitter::emitDeleteProperty(ParseNode* node)
7796 {
7797     MOZ_ASSERT(node->isKind(PNK_DELETEPROP));
7798     MOZ_ASSERT(node->isArity(PN_UNARY));
7799 
7800     ParseNode* propExpr = node->pn_kid;
7801     MOZ_ASSERT(propExpr->isKind(PNK_DOT));
7802 
7803     if (propExpr->as<PropertyAccess>().isSuper()) {
7804         // Still have to calculate the base, even though we are are going
7805         // to throw unconditionally, as calculating the base could also
7806         // throw.
7807         if (!emit1(JSOP_SUPERBASE))
7808             return false;
7809 
7810         return emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER);
7811     }
7812 
7813     JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
7814     return emitPropOp(propExpr, delOp);
7815 }
7816 
7817 bool
emitDeleteElement(ParseNode * node)7818 BytecodeEmitter::emitDeleteElement(ParseNode* node)
7819 {
7820     MOZ_ASSERT(node->isKind(PNK_DELETEELEM));
7821     MOZ_ASSERT(node->isArity(PN_UNARY));
7822 
7823     ParseNode* elemExpr = node->pn_kid;
7824     MOZ_ASSERT(elemExpr->isKind(PNK_ELEM));
7825 
7826     if (elemExpr->as<PropertyByValue>().isSuper()) {
7827         // Still have to calculate everything, even though we're gonna throw
7828         // since it may have side effects
7829         if (!emitTree(elemExpr->pn_right))
7830             return false;
7831 
7832         if (!emit1(JSOP_SUPERBASE))
7833             return false;
7834         if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_CANT_DELETE_SUPER))
7835             return false;
7836 
7837         // Another wrinkle: Balance the stack from the emitter's point of view.
7838         // Execution will not reach here, as the last bytecode threw.
7839         return emit1(JSOP_POP);
7840     }
7841 
7842     JSOp delOp = sc->strict() ? JSOP_STRICTDELELEM : JSOP_DELELEM;
7843     return emitElemOp(elemExpr, delOp);
7844 }
7845 
7846 bool
emitDeleteExpression(ParseNode * node)7847 BytecodeEmitter::emitDeleteExpression(ParseNode* node)
7848 {
7849     MOZ_ASSERT(node->isKind(PNK_DELETEEXPR));
7850     MOZ_ASSERT(node->isArity(PN_UNARY));
7851 
7852     ParseNode* expression = node->pn_kid;
7853 
7854     // If useless, just emit JSOP_TRUE; otherwise convert |delete <expr>| to
7855     // effectively |<expr>, true|.
7856     bool useful = false;
7857     if (!checkSideEffects(expression, &useful))
7858         return false;
7859 
7860     if (useful) {
7861         if (!emitTree(expression))
7862             return false;
7863         if (!emit1(JSOP_POP))
7864             return false;
7865     }
7866 
7867     return emit1(JSOP_TRUE);
7868 }
7869 
7870 static const char *
SelfHostedCallFunctionName(JSAtom * name,ExclusiveContext * cx)7871 SelfHostedCallFunctionName(JSAtom* name, ExclusiveContext* cx)
7872 {
7873     if (name == cx->names().callFunction)
7874         return "callFunction";
7875     if (name == cx->names().callContentFunction)
7876         return "callContentFunction";
7877     if (name == cx->names().constructContentFunction)
7878         return "constructContentFunction";
7879 
7880     MOZ_CRASH("Unknown self-hosted call function name");
7881 }
7882 
7883 bool
emitSelfHostedCallFunction(ParseNode * pn)7884 BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
7885 {
7886     // Special-casing of callFunction to emit bytecode that directly
7887     // invokes the callee with the correct |this| object and arguments.
7888     // callFunction(fun, thisArg, arg0, arg1) thus becomes:
7889     // - emit lookup for fun
7890     // - emit lookup for thisArg
7891     // - emit lookups for arg0, arg1
7892     //
7893     // argc is set to the amount of actually emitted args and the
7894     // emitting of args below is disabled by setting emitArgs to false.
7895     ParseNode* pn2 = pn->pn_head;
7896     const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
7897 
7898     if (pn->pn_count < 3) {
7899         reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
7900         return false;
7901     }
7902 
7903     JSOp callOp = pn->getOp();
7904     if (callOp != JSOP_CALL) {
7905         reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
7906         return false;
7907     }
7908 
7909     bool constructing = pn2->name() == cx->names().constructContentFunction;
7910     ParseNode* funNode = pn2->pn_next;
7911     if (constructing)
7912         callOp = JSOP_NEW;
7913     else if (funNode->getKind() == PNK_NAME && funNode->name() == cx->names().std_Function_apply)
7914         callOp = JSOP_FUNAPPLY;
7915 
7916     if (!emitTree(funNode))
7917         return false;
7918 
7919 #ifdef DEBUG
7920     if (emitterMode == BytecodeEmitter::SelfHosting &&
7921         pn2->name() == cx->names().callFunction)
7922     {
7923         if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
7924             return false;
7925     }
7926 #endif
7927 
7928     ParseNode* thisOrNewTarget = funNode->pn_next;
7929     if (constructing) {
7930         // Save off the new.target value, but here emit a proper |this| for a
7931         // constructing call.
7932         if (!emit1(JSOP_IS_CONSTRUCTING))
7933             return false;
7934     } else {
7935         // It's |this|, emit it.
7936         if (!emitTree(thisOrNewTarget))
7937             return false;
7938     }
7939 
7940     for (ParseNode* argpn = thisOrNewTarget->pn_next; argpn; argpn = argpn->pn_next) {
7941         if (!emitTree(argpn))
7942             return false;
7943     }
7944 
7945     if (constructing) {
7946         if (!emitTree(thisOrNewTarget))
7947             return false;
7948     }
7949 
7950     uint32_t argc = pn->pn_count - 3;
7951     if (!emitCall(callOp, argc))
7952         return false;
7953 
7954     checkTypeSet(callOp);
7955     return true;
7956 }
7957 
7958 bool
emitSelfHostedResumeGenerator(ParseNode * pn)7959 BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
7960 {
7961     // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close')
7962     if (pn->pn_count != 4) {
7963         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
7964         return false;
7965     }
7966 
7967     ParseNode* funNode = pn->pn_head;  // The resumeGenerator node.
7968 
7969     ParseNode* genNode = funNode->pn_next;
7970     if (!emitTree(genNode))
7971         return false;
7972 
7973     ParseNode* valNode = genNode->pn_next;
7974     if (!emitTree(valNode))
7975         return false;
7976 
7977     ParseNode* kindNode = valNode->pn_next;
7978     MOZ_ASSERT(kindNode->isKind(PNK_STRING));
7979     uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
7980     MOZ_ASSERT(!kindNode->pn_next);
7981 
7982     if (!emitCall(JSOP_RESUME, operand))
7983         return false;
7984 
7985     return true;
7986 }
7987 
7988 bool
emitSelfHostedForceInterpreter(ParseNode * pn)7989 BytecodeEmitter::emitSelfHostedForceInterpreter(ParseNode* pn)
7990 {
7991     if (!emit1(JSOP_FORCEINTERPRETER))
7992         return false;
7993     if (!emit1(JSOP_UNDEFINED))
7994         return false;
7995     return true;
7996 }
7997 
7998 bool
emitSelfHostedAllowContentSpread(ParseNode * pn)7999 BytecodeEmitter::emitSelfHostedAllowContentSpread(ParseNode* pn)
8000 {
8001     if (pn->pn_count != 2) {
8002         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentSpread", "1", "");
8003         return false;
8004     }
8005 
8006     // We're just here as a sentinel. Pass the value through directly.
8007     return emitTree(pn->pn_head->pn_next);
8008 }
8009 
8010 bool
isRestParameter(ParseNode * pn,bool * result)8011 BytecodeEmitter::isRestParameter(ParseNode* pn, bool* result)
8012 {
8013     if (!sc->isFunctionBox()) {
8014         *result = false;
8015         return true;
8016     }
8017 
8018     FunctionBox* funbox = sc->asFunctionBox();
8019     RootedFunction fun(cx, funbox->function());
8020     if (!fun->hasRest()) {
8021         *result = false;
8022         return true;
8023     }
8024 
8025     if (!pn->isKind(PNK_NAME)) {
8026         if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) {
8027             ParseNode* pn2 = pn->pn_head;
8028             if (pn2->getKind() == PNK_NAME && pn2->name() == cx->names().allowContentSpread)
8029                 return isRestParameter(pn2->pn_next, result);
8030         }
8031         *result = false;
8032         return true;
8033     }
8034 
8035     JSAtom* name = pn->name();
8036     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
8037     if (paramLoc && lookupName(name) == *paramLoc) {
8038         FunctionScope::Data* bindings = funbox->functionScopeBindings();
8039         if (bindings->nonPositionalFormalStart > 0) {
8040             // |paramName| can be nullptr when the rest destructuring syntax is
8041             // used: `function f(...[]) {}`.
8042             JSAtom* paramName = bindings->names[bindings->nonPositionalFormalStart - 1].name();
8043             *result = paramName && name == paramName;
8044             return true;
8045         }
8046     }
8047 
8048     return true;
8049 }
8050 
8051 bool
emitOptimizeSpread(ParseNode * arg0,JumpList * jmp,bool * emitted)8052 BytecodeEmitter::emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitted)
8053 {
8054     // Emit a pereparation code to optimize the spread call with a rest
8055     // parameter:
8056     //
8057     //   function f(...args) {
8058     //     g(...args);
8059     //   }
8060     //
8061     // If the spread operand is a rest parameter and it's optimizable array,
8062     // skip spread operation and pass it directly to spread call operation.
8063     // See the comment in OptimizeSpreadCall in Interpreter.cpp for the
8064     // optimizable conditons.
8065     bool result = false;
8066     if (!isRestParameter(arg0, &result))
8067         return false;
8068 
8069     if (!result) {
8070         *emitted = false;
8071         return true;
8072     }
8073 
8074     if (!emitTree(arg0))
8075         return false;
8076 
8077     if (!emit1(JSOP_OPTIMIZE_SPREADCALL))
8078         return false;
8079 
8080     if (!emitJump(JSOP_IFNE, jmp))
8081         return false;
8082 
8083     if (!emit1(JSOP_POP))
8084         return false;
8085 
8086     *emitted = true;
8087     return true;
8088 }
8089 
8090 bool
emitCallOrNew(ParseNode * pn)8091 BytecodeEmitter::emitCallOrNew(ParseNode* pn)
8092 {
8093     bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
8094     /*
8095      * Emit callable invocation or operator new (constructor call) code.
8096      * First, emit code for the left operand to evaluate the callable or
8097      * constructable object expression.
8098      *
8099      * For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
8100      * This is necessary to interpose the lambda-initialized method read
8101      * barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
8102      * JSOP_{SET,INIT}PROP.
8103      *
8104      * Then (or in a call case that has no explicit reference-base
8105      * object) we emit JSOP_UNDEFINED to produce the undefined |this|
8106      * value required for calls (which non-strict mode functions
8107      * will box into the global object).
8108      */
8109     uint32_t argc = pn->pn_count - 1;
8110 
8111     if (argc >= ARGC_LIMIT) {
8112         parser->tokenStream.reportError(callop
8113                                         ? JSMSG_TOO_MANY_FUN_ARGS
8114                                         : JSMSG_TOO_MANY_CON_ARGS);
8115         return false;
8116     }
8117 
8118     ParseNode* pn2 = pn->pn_head;
8119     bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
8120     switch (pn2->getKind()) {
8121       case PNK_NAME:
8122         if (emitterMode == BytecodeEmitter::SelfHosting && !spread) {
8123             // Calls to "forceInterpreter", "callFunction",
8124             // "callContentFunction", or "resumeGenerator" in self-hosted
8125             // code generate inline bytecode.
8126             if (pn2->name() == cx->names().callFunction ||
8127                 pn2->name() == cx->names().callContentFunction ||
8128                 pn2->name() == cx->names().constructContentFunction)
8129             {
8130                 return emitSelfHostedCallFunction(pn);
8131             }
8132             if (pn2->name() == cx->names().resumeGenerator)
8133                 return emitSelfHostedResumeGenerator(pn);
8134             if (pn2->name() == cx->names().forceInterpreter)
8135                 return emitSelfHostedForceInterpreter(pn);
8136             if (pn2->name() == cx->names().allowContentSpread)
8137                 return emitSelfHostedAllowContentSpread(pn);
8138             // Fall through.
8139         }
8140         if (!emitGetName(pn2, callop))
8141             return false;
8142         break;
8143       case PNK_DOT:
8144         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
8145         if (pn2->as<PropertyAccess>().isSuper()) {
8146             if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
8147                 return false;
8148         } else {
8149             if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
8150                 return false;
8151         }
8152 
8153         break;
8154       case PNK_ELEM:
8155         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
8156         if (pn2->as<PropertyByValue>().isSuper()) {
8157             if (!emitSuperElemOp(pn2, JSOP_GETELEM_SUPER, /* isCall = */ callop))
8158                 return false;
8159         } else {
8160             if (!emitElemOp(pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM))
8161                 return false;
8162             if (callop) {
8163                 if (!emit1(JSOP_SWAP))
8164                     return false;
8165             }
8166         }
8167 
8168         break;
8169       case PNK_FUNCTION:
8170         /*
8171          * Top level lambdas which are immediately invoked should be
8172          * treated as only running once. Every time they execute we will
8173          * create new types and scripts for their contents, to increase
8174          * the quality of type information within them and enable more
8175          * backend optimizations. Note that this does not depend on the
8176          * lambda being invoked at most once (it may be named or be
8177          * accessed via foo.caller indirection), as multiple executions
8178          * will just cause the inner scripts to be repeatedly cloned.
8179          */
8180         MOZ_ASSERT(!emittingRunOnceLambda);
8181         if (checkRunOnceContext()) {
8182             emittingRunOnceLambda = true;
8183             if (!emitTree(pn2))
8184                 return false;
8185             emittingRunOnceLambda = false;
8186         } else {
8187             if (!emitTree(pn2))
8188                 return false;
8189         }
8190         callop = false;
8191         break;
8192       case PNK_SUPERBASE:
8193         MOZ_ASSERT(pn->isKind(PNK_SUPERCALL));
8194         MOZ_ASSERT(parser->handler.isSuperBase(pn2));
8195         if (!emit1(JSOP_SUPERFUN))
8196             return false;
8197         break;
8198       default:
8199         if (!emitTree(pn2))
8200             return false;
8201         callop = false;             /* trigger JSOP_UNDEFINED after */
8202         break;
8203     }
8204 
8205     bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
8206                    pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
8207 
8208 
8209     // Emit room for |this|.
8210     if (!callop) {
8211         if (isNewOp) {
8212             if (!emit1(JSOP_IS_CONSTRUCTING))
8213                 return false;
8214         } else {
8215             if (!emit1(JSOP_UNDEFINED))
8216                 return false;
8217         }
8218     }
8219 
8220     /*
8221      * Emit code for each argument in order, then emit the JSOP_*CALL or
8222      * JSOP_NEW bytecode with a two-byte immediate telling how many args
8223      * were pushed on the operand stack.
8224      */
8225     if (!spread) {
8226         for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
8227             if (!emitTree(pn3))
8228                 return false;
8229         }
8230 
8231         if (isNewOp) {
8232             if (pn->isKind(PNK_SUPERCALL)) {
8233                 if (!emit1(JSOP_NEWTARGET))
8234                     return false;
8235             } else {
8236                 // Repush the callee as new.target
8237                 if (!emitDupAt(argc + 1))
8238                     return false;
8239             }
8240         }
8241     } else {
8242         ParseNode* args = pn2->pn_next;
8243         JumpList jmp;
8244         bool optCodeEmitted = false;
8245         if (argc == 1) {
8246             if (!emitOptimizeSpread(args->pn_kid, &jmp, &optCodeEmitted))
8247                 return false;
8248         }
8249 
8250         if (!emitArray(args, argc, JSOP_SPREADCALLARRAY))
8251             return false;
8252 
8253         if (optCodeEmitted) {
8254             if (!emitJumpTargetAndPatch(jmp))
8255                 return false;
8256         }
8257 
8258         if (isNewOp) {
8259             if (pn->isKind(PNK_SUPERCALL)) {
8260                 if (!emit1(JSOP_NEWTARGET))
8261                     return false;
8262             } else {
8263                 if (!emitDupAt(2))
8264                     return false;
8265             }
8266         }
8267     }
8268 
8269     if (!spread) {
8270         if (!emitCall(pn->getOp(), argc, pn))
8271             return false;
8272     } else {
8273         if (!emit1(pn->getOp()))
8274             return false;
8275     }
8276     checkTypeSet(pn->getOp());
8277     if (pn->isOp(JSOP_EVAL) ||
8278         pn->isOp(JSOP_STRICTEVAL) ||
8279         pn->isOp(JSOP_SPREADEVAL) ||
8280         pn->isOp(JSOP_STRICTSPREADEVAL))
8281     {
8282         uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin);
8283         if (!emitUint32Operand(JSOP_LINENO, lineNum))
8284             return false;
8285     }
8286 
8287     return true;
8288 }
8289 
8290 bool
emitRightAssociative(ParseNode * pn)8291 BytecodeEmitter::emitRightAssociative(ParseNode* pn)
8292 {
8293     // ** is the only right-associative operator.
8294     MOZ_ASSERT(pn->isKind(PNK_POW));
8295     MOZ_ASSERT(pn->isArity(PN_LIST));
8296 
8297     // Right-associative operator chain.
8298     for (ParseNode* subexpr = pn->pn_head; subexpr; subexpr = subexpr->pn_next) {
8299         if (!emitTree(subexpr))
8300             return false;
8301     }
8302     for (uint32_t i = 0; i < pn->pn_count - 1; i++) {
8303         if (!emit1(JSOP_POW))
8304             return false;
8305     }
8306     return true;
8307 }
8308 
8309 bool
emitLeftAssociative(ParseNode * pn)8310 BytecodeEmitter::emitLeftAssociative(ParseNode* pn)
8311 {
8312     MOZ_ASSERT(pn->isArity(PN_LIST));
8313 
8314     // Left-associative operator chain.
8315     if (!emitTree(pn->pn_head))
8316         return false;
8317     JSOp op = pn->getOp();
8318     ParseNode* nextExpr = pn->pn_head->pn_next;
8319     do {
8320         if (!emitTree(nextExpr))
8321             return false;
8322         if (!emit1(op))
8323             return false;
8324     } while ((nextExpr = nextExpr->pn_next));
8325     return true;
8326 }
8327 
8328 bool
emitLogical(ParseNode * pn)8329 BytecodeEmitter::emitLogical(ParseNode* pn)
8330 {
8331     MOZ_ASSERT(pn->isArity(PN_LIST));
8332 
8333     /*
8334      * JSOP_OR converts the operand on the stack to boolean, leaves the original
8335      * value on the stack and jumps if true; otherwise it falls into the next
8336      * bytecode, which pops the left operand and then evaluates the right operand.
8337      * The jump goes around the right operand evaluation.
8338      *
8339      * JSOP_AND converts the operand on the stack to boolean and jumps if false;
8340      * otherwise it falls into the right operand's bytecode.
8341      */
8342 
8343     TDZCheckCache tdzCache(this);
8344 
8345     /* Left-associative operator chain: avoid too much recursion. */
8346     ParseNode* pn2 = pn->pn_head;
8347     if (!emitTree(pn2))
8348         return false;
8349     JSOp op = pn->getOp();
8350     JumpList jump;
8351     if (!emitJump(op, &jump))
8352         return false;
8353     if (!emit1(JSOP_POP))
8354         return false;
8355 
8356     /* Emit nodes between the head and the tail. */
8357     while ((pn2 = pn2->pn_next)->pn_next) {
8358         if (!emitTree(pn2))
8359             return false;
8360         if (!emitJump(op, &jump))
8361             return false;
8362         if (!emit1(JSOP_POP))
8363             return false;
8364     }
8365     if (!emitTree(pn2))
8366         return false;
8367 
8368     if (!emitJumpTargetAndPatch(jump))
8369         return false;
8370     return true;
8371 }
8372 
8373 bool
emitSequenceExpr(ParseNode * pn)8374 BytecodeEmitter::emitSequenceExpr(ParseNode* pn)
8375 {
8376     for (ParseNode* child = pn->pn_head; ; child = child->pn_next) {
8377         if (!updateSourceCoordNotes(child->pn_pos.begin))
8378             return false;
8379         if (!emitTree(child))
8380             return false;
8381         if (!child->pn_next)
8382             break;
8383         if (!emit1(JSOP_POP))
8384             return false;
8385     }
8386     return true;
8387 }
8388 
8389 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
8390 // the comment on emitSwitch.
8391 MOZ_NEVER_INLINE bool
emitIncOrDec(ParseNode * pn)8392 BytecodeEmitter::emitIncOrDec(ParseNode* pn)
8393 {
8394     switch (pn->pn_kid->getKind()) {
8395       case PNK_DOT:
8396         return emitPropIncDec(pn);
8397       case PNK_ELEM:
8398         return emitElemIncDec(pn);
8399       case PNK_CALL:
8400         return emitCallIncDec(pn);
8401       default:
8402         return emitNameIncDec(pn);
8403     }
8404 
8405     return true;
8406 }
8407 
8408 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
8409 // the comment on emitSwitch.
8410 MOZ_NEVER_INLINE bool
emitLabeledStatement(const LabeledStatement * pn)8411 BytecodeEmitter::emitLabeledStatement(const LabeledStatement* pn)
8412 {
8413     /*
8414      * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
8415      * following the labeled statement.
8416      */
8417     uint32_t index;
8418     if (!makeAtomIndex(pn->label(), &index))
8419         return false;
8420 
8421     JumpList top;
8422     if (!emitJump(JSOP_LABEL, &top))
8423         return false;
8424 
8425     /* Emit code for the labeled statement. */
8426     LabelControl controlInfo(this, pn->label(), offset());
8427 
8428     if (!emitTree(pn->statement()))
8429         return false;
8430 
8431     /* Patch the JSOP_LABEL offset. */
8432     JumpTarget brk{ lastNonJumpTargetOffset() };
8433     patchJumpsToTarget(top, brk);
8434 
8435     if (!controlInfo.patchBreaks(this))
8436         return false;
8437 
8438     return true;
8439 }
8440 
8441 bool
emitConditionalExpression(ConditionalExpression & conditional)8442 BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
8443 {
8444     /* Emit the condition, then branch if false to the else part. */
8445     if (!emitTree(&conditional.condition()))
8446         return false;
8447 
8448     IfThenElseEmitter ifThenElse(this);
8449     if (!ifThenElse.emitCond())
8450         return false;
8451 
8452     if (!emitConditionallyExecutedTree(&conditional.thenExpression()))
8453         return false;
8454 
8455     if (!ifThenElse.emitElse())
8456         return false;
8457 
8458     if (!emitConditionallyExecutedTree(&conditional.elseExpression()))
8459         return false;
8460 
8461     if (!ifThenElse.emitEnd())
8462         return false;
8463     MOZ_ASSERT(ifThenElse.pushed() == 1);
8464 
8465     return true;
8466 }
8467 
8468 bool
emitPropertyList(ParseNode * pn,MutableHandlePlainObject objp,PropListType type)8469 BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type)
8470 {
8471     for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
8472         if (!updateSourceCoordNotes(propdef->pn_pos.begin))
8473             return false;
8474 
8475         // Handle __proto__: v specially because *only* this form, and no other
8476         // involving "__proto__", performs [[Prototype]] mutation.
8477         if (propdef->isKind(PNK_MUTATEPROTO)) {
8478             MOZ_ASSERT(type == ObjectLiteral);
8479             if (!emitTree(propdef->pn_kid))
8480                 return false;
8481             objp.set(nullptr);
8482             if (!emit1(JSOP_MUTATEPROTO))
8483                 return false;
8484             continue;
8485         }
8486 
8487         bool extraPop = false;
8488         if (type == ClassBody && propdef->as<ClassMethod>().isStatic()) {
8489             extraPop = true;
8490             if (!emit1(JSOP_DUP2))
8491                 return false;
8492             if (!emit1(JSOP_POP))
8493                 return false;
8494         }
8495 
8496         /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
8497         ParseNode* key = propdef->pn_left;
8498         bool isIndex = false;
8499         if (key->isKind(PNK_NUMBER)) {
8500             if (!emitNumberOp(key->pn_dval))
8501                 return false;
8502             isIndex = true;
8503         } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
8504             // EmitClass took care of constructor already.
8505             if (type == ClassBody && key->pn_atom == cx->names().constructor &&
8506                 !propdef->as<ClassMethod>().isStatic())
8507             {
8508                 continue;
8509             }
8510 
8511             // The parser already checked for atoms representing indexes and
8512             // used PNK_NUMBER instead, but also watch for ids which TI treats
8513             // as indexes for simpliciation of downstream analysis.
8514             jsid id = NameToId(key->pn_atom->asPropertyName());
8515             if (id != IdToTypeId(id)) {
8516                 if (!emitTree(key))
8517                     return false;
8518                 isIndex = true;
8519             }
8520         } else {
8521             if (!emitComputedPropertyName(key))
8522                 return false;
8523             isIndex = true;
8524         }
8525 
8526         /* Emit code for the property initializer. */
8527         if (!emitTree(propdef->pn_right))
8528             return false;
8529 
8530         JSOp op = propdef->getOp();
8531         MOZ_ASSERT(op == JSOP_INITPROP ||
8532                    op == JSOP_INITPROP_GETTER ||
8533                    op == JSOP_INITPROP_SETTER);
8534 
8535         if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
8536             objp.set(nullptr);
8537 
8538         if (propdef->pn_right->isKind(PNK_FUNCTION) &&
8539             propdef->pn_right->pn_funbox->needsHomeObject())
8540         {
8541             MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty());
8542             bool isAsync = propdef->pn_right->pn_funbox->isAsync();
8543             if (isAsync) {
8544                 if (!emit1(JSOP_SWAP))
8545                     return false;
8546             }
8547             if (!emit2(JSOP_INITHOMEOBJECT, isIndex + isAsync))
8548                 return false;
8549             if (isAsync) {
8550                 if (!emit1(JSOP_POP))
8551                     return false;
8552             }
8553         }
8554 
8555         // Class methods are not enumerable.
8556         if (type == ClassBody) {
8557             switch (op) {
8558               case JSOP_INITPROP:        op = JSOP_INITHIDDENPROP;          break;
8559               case JSOP_INITPROP_GETTER: op = JSOP_INITHIDDENPROP_GETTER;   break;
8560               case JSOP_INITPROP_SETTER: op = JSOP_INITHIDDENPROP_SETTER;   break;
8561               default: MOZ_CRASH("Invalid op");
8562             }
8563         }
8564 
8565         if (isIndex) {
8566             objp.set(nullptr);
8567             switch (op) {
8568               case JSOP_INITPROP:               op = JSOP_INITELEM;              break;
8569               case JSOP_INITHIDDENPROP:         op = JSOP_INITHIDDENELEM;        break;
8570               case JSOP_INITPROP_GETTER:        op = JSOP_INITELEM_GETTER;       break;
8571               case JSOP_INITHIDDENPROP_GETTER:  op = JSOP_INITHIDDENELEM_GETTER; break;
8572               case JSOP_INITPROP_SETTER:        op = JSOP_INITELEM_SETTER;       break;
8573               case JSOP_INITHIDDENPROP_SETTER:  op = JSOP_INITHIDDENELEM_SETTER; break;
8574               default: MOZ_CRASH("Invalid op");
8575             }
8576             if (!emit1(op))
8577                 return false;
8578         } else {
8579             MOZ_ASSERT(key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING));
8580 
8581             uint32_t index;
8582             if (!makeAtomIndex(key->pn_atom, &index))
8583                 return false;
8584 
8585             if (objp) {
8586                 MOZ_ASSERT(type == ObjectLiteral);
8587                 MOZ_ASSERT(!IsHiddenInitOp(op));
8588                 MOZ_ASSERT(!objp->inDictionaryMode());
8589                 Rooted<jsid> id(cx, AtomToId(key->pn_atom));
8590                 RootedValue undefinedValue(cx, UndefinedValue());
8591                 if (!NativeDefineProperty(cx, objp, id, undefinedValue, nullptr, nullptr,
8592                                           JSPROP_ENUMERATE))
8593                 {
8594                     return false;
8595                 }
8596                 if (objp->inDictionaryMode())
8597                     objp.set(nullptr);
8598             }
8599 
8600             if (!emitIndex32(op, index))
8601                 return false;
8602         }
8603 
8604         if (extraPop) {
8605             if (!emit1(JSOP_POP))
8606                 return false;
8607         }
8608     }
8609     return true;
8610 }
8611 
8612 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
8613 // the comment on emitSwitch.
8614 MOZ_NEVER_INLINE bool
emitObject(ParseNode * pn)8615 BytecodeEmitter::emitObject(ParseNode* pn)
8616 {
8617     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && checkSingletonContext())
8618         return emitSingletonInitialiser(pn);
8619 
8620     /*
8621      * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
8622      * a new object and defining (in source order) each property on the object
8623      * (or mutating the object's [[Prototype]], in the case of __proto__).
8624      */
8625     ptrdiff_t offset = this->offset();
8626     if (!emitNewInit(JSProto_Object))
8627         return false;
8628 
8629     /*
8630      * Try to construct the shape of the object as we go, so we can emit a
8631      * JSOP_NEWOBJECT with the final shape instead.
8632      */
8633     RootedPlainObject obj(cx);
8634     // No need to do any guessing for the object kind, since we know exactly
8635     // how many properties we plan to have.
8636     gc::AllocKind kind = gc::GetGCObjectKind(pn->pn_count);
8637     obj = NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject);
8638     if (!obj)
8639         return false;
8640 
8641     if (!emitPropertyList(pn, &obj, ObjectLiteral))
8642         return false;
8643 
8644     if (obj) {
8645         /*
8646          * The object survived and has a predictable shape: update the original
8647          * bytecode.
8648          */
8649         ObjectBox* objbox = parser->newObjectBox(obj);
8650         if (!objbox)
8651             return false;
8652 
8653         static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
8654                       "newinit and newobject must have equal length to edit in-place");
8655 
8656         uint32_t index = objectList.add(objbox);
8657         jsbytecode* code = this->code(offset);
8658         code[0] = JSOP_NEWOBJECT;
8659         code[1] = jsbytecode(index >> 24);
8660         code[2] = jsbytecode(index >> 16);
8661         code[3] = jsbytecode(index >> 8);
8662         code[4] = jsbytecode(index);
8663     }
8664 
8665     return true;
8666 }
8667 
8668 bool
emitArrayComp(ParseNode * pn)8669 BytecodeEmitter::emitArrayComp(ParseNode* pn)
8670 {
8671     if (!emitNewInit(JSProto_Array))
8672         return false;
8673 
8674     /*
8675      * Pass the new array's stack index to the PNK_ARRAYPUSH case via
8676      * arrayCompDepth, then simply traverse the PNK_FOR node and
8677      * its kids under pn2 to generate this comprehension.
8678      */
8679     MOZ_ASSERT(stackDepth > 0);
8680     uint32_t saveDepth = arrayCompDepth;
8681     arrayCompDepth = (uint32_t) (stackDepth - 1);
8682     if (!emitTree(pn->pn_head))
8683         return false;
8684     arrayCompDepth = saveDepth;
8685 
8686     return true;
8687 }
8688 
8689 bool
emitArrayLiteral(ParseNode * pn)8690 BytecodeEmitter::emitArrayLiteral(ParseNode* pn)
8691 {
8692     if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head) {
8693         if (checkSingletonContext()) {
8694             // Bake in the object entirely if it will only be created once.
8695             return emitSingletonInitialiser(pn);
8696         }
8697 
8698         // If the array consists entirely of primitive values, make a
8699         // template object with copy on write elements that can be reused
8700         // every time the initializer executes.
8701         if (emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
8702             RootedValue value(cx);
8703             if (!pn->getConstantValue(cx, ParseNode::ForCopyOnWriteArray, &value))
8704                 return false;
8705             if (!value.isMagic(JS_GENERIC_MAGIC)) {
8706                 // Note: the group of the template object might not yet reflect
8707                 // that the object has copy on write elements. When the
8708                 // interpreter or JIT compiler fetches the template, it should
8709                 // use ObjectGroup::getOrFixupCopyOnWriteObject to make sure the
8710                 // group for the template is accurate. We don't do this here as we
8711                 // want to use ObjectGroup::allocationSiteGroup, which requires a
8712                 // finished script.
8713                 JSObject* obj = &value.toObject();
8714                 MOZ_ASSERT(obj->is<ArrayObject>() &&
8715                            obj->as<ArrayObject>().denseElementsAreCopyOnWrite());
8716 
8717                 ObjectBox* objbox = parser->newObjectBox(obj);
8718                 if (!objbox)
8719                     return false;
8720 
8721                 return emitObjectOp(objbox, JSOP_NEWARRAY_COPYONWRITE);
8722             }
8723         }
8724     }
8725 
8726     return emitArray(pn->pn_head, pn->pn_count, JSOP_NEWARRAY);
8727 }
8728 
8729 bool
emitArray(ParseNode * pn,uint32_t count,JSOp op)8730 BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
8731 {
8732 
8733     /*
8734      * Emit code for [a, b, c] that is equivalent to constructing a new
8735      * array and in source order evaluating each element value and adding
8736      * it to the array, without invoking latent setters.  We use the
8737      * JSOP_NEWINIT and JSOP_INITELEM_ARRAY bytecodes to ignore setters and
8738      * to avoid dup'ing and popping the array as each element is added, as
8739      * JSOP_SETELEM/JSOP_SETPROP would do.
8740      */
8741     MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
8742 
8743     uint32_t nspread = 0;
8744     for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
8745         if (elt->isKind(PNK_SPREAD))
8746             nspread++;
8747     }
8748 
8749     // Array literal's length is limited to NELEMENTS_LIMIT in parser.
8750     static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
8751                   "array literals' maximum length must not exceed limits "
8752                   "required by BaselineCompiler::emit_JSOP_NEWARRAY, "
8753                   "BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
8754                   "and DoSetElemFallback's handling of JSOP_INITELEM_ARRAY");
8755     MOZ_ASSERT(count >= nspread);
8756     MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,
8757                "the parser must throw an error if the array exceeds maximum "
8758                "length");
8759 
8760     // For arrays with spread, this is a very pessimistic allocation, the
8761     // minimum possible final size.
8762     if (!emitUint32Operand(op, count - nspread))                    // ARRAY
8763         return false;
8764 
8765     ParseNode* pn2 = pn;
8766     uint32_t index;
8767     bool afterSpread = false;
8768     for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
8769         if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
8770             afterSpread = true;
8771             if (!emitNumberOp(index))                               // ARRAY INDEX
8772                 return false;
8773         }
8774         if (!updateSourceCoordNotes(pn2->pn_pos.begin))
8775             return false;
8776 
8777         bool allowSelfHostedSpread = false;
8778         if (pn2->isKind(PNK_ELISION)) {
8779             if (!emit1(JSOP_HOLE))
8780                 return false;
8781         } else {
8782             ParseNode* expr;
8783             if (pn2->isKind(PNK_SPREAD)) {
8784                 expr = pn2->pn_kid;
8785 
8786                 if (emitterMode == BytecodeEmitter::SelfHosting &&
8787                     expr->isKind(PNK_CALL) &&
8788                     expr->pn_head->name() == cx->names().allowContentSpread)
8789                 {
8790                     allowSelfHostedSpread = true;
8791                 }
8792             } else {
8793                 expr = pn2;
8794             }
8795             if (!emitTree(expr))                                         // ARRAY INDEX? VALUE
8796                 return false;
8797         }
8798         if (pn2->isKind(PNK_SPREAD)) {
8799             if (!emitIterator())                                         // ARRAY INDEX ITER
8800                 return false;
8801             if (!emit2(JSOP_PICK, 2))                                    // INDEX ITER ARRAY
8802                 return false;
8803             if (!emit2(JSOP_PICK, 2))                                    // ITER ARRAY INDEX
8804                 return false;
8805             if (!emitSpread(allowSelfHostedSpread))                      // ARRAY INDEX
8806                 return false;
8807         } else if (afterSpread) {
8808             if (!emit1(JSOP_INITELEM_INC))
8809                 return false;
8810         } else {
8811             if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index))
8812                 return false;
8813         }
8814     }
8815     MOZ_ASSERT(index == count);
8816     if (afterSpread) {
8817         if (!emit1(JSOP_POP))                                            // ARRAY
8818             return false;
8819     }
8820     return true;
8821 }
8822 
8823 bool
emitUnary(ParseNode * pn)8824 BytecodeEmitter::emitUnary(ParseNode* pn)
8825 {
8826     if (!updateSourceCoordNotes(pn->pn_pos.begin))
8827         return false;
8828 
8829     /* Unary op, including unary +/-. */
8830     JSOp op = pn->getOp();
8831     ParseNode* pn2 = pn->pn_kid;
8832 
8833     if (!emitTree(pn2))
8834         return false;
8835 
8836     return emit1(op);
8837 }
8838 
8839 bool
emitTypeof(ParseNode * node,JSOp op)8840 BytecodeEmitter::emitTypeof(ParseNode* node, JSOp op)
8841 {
8842     MOZ_ASSERT(op == JSOP_TYPEOF || op == JSOP_TYPEOFEXPR);
8843 
8844     if (!updateSourceCoordNotes(node->pn_pos.begin))
8845         return false;
8846 
8847     if (!emitTree(node->pn_kid))
8848         return false;
8849 
8850     return emit1(op);
8851 }
8852 
8853 bool
emitFunctionFormalParametersAndBody(ParseNode * pn)8854 BytecodeEmitter::emitFunctionFormalParametersAndBody(ParseNode *pn)
8855 {
8856     MOZ_ASSERT(pn->isKind(PNK_PARAMSBODY));
8857 
8858     ParseNode* funBody = pn->last();
8859     FunctionBox* funbox = sc->asFunctionBox();
8860 
8861     TDZCheckCache tdzCache(this);
8862 
8863     if (funbox->hasParameterExprs) {
8864         EmitterScope funEmitterScope(this);
8865         if (!funEmitterScope.enterFunction(this, funbox))
8866             return false;
8867 
8868         if (!emitInitializeFunctionSpecialNames())
8869             return false;
8870 
8871         if (!emitFunctionFormalParameters(pn))
8872             return false;
8873 
8874         {
8875             Maybe<EmitterScope> extraVarEmitterScope;
8876 
8877             if (funbox->hasExtraBodyVarScope()) {
8878                 extraVarEmitterScope.emplace(this);
8879                 if (!extraVarEmitterScope->enterFunctionExtraBodyVar(this, funbox))
8880                     return false;
8881 
8882                 // After emitting expressions for all parameters, copy over any
8883                 // formal parameters which have been redeclared as vars. For
8884                 // example, in the following, the var y in the body scope is 42:
8885                 //
8886                 //   function f(x, y = 42) { var y; }
8887                 //
8888                 RootedAtom name(cx);
8889                 if (funbox->extraVarScopeBindings() && funbox->functionScopeBindings()) {
8890                     for (BindingIter bi(*funbox->functionScopeBindings(), true); bi; bi++) {
8891                         name = bi.name();
8892 
8893                         // There may not be a var binding of the same name.
8894                         if (!locationOfNameBoundInScope(name, extraVarEmitterScope.ptr()))
8895                             continue;
8896 
8897                         // The '.this' and '.generator' function special
8898                         // bindings should never appear in the extra var
8899                         // scope. 'arguments', however, may.
8900                         MOZ_ASSERT(name != cx->names().dotThis &&
8901                                    name != cx->names().dotGenerator);
8902 
8903                         NameLocation paramLoc = *locationOfNameBoundInScope(name, &funEmitterScope);
8904                         auto emitRhs = [&name, &paramLoc](BytecodeEmitter* bce,
8905                                                           const NameLocation&, bool)
8906                         {
8907                             return bce->emitGetNameAtLocation(name, paramLoc);
8908                         };
8909 
8910                         if (!emitInitializeName(name, emitRhs))
8911                             return false;
8912                         if (!emit1(JSOP_POP))
8913                             return false;
8914                     }
8915                 }
8916             }
8917 
8918             if (!emitFunctionBody(funBody))
8919                 return false;
8920 
8921             if (extraVarEmitterScope && !extraVarEmitterScope->leave(this))
8922                 return false;
8923         }
8924 
8925         return funEmitterScope.leave(this);
8926     }
8927 
8928     // No parameter expressions. Enter the function body scope and emit
8929     // everything.
8930     //
8931     // One caveat is that Debugger considers ops in the prologue to be
8932     // unreachable (i.e. cannot set a breakpoint on it). If there are no
8933     // parameter exprs, any unobservable environment ops (like pushing the
8934     // call object, setting '.this', etc) need to go in the prologue, else it
8935     // messes up breakpoint tests.
8936     EmitterScope emitterScope(this);
8937 
8938     switchToPrologue();
8939     if (!emitterScope.enterFunction(this, funbox))
8940         return false;
8941 
8942     if (!emitInitializeFunctionSpecialNames())
8943         return false;
8944     switchToMain();
8945 
8946     if (!emitFunctionFormalParameters(pn))
8947         return false;
8948 
8949     if (!emitFunctionBody(funBody))
8950         return false;
8951 
8952     return emitterScope.leave(this);
8953 }
8954 
8955 bool
emitFunctionFormalParameters(ParseNode * pn)8956 BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn)
8957 {
8958     ParseNode* funBody = pn->last();
8959     FunctionBox* funbox = sc->asFunctionBox();
8960     EmitterScope* funScope = innermostEmitterScope;
8961 
8962     bool hasParameterExprs = funbox->hasParameterExprs;
8963     bool hasRest = funbox->function()->hasRest();
8964 
8965     uint16_t argSlot = 0;
8966     for (ParseNode* arg = pn->pn_head; arg != funBody; arg = arg->pn_next, argSlot++) {
8967         ParseNode* bindingElement = arg;
8968         ParseNode* initializer = nullptr;
8969         if (arg->isKind(PNK_ASSIGN)) {
8970             bindingElement = arg->pn_left;
8971             initializer = arg->pn_right;
8972         }
8973 
8974         // Left-hand sides are either simple names or destructuring patterns.
8975         MOZ_ASSERT(bindingElement->isKind(PNK_NAME) ||
8976                    bindingElement->isKind(PNK_ARRAY) ||
8977                    bindingElement->isKind(PNK_ARRAYCOMP) ||
8978                    bindingElement->isKind(PNK_OBJECT));
8979 
8980         // The rest parameter doesn't have an initializer.
8981         bool isRest = hasRest && arg->pn_next == funBody;
8982         MOZ_ASSERT_IF(isRest, !initializer);
8983 
8984         bool isDestructuring = !bindingElement->isKind(PNK_NAME);
8985 
8986         // ES 14.1.19 says if BindingElement contains an expression in the
8987         // production FormalParameter : BindingElement, it is evaluated in a
8988         // new var environment. This is needed to prevent vars from escaping
8989         // direct eval in parameter expressions.
8990         Maybe<EmitterScope> paramExprVarScope;
8991         if (funbox->hasDirectEvalInParameterExpr && (isDestructuring || initializer)) {
8992             paramExprVarScope.emplace(this);
8993             if (!paramExprVarScope->enterParameterExpressionVar(this))
8994                 return false;
8995         }
8996 
8997         // First push the RHS if there is a default expression or if it is
8998         // rest.
8999 
9000         if (initializer) {
9001             // If we have an initializer, emit the initializer and assign it
9002             // to the argument slot. TDZ is taken care of afterwards.
9003             MOZ_ASSERT(hasParameterExprs);
9004             if (!emitArgOp(JSOP_GETARG, argSlot))
9005                 return false;
9006             if (!emit1(JSOP_DUP))
9007                 return false;
9008             if (!emit1(JSOP_UNDEFINED))
9009                 return false;
9010             if (!emit1(JSOP_STRICTEQ))
9011                 return false;
9012             // Emit source note to enable Ion compilation.
9013             if (!newSrcNote(SRC_IF))
9014                 return false;
9015             JumpList jump;
9016             if (!emitJump(JSOP_IFEQ, &jump))
9017                 return false;
9018             if (!emit1(JSOP_POP))
9019                 return false;
9020             if (!emitConditionallyExecutedTree(initializer))
9021                 return false;
9022             if (!emitJumpTargetAndPatch(jump))
9023                 return false;
9024         } else if (isRest) {
9025             if (!emit1(JSOP_REST))
9026                 return false;
9027             checkTypeSet(JSOP_REST);
9028         }
9029 
9030         // Initialize the parameter name.
9031 
9032         if (isDestructuring) {
9033             // If we had an initializer or the rest parameter, the value is
9034             // already on the stack.
9035             if (!initializer && !isRest && !emitArgOp(JSOP_GETARG, argSlot))
9036                 return false;
9037 
9038             // If there's an parameter expression var scope, the destructuring
9039             // declaration needs to initialize the name in the function scope,
9040             // which is not the innermost scope.
9041             if (!emitDestructuringOps(bindingElement,
9042                                       paramExprVarScope
9043                                       ? DestructuringFormalParameterInVarScope
9044                                       : DestructuringDeclaration))
9045             {
9046                 return false;
9047             }
9048 
9049             if (!emit1(JSOP_POP))
9050                 return false;
9051         } else {
9052             RootedAtom paramName(cx, bindingElement->name());
9053             NameLocation paramLoc = *locationOfNameBoundInScope(paramName, funScope);
9054 
9055             if (hasParameterExprs) {
9056                 auto emitRhs = [argSlot, initializer, isRest](BytecodeEmitter* bce,
9057                                                               const NameLocation&, bool)
9058                 {
9059                     // If we had an initializer or a rest parameter, the value is
9060                     // already on the stack.
9061                     if (!initializer && !isRest)
9062                         return bce->emitArgOp(JSOP_GETARG, argSlot);
9063                     return true;
9064                 };
9065 
9066                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, emitRhs, true))
9067                     return false;
9068                 if (!emit1(JSOP_POP))
9069                     return false;
9070             } else if (isRest) {
9071                 // The rest value is already on top of the stack.
9072                 auto nop = [](BytecodeEmitter*, const NameLocation&, bool) {
9073                     return true;
9074                 };
9075 
9076                 if (!emitSetOrInitializeNameAtLocation(paramName, paramLoc, nop, true))
9077                     return false;
9078                 if (!emit1(JSOP_POP))
9079                     return false;
9080             }
9081         }
9082 
9083         if (paramExprVarScope) {
9084             if (!paramExprVarScope->leave(this))
9085                 return false;
9086         }
9087     }
9088 
9089     return true;
9090 }
9091 
9092 bool
emitInitializeFunctionSpecialNames()9093 BytecodeEmitter::emitInitializeFunctionSpecialNames()
9094 {
9095     FunctionBox* funbox = sc->asFunctionBox();
9096 
9097     auto emitInitializeFunctionSpecialName = [](BytecodeEmitter* bce, HandlePropertyName name,
9098                                                 JSOp op)
9099     {
9100         // A special name must be slotful, either on the frame or on the
9101         // call environment.
9102         MOZ_ASSERT(bce->lookupName(name).hasKnownSlot());
9103 
9104         auto emitInitial = [op](BytecodeEmitter* bce, const NameLocation&, bool) {
9105             return bce->emit1(op);
9106         };
9107 
9108         if (!bce->emitInitializeName(name, emitInitial))
9109             return false;
9110         if (!bce->emit1(JSOP_POP))
9111             return false;
9112 
9113         return true;
9114     };
9115 
9116     // Do nothing if the function doesn't have an arguments binding.
9117     if (funbox->argumentsHasLocalBinding()) {
9118         if (!emitInitializeFunctionSpecialName(this, cx->names().arguments, JSOP_ARGUMENTS))
9119             return false;
9120     }
9121 
9122     // Do nothing if the function doesn't have a this-binding (this
9123     // happens for instance if it doesn't use this/eval or if it's an
9124     // arrow function).
9125     if (funbox->hasThisBinding()) {
9126         if (!emitInitializeFunctionSpecialName(this, cx->names().dotThis, JSOP_FUNCTIONTHIS))
9127             return false;
9128     }
9129 
9130     return true;
9131 }
9132 
9133 bool
emitFunctionBody(ParseNode * funBody)9134 BytecodeEmitter::emitFunctionBody(ParseNode* funBody)
9135 {
9136     FunctionBox* funbox = sc->asFunctionBox();
9137 
9138     if (!emitTree(funBody))
9139         return false;
9140 
9141     if (funbox->isGenerator()) {
9142         // If we fall off the end of a generator, do a final yield.
9143         if (funbox->isStarGenerator() && !emitPrepareIteratorResult())
9144             return false;
9145 
9146         if (!emit1(JSOP_UNDEFINED))
9147             return false;
9148 
9149         if (sc->asFunctionBox()->isStarGenerator() && !emitFinishIteratorResult(true))
9150             return false;
9151 
9152         if (!emit1(JSOP_SETRVAL))
9153             return false;
9154 
9155         NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator);
9156         if (!emitGetNameAtLocation(cx->names().dotGenerator, loc))
9157             return false;
9158 
9159         // No need to check for finally blocks, etc as in EmitReturn.
9160         if (!emitYieldOp(JSOP_FINALYIELDRVAL))
9161             return false;
9162     } else {
9163         // Non-generator functions just return |undefined|. The
9164         // JSOP_RETRVAL emitted below will do that, except if the
9165         // script has a finally block: there can be a non-undefined
9166         // value in the return value slot. Make sure the return value
9167         // is |undefined|.
9168         if (hasTryFinally) {
9169             if (!emit1(JSOP_UNDEFINED))
9170                 return false;
9171             if (!emit1(JSOP_SETRVAL))
9172                 return false;
9173         }
9174     }
9175 
9176     if (funbox->isDerivedClassConstructor()) {
9177         if (!emitCheckDerivedClassConstructorReturn())
9178             return false;
9179     }
9180 
9181     return true;
9182 }
9183 
9184 bool
emitLexicalInitialization(ParseNode * pn)9185 BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
9186 {
9187     // The caller has pushed the RHS to the top of the stack. Assert that the
9188     // name is lexical and no BIND[G]NAME ops were emitted.
9189     auto assertLexical = [](BytecodeEmitter*, const NameLocation& loc, bool emittedBindOp) {
9190         MOZ_ASSERT(loc.isLexical());
9191         MOZ_ASSERT(!emittedBindOp);
9192         return true;
9193     };
9194     return emitInitializeName(pn, assertLexical);
9195 }
9196 
9197 // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
9198 // (BindingClassDeclarationEvaluation).
9199 bool
emitClass(ParseNode * pn)9200 BytecodeEmitter::emitClass(ParseNode* pn)
9201 {
9202     ClassNode& classNode = pn->as<ClassNode>();
9203 
9204     ClassNames* names = classNode.names();
9205 
9206     ParseNode* heritageExpression = classNode.heritage();
9207 
9208     ParseNode* classMethods = classNode.methodList();
9209     ParseNode* constructor = nullptr;
9210     for (ParseNode* mn = classMethods->pn_head; mn; mn = mn->pn_next) {
9211         ClassMethod& method = mn->as<ClassMethod>();
9212         ParseNode& methodName = method.name();
9213         if (!method.isStatic() &&
9214             (methodName.isKind(PNK_OBJECT_PROPERTY_NAME) || methodName.isKind(PNK_STRING)) &&
9215             methodName.pn_atom == cx->names().constructor)
9216         {
9217             constructor = &method.method();
9218             break;
9219         }
9220     }
9221 
9222     bool savedStrictness = sc->setLocalStrictMode(true);
9223 
9224     Maybe<TDZCheckCache> tdzCache;
9225     Maybe<EmitterScope> emitterScope;
9226     if (names) {
9227         tdzCache.emplace(this);
9228         emitterScope.emplace(this);
9229         if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode.scopeBindings()))
9230             return false;
9231     }
9232 
9233     // This is kind of silly. In order to the get the home object defined on
9234     // the constructor, we have to make it second, but we want the prototype
9235     // on top for EmitPropertyList, because we expect static properties to be
9236     // rarer. The result is a few more swaps than we would like. Such is life.
9237     if (heritageExpression) {
9238         if (!emitTree(heritageExpression))
9239             return false;
9240         if (!emit1(JSOP_CLASSHERITAGE))
9241             return false;
9242         if (!emit1(JSOP_OBJWITHPROTO))
9243             return false;
9244 
9245         // JSOP_CLASSHERITAGE leaves both protos on the stack. After
9246         // creating the prototype, swap it to the bottom to make the
9247         // constructor.
9248         if (!emit1(JSOP_SWAP))
9249             return false;
9250     } else {
9251         if (!emitNewInit(JSProto_Object))
9252             return false;
9253     }
9254 
9255     if (constructor) {
9256         if (!emitFunction(constructor, !!heritageExpression))
9257             return false;
9258         if (constructor->pn_funbox->needsHomeObject()) {
9259             if (!emit2(JSOP_INITHOMEOBJECT, 0))
9260                 return false;
9261         }
9262     } else {
9263         JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;
9264         if (heritageExpression) {
9265             if (!emitAtomOp(name, JSOP_DERIVEDCONSTRUCTOR))
9266                 return false;
9267         } else {
9268             if (!emitAtomOp(name, JSOP_CLASSCONSTRUCTOR))
9269                 return false;
9270         }
9271     }
9272 
9273     if (!emit1(JSOP_SWAP))
9274         return false;
9275 
9276     if (!emit1(JSOP_DUP2))
9277         return false;
9278     if (!emitAtomOp(cx->names().prototype, JSOP_INITLOCKEDPROP))
9279         return false;
9280     if (!emitAtomOp(cx->names().constructor, JSOP_INITHIDDENPROP))
9281         return false;
9282 
9283     RootedPlainObject obj(cx);
9284     if (!emitPropertyList(classMethods, &obj, ClassBody))
9285         return false;
9286 
9287     if (!emit1(JSOP_POP))
9288         return false;
9289 
9290     if (names) {
9291         ParseNode* innerName = names->innerBinding();
9292         if (!emitLexicalInitialization(innerName))
9293             return false;
9294 
9295         // Pop the inner scope.
9296         if (!emitterScope->leave(this))
9297             return false;
9298         emitterScope.reset();
9299 
9300         ParseNode* outerName = names->outerBinding();
9301         if (outerName) {
9302             if (!emitLexicalInitialization(outerName))
9303                 return false;
9304             // Only class statements make outer bindings, and they do not leave
9305             // themselves on the stack.
9306             if (!emit1(JSOP_POP))
9307                 return false;
9308         }
9309     }
9310 
9311     MOZ_ALWAYS_TRUE(sc->setLocalStrictMode(savedStrictness));
9312 
9313     return true;
9314 }
9315 
9316 bool
emitTree(ParseNode * pn,EmitLineNumberNote emitLineNote)9317 BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
9318 {
9319     JS_CHECK_RECURSION(cx, return false);
9320 
9321     EmitLevelManager elm(this);
9322 
9323     /* Emit notes to tell the current bytecode's source line number.
9324        However, a couple trees require special treatment; see the
9325        relevant emitter functions for details. */
9326     if (emitLineNote == EMIT_LINENOTE && !ParseNodeRequiresSpecialLineNumberNotes(pn)) {
9327         if (!updateLineNumberNotes(pn->pn_pos.begin))
9328             return false;
9329     }
9330 
9331     switch (pn->getKind()) {
9332       case PNK_FUNCTION:
9333         if (!emitFunction(pn))
9334             return false;
9335         break;
9336 
9337       case PNK_PARAMSBODY:
9338         if (!emitFunctionFormalParametersAndBody(pn))
9339             return false;
9340         break;
9341 
9342       case PNK_IF:
9343         if (!emitIf(pn))
9344             return false;
9345         break;
9346 
9347       case PNK_SWITCH:
9348         if (!emitSwitch(pn))
9349             return false;
9350         break;
9351 
9352       case PNK_WHILE:
9353         if (!emitWhile(pn))
9354             return false;
9355         break;
9356 
9357       case PNK_DOWHILE:
9358         if (!emitDo(pn))
9359             return false;
9360         break;
9361 
9362       case PNK_FOR:
9363         if (!emitFor(pn))
9364             return false;
9365         break;
9366 
9367       case PNK_COMPREHENSIONFOR:
9368         if (!emitComprehensionFor(pn))
9369             return false;
9370         break;
9371 
9372       case PNK_BREAK:
9373         if (!emitBreak(pn->as<BreakStatement>().label()))
9374             return false;
9375         break;
9376 
9377       case PNK_CONTINUE:
9378         if (!emitContinue(pn->as<ContinueStatement>().label()))
9379             return false;
9380         break;
9381 
9382       case PNK_WITH:
9383         if (!emitWith(pn))
9384             return false;
9385         break;
9386 
9387       case PNK_TRY:
9388         if (!emitTry(pn))
9389             return false;
9390         break;
9391 
9392       case PNK_CATCH:
9393         if (!emitCatch(pn))
9394             return false;
9395         break;
9396 
9397       case PNK_VAR:
9398         if (!emitDeclarationList(pn))
9399             return false;
9400         break;
9401 
9402       case PNK_RETURN:
9403         if (!emitReturn(pn))
9404             return false;
9405         break;
9406 
9407       case PNK_YIELD_STAR:
9408         if (!emitYieldStar(pn->pn_left, pn->pn_right))
9409             return false;
9410         break;
9411 
9412       case PNK_GENERATOR:
9413         if (!emit1(JSOP_GENERATOR))
9414             return false;
9415         break;
9416 
9417       case PNK_YIELD:
9418       case PNK_AWAIT:
9419         if (!emitYield(pn))
9420             return false;
9421         break;
9422 
9423       case PNK_STATEMENTLIST:
9424         if (!emitStatementList(pn))
9425             return false;
9426         break;
9427 
9428       case PNK_SEMI:
9429         if (!emitStatement(pn))
9430             return false;
9431         break;
9432 
9433       case PNK_LABEL:
9434         if (!emitLabeledStatement(&pn->as<LabeledStatement>()))
9435             return false;
9436         break;
9437 
9438       case PNK_COMMA:
9439         if (!emitSequenceExpr(pn))
9440             return false;
9441         break;
9442 
9443       case PNK_ASSIGN:
9444       case PNK_ADDASSIGN:
9445       case PNK_SUBASSIGN:
9446       case PNK_BITORASSIGN:
9447       case PNK_BITXORASSIGN:
9448       case PNK_BITANDASSIGN:
9449       case PNK_LSHASSIGN:
9450       case PNK_RSHASSIGN:
9451       case PNK_URSHASSIGN:
9452       case PNK_MULASSIGN:
9453       case PNK_DIVASSIGN:
9454       case PNK_MODASSIGN:
9455       case PNK_POWASSIGN:
9456         if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
9457             return false;
9458         break;
9459 
9460       case PNK_CONDITIONAL:
9461         if (!emitConditionalExpression(pn->as<ConditionalExpression>()))
9462             return false;
9463         break;
9464 
9465       case PNK_OR:
9466       case PNK_AND:
9467         if (!emitLogical(pn))
9468             return false;
9469         break;
9470 
9471       case PNK_ADD:
9472       case PNK_SUB:
9473       case PNK_BITOR:
9474       case PNK_BITXOR:
9475       case PNK_BITAND:
9476       case PNK_STRICTEQ:
9477       case PNK_EQ:
9478       case PNK_STRICTNE:
9479       case PNK_NE:
9480       case PNK_LT:
9481       case PNK_LE:
9482       case PNK_GT:
9483       case PNK_GE:
9484       case PNK_IN:
9485       case PNK_INSTANCEOF:
9486       case PNK_LSH:
9487       case PNK_RSH:
9488       case PNK_URSH:
9489       case PNK_STAR:
9490       case PNK_DIV:
9491       case PNK_MOD:
9492         if (!emitLeftAssociative(pn))
9493             return false;
9494         break;
9495 
9496       case PNK_POW:
9497         if (!emitRightAssociative(pn))
9498             return false;
9499         break;
9500 
9501       case PNK_TYPEOFNAME:
9502         if (!emitTypeof(pn, JSOP_TYPEOF))
9503             return false;
9504         break;
9505 
9506       case PNK_TYPEOFEXPR:
9507         if (!emitTypeof(pn, JSOP_TYPEOFEXPR))
9508             return false;
9509         break;
9510 
9511       case PNK_THROW:
9512       case PNK_VOID:
9513       case PNK_NOT:
9514       case PNK_BITNOT:
9515       case PNK_POS:
9516       case PNK_NEG:
9517         if (!emitUnary(pn))
9518             return false;
9519         break;
9520 
9521       case PNK_PREINCREMENT:
9522       case PNK_PREDECREMENT:
9523       case PNK_POSTINCREMENT:
9524       case PNK_POSTDECREMENT:
9525         if (!emitIncOrDec(pn))
9526             return false;
9527         break;
9528 
9529       case PNK_DELETENAME:
9530         if (!emitDeleteName(pn))
9531             return false;
9532         break;
9533 
9534       case PNK_DELETEPROP:
9535         if (!emitDeleteProperty(pn))
9536             return false;
9537         break;
9538 
9539       case PNK_DELETEELEM:
9540         if (!emitDeleteElement(pn))
9541             return false;
9542         break;
9543 
9544       case PNK_DELETEEXPR:
9545         if (!emitDeleteExpression(pn))
9546             return false;
9547         break;
9548 
9549       case PNK_DOT:
9550         if (pn->as<PropertyAccess>().isSuper()) {
9551             if (!emitSuperPropOp(pn, JSOP_GETPROP_SUPER))
9552                 return false;
9553         } else {
9554             if (!emitPropOp(pn, JSOP_GETPROP))
9555                 return false;
9556         }
9557         break;
9558 
9559       case PNK_ELEM:
9560         if (pn->as<PropertyByValue>().isSuper()) {
9561             if (!emitSuperElemOp(pn, JSOP_GETELEM_SUPER))
9562                 return false;
9563         } else {
9564             if (!emitElemOp(pn, JSOP_GETELEM))
9565                 return false;
9566         }
9567         break;
9568 
9569       case PNK_NEW:
9570       case PNK_TAGGED_TEMPLATE:
9571       case PNK_CALL:
9572       case PNK_GENEXP:
9573       case PNK_SUPERCALL:
9574         if (!emitCallOrNew(pn))
9575             return false;
9576         break;
9577 
9578       case PNK_LEXICALSCOPE:
9579         if (!emitLexicalScope(pn))
9580             return false;
9581         break;
9582 
9583       case PNK_CONST:
9584       case PNK_LET:
9585         if (!emitDeclarationList(pn))
9586             return false;
9587         break;
9588 
9589       case PNK_IMPORT:
9590         MOZ_ASSERT(sc->isModuleContext());
9591         break;
9592 
9593       case PNK_EXPORT:
9594         MOZ_ASSERT(sc->isModuleContext());
9595         if (pn->pn_kid->getKind() != PNK_EXPORT_SPEC_LIST) {
9596             if (!emitTree(pn->pn_kid))
9597                 return false;
9598         }
9599         break;
9600 
9601       case PNK_EXPORT_DEFAULT:
9602         MOZ_ASSERT(sc->isModuleContext());
9603         if (!emitTree(pn->pn_kid))
9604             return false;
9605         if (pn->pn_right) {
9606             if (!emitLexicalInitialization(pn->pn_right))
9607                 return false;
9608             if (!emit1(JSOP_POP))
9609                 return false;
9610         }
9611         break;
9612 
9613       case PNK_EXPORT_FROM:
9614         MOZ_ASSERT(sc->isModuleContext());
9615         break;
9616 
9617       case PNK_ARRAYPUSH:
9618         /*
9619          * The array object's stack index is in arrayCompDepth. See below
9620          * under the array initialiser code generator for array comprehension
9621          * special casing.
9622          */
9623         if (!emitTree(pn->pn_kid))
9624             return false;
9625         if (!emitDupAt(this->stackDepth - 1 - arrayCompDepth))
9626             return false;
9627         if (!emit1(JSOP_ARRAYPUSH))
9628             return false;
9629         break;
9630 
9631       case PNK_CALLSITEOBJ:
9632         if (!emitCallSiteObject(pn))
9633             return false;
9634         break;
9635 
9636       case PNK_ARRAY:
9637         if (!emitArrayLiteral(pn))
9638             return false;
9639         break;
9640 
9641       case PNK_ARRAYCOMP:
9642         if (!emitArrayComp(pn))
9643             return false;
9644         break;
9645 
9646       case PNK_OBJECT:
9647         if (!emitObject(pn))
9648             return false;
9649         break;
9650 
9651       case PNK_NAME:
9652         if (!emitGetName(pn))
9653             return false;
9654         break;
9655 
9656       case PNK_TEMPLATE_STRING_LIST:
9657         if (!emitTemplateString(pn))
9658             return false;
9659         break;
9660 
9661       case PNK_TEMPLATE_STRING:
9662       case PNK_STRING:
9663         if (!emitAtomOp(pn, JSOP_STRING))
9664             return false;
9665         break;
9666 
9667       case PNK_NUMBER:
9668         if (!emitNumberOp(pn->pn_dval))
9669             return false;
9670         break;
9671 
9672       case PNK_REGEXP:
9673         if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox())))
9674             return false;
9675         break;
9676 
9677       case PNK_TRUE:
9678       case PNK_FALSE:
9679       case PNK_NULL:
9680         if (!emit1(pn->getOp()))
9681             return false;
9682         break;
9683 
9684       case PNK_THIS:
9685         if (!emitThisLiteral(pn))
9686             return false;
9687         break;
9688 
9689       case PNK_DEBUGGER:
9690         if (!updateSourceCoordNotes(pn->pn_pos.begin))
9691             return false;
9692         if (!emit1(JSOP_DEBUGGER))
9693             return false;
9694         break;
9695 
9696       case PNK_NOP:
9697         MOZ_ASSERT(pn->getArity() == PN_NULLARY);
9698         break;
9699 
9700       case PNK_CLASS:
9701         if (!emitClass(pn))
9702             return false;
9703         break;
9704 
9705       case PNK_NEWTARGET:
9706         if (!emit1(JSOP_NEWTARGET))
9707             return false;
9708         break;
9709 
9710       case PNK_SETTHIS:
9711         if (!emitSetThis(pn))
9712             return false;
9713         break;
9714 
9715       case PNK_POSHOLDER:
9716         MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER");
9717 
9718       default:
9719         MOZ_ASSERT(0);
9720     }
9721 
9722     /* bce->emitLevel == 1 means we're last on the stack, so finish up. */
9723     if (emitLevel == 1) {
9724         if (!updateSourceCoordNotes(pn->pn_pos.end))
9725             return false;
9726     }
9727     return true;
9728 }
9729 
9730 bool
emitConditionallyExecutedTree(ParseNode * pn)9731 BytecodeEmitter::emitConditionallyExecutedTree(ParseNode* pn)
9732 {
9733     // Code that may be conditionally executed always need their own TDZ
9734     // cache.
9735     TDZCheckCache tdzCache(this);
9736     return emitTree(pn);
9737 }
9738 
9739 static bool
AllocSrcNote(ExclusiveContext * cx,SrcNotesVector & notes,unsigned * index)9740 AllocSrcNote(ExclusiveContext* cx, SrcNotesVector& notes, unsigned* index)
9741 {
9742     // Start it off moderately large to avoid repeated resizings early on.
9743     // ~99% of cases fit within 256 bytes.
9744     if (notes.capacity() == 0 && !notes.reserve(256))
9745         return false;
9746 
9747     if (!notes.growBy(1)) {
9748         ReportOutOfMemory(cx);
9749         return false;
9750     }
9751 
9752     *index = notes.length() - 1;
9753     return true;
9754 }
9755 
9756 bool
newSrcNote(SrcNoteType type,unsigned * indexp)9757 BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp)
9758 {
9759     SrcNotesVector& notes = this->notes();
9760     unsigned index;
9761     if (!AllocSrcNote(cx, notes, &index))
9762         return false;
9763 
9764     /*
9765      * Compute delta from the last annotated bytecode's offset.  If it's too
9766      * big to fit in sn, allocate one or more xdelta notes and reset sn.
9767      */
9768     ptrdiff_t offset = this->offset();
9769     ptrdiff_t delta = offset - lastNoteOffset();
9770     current->lastNoteOffset = offset;
9771     if (delta >= SN_DELTA_LIMIT) {
9772         do {
9773             ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
9774             SN_MAKE_XDELTA(&notes[index], xdelta);
9775             delta -= xdelta;
9776             if (!AllocSrcNote(cx, notes, &index))
9777                 return false;
9778         } while (delta >= SN_DELTA_LIMIT);
9779     }
9780 
9781     /*
9782      * Initialize type and delta, then allocate the minimum number of notes
9783      * needed for type's arity.  Usually, we won't need more, but if an offset
9784      * does take two bytes, setSrcNoteOffset will grow notes.
9785      */
9786     SN_MAKE_NOTE(&notes[index], type, delta);
9787     for (int n = (int)js_SrcNoteSpec[type].arity; n > 0; n--) {
9788         if (!newSrcNote(SRC_NULL))
9789             return false;
9790     }
9791 
9792     if (indexp)
9793         *indexp = index;
9794     return true;
9795 }
9796 
9797 bool
newSrcNote2(SrcNoteType type,ptrdiff_t offset,unsigned * indexp)9798 BytecodeEmitter::newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp)
9799 {
9800     unsigned index;
9801     if (!newSrcNote(type, &index))
9802         return false;
9803     if (!setSrcNoteOffset(index, 0, offset))
9804         return false;
9805     if (indexp)
9806         *indexp = index;
9807     return true;
9808 }
9809 
9810 bool
newSrcNote3(SrcNoteType type,ptrdiff_t offset1,ptrdiff_t offset2,unsigned * indexp)9811 BytecodeEmitter::newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
9812                              unsigned* indexp)
9813 {
9814     unsigned index;
9815     if (!newSrcNote(type, &index))
9816         return false;
9817     if (!setSrcNoteOffset(index, 0, offset1))
9818         return false;
9819     if (!setSrcNoteOffset(index, 1, offset2))
9820         return false;
9821     if (indexp)
9822         *indexp = index;
9823     return true;
9824 }
9825 
9826 bool
addToSrcNoteDelta(jssrcnote * sn,ptrdiff_t delta)9827 BytecodeEmitter::addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta)
9828 {
9829     /*
9830      * Called only from finishTakingSrcNotes to add to main script note
9831      * deltas, and only by a small positive amount.
9832      */
9833     MOZ_ASSERT(current == &main);
9834     MOZ_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT);
9835 
9836     ptrdiff_t base = SN_DELTA(sn);
9837     ptrdiff_t limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
9838     ptrdiff_t newdelta = base + delta;
9839     if (newdelta < limit) {
9840         SN_SET_DELTA(sn, newdelta);
9841     } else {
9842         jssrcnote xdelta;
9843         SN_MAKE_XDELTA(&xdelta, delta);
9844         if (!main.notes.insert(sn, xdelta))
9845             return false;
9846     }
9847     return true;
9848 }
9849 
9850 bool
setSrcNoteOffset(unsigned index,unsigned which,ptrdiff_t offset)9851 BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset)
9852 {
9853     if (!SN_REPRESENTABLE_OFFSET(offset)) {
9854         parser->tokenStream.reportError(JSMSG_NEED_DIET, js_script_str);
9855         return false;
9856     }
9857 
9858     SrcNotesVector& notes = this->notes();
9859 
9860     /* Find the offset numbered which (i.e., skip exactly which offsets). */
9861     jssrcnote* sn = &notes[index];
9862     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
9863     MOZ_ASSERT((int) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
9864     for (sn++; which; sn++, which--) {
9865         if (*sn & SN_4BYTE_OFFSET_FLAG)
9866             sn += 3;
9867     }
9868 
9869     /*
9870      * See if the new offset requires four bytes either by being too big or if
9871      * the offset has already been inflated (in which case, we need to stay big
9872      * to not break the srcnote encoding if this isn't the last srcnote).
9873      */
9874     if (offset > (ptrdiff_t)SN_4BYTE_OFFSET_MASK || (*sn & SN_4BYTE_OFFSET_FLAG)) {
9875         /* Maybe this offset was already set to a four-byte value. */
9876         if (!(*sn & SN_4BYTE_OFFSET_FLAG)) {
9877             /* Insert three dummy bytes that will be overwritten shortly. */
9878             jssrcnote dummy = 0;
9879             if (!(sn = notes.insert(sn, dummy)) ||
9880                 !(sn = notes.insert(sn, dummy)) ||
9881                 !(sn = notes.insert(sn, dummy)))
9882             {
9883                 ReportOutOfMemory(cx);
9884                 return false;
9885             }
9886         }
9887         *sn++ = (jssrcnote)(SN_4BYTE_OFFSET_FLAG | (offset >> 24));
9888         *sn++ = (jssrcnote)(offset >> 16);
9889         *sn++ = (jssrcnote)(offset >> 8);
9890     }
9891     *sn = (jssrcnote)offset;
9892     return true;
9893 }
9894 
9895 bool
finishTakingSrcNotes(uint32_t * out)9896 BytecodeEmitter::finishTakingSrcNotes(uint32_t* out)
9897 {
9898     MOZ_ASSERT(current == &main);
9899 
9900     unsigned prologueCount = prologue.notes.length();
9901     if (prologueCount && prologue.currentLine != firstLine) {
9902         switchToPrologue();
9903         if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(firstLine)))
9904             return false;
9905         switchToMain();
9906     } else {
9907         /*
9908          * Either no prologue srcnotes, or no line number change over prologue.
9909          * We don't need a SRC_SETLINE, but we may need to adjust the offset
9910          * of the first main note, by adding to its delta and possibly even
9911          * prepending SRC_XDELTA notes to it to account for prologue bytecodes
9912          * that came at and after the last annotated bytecode.
9913          */
9914         ptrdiff_t offset = prologueOffset() - prologue.lastNoteOffset;
9915         MOZ_ASSERT(offset >= 0);
9916         if (offset > 0 && main.notes.length() != 0) {
9917             /* NB: Use as much of the first main note's delta as we can. */
9918             jssrcnote* sn = main.notes.begin();
9919             ptrdiff_t delta = SN_IS_XDELTA(sn)
9920                             ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK)
9921                             : SN_DELTA_MASK - (*sn & SN_DELTA_MASK);
9922             if (offset < delta)
9923                 delta = offset;
9924             for (;;) {
9925                 if (!addToSrcNoteDelta(sn, delta))
9926                     return false;
9927                 offset -= delta;
9928                 if (offset == 0)
9929                     break;
9930                 delta = Min(offset, SN_XDELTA_MASK);
9931                 sn = main.notes.begin();
9932             }
9933         }
9934     }
9935 
9936     // The prologue count might have changed, so we can't reuse prologueCount.
9937     // The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
9938     // when the notes are copied to their final destination by CopySrcNotes.
9939     *out = prologue.notes.length() + main.notes.length() + 1;
9940     return true;
9941 }
9942 
9943 void
copySrcNotes(jssrcnote * destination,uint32_t nsrcnotes)9944 BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes)
9945 {
9946     unsigned prologueCount = prologue.notes.length();
9947     unsigned mainCount = main.notes.length();
9948     unsigned totalCount = prologueCount + mainCount;
9949     MOZ_ASSERT(totalCount == nsrcnotes - 1);
9950     if (prologueCount)
9951         PodCopy(destination, prologue.notes.begin(), prologueCount);
9952     PodCopy(destination + prologueCount, main.notes.begin(), mainCount);
9953     SN_MAKE_TERMINATOR(&destination[totalCount]);
9954 }
9955 
9956 void
finish(ConstArray * array)9957 CGConstList::finish(ConstArray* array)
9958 {
9959     MOZ_ASSERT(length() == array->length);
9960 
9961     for (unsigned i = 0; i < length(); i++)
9962         array->vector[i] = list[i];
9963 }
9964 
9965 bool
isAdded(ObjectBox * objbox)9966 CGObjectList::isAdded(ObjectBox* objbox)
9967 {
9968     // An objbox added to CGObjectList as non-first element has non-null
9969     // emitLink member.  The first element has null emitLink.
9970     // Check for firstbox to cover the first element.
9971     return objbox->emitLink || objbox == firstbox;
9972 }
9973 
9974 /*
9975  * Find the index of the given object for code generator.
9976  *
9977  * Since the emitter refers to each parsed object only once, for the index we
9978  * use the number of already indexed objects. We also add the object to a list
9979  * to convert the list to a fixed-size array when we complete code generation,
9980  * see js::CGObjectList::finish below.
9981  */
9982 unsigned
add(ObjectBox * objbox)9983 CGObjectList::add(ObjectBox* objbox)
9984 {
9985     if (isAdded(objbox))
9986         return indexOf(objbox->object);
9987 
9988     objbox->emitLink = lastbox;
9989     lastbox = objbox;
9990 
9991     // See the comment in CGObjectList::isAdded.
9992     if (!firstbox)
9993         firstbox = objbox;
9994     return length++;
9995 }
9996 
9997 unsigned
indexOf(JSObject * obj)9998 CGObjectList::indexOf(JSObject* obj)
9999 {
10000     MOZ_ASSERT(length > 0);
10001     unsigned index = length - 1;
10002     for (ObjectBox* box = lastbox; box->object != obj; box = box->emitLink)
10003         index--;
10004     return index;
10005 }
10006 
10007 void
finish(ObjectArray * array)10008 CGObjectList::finish(ObjectArray* array)
10009 {
10010     MOZ_ASSERT(length <= INDEX_LIMIT);
10011     MOZ_ASSERT(length == array->length);
10012 
10013     js::GCPtrObject* cursor = array->vector + array->length;
10014     ObjectBox* objbox = lastbox;
10015     do {
10016         --cursor;
10017         MOZ_ASSERT(!*cursor);
10018         MOZ_ASSERT(objbox->object->isTenured());
10019         *cursor = objbox->object;
10020 
10021         ObjectBox* tmp = objbox->emitLink;
10022         // Clear emitLink for CGObjectList::isAdded.
10023         objbox->emitLink = nullptr;
10024         objbox = tmp;
10025     } while (objbox != nullptr);
10026     MOZ_ASSERT(cursor == array->vector);
10027 }
10028 
10029 ObjectBox*
find(uint32_t index)10030 CGObjectList::find(uint32_t index)
10031 {
10032     MOZ_ASSERT(index < length);
10033     ObjectBox* box = lastbox;
10034     for (unsigned n = length - 1; n > index; n--)
10035         box = box->emitLink;
10036     return box;
10037 }
10038 
10039 void
finish(ScopeArray * array)10040 CGScopeList::finish(ScopeArray* array)
10041 {
10042     MOZ_ASSERT(length() <= INDEX_LIMIT);
10043     MOZ_ASSERT(length() == array->length);
10044     for (uint32_t i = 0; i < length(); i++)
10045         array->vector[i].init(vector[i]);
10046 }
10047 
10048 bool
append(JSTryNoteKind kind,uint32_t stackDepth,size_t start,size_t end)10049 CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end)
10050 {
10051     MOZ_ASSERT(start <= end);
10052     MOZ_ASSERT(size_t(uint32_t(start)) == start);
10053     MOZ_ASSERT(size_t(uint32_t(end)) == end);
10054 
10055     JSTryNote note;
10056     note.kind = kind;
10057     note.stackDepth = stackDepth;
10058     note.start = uint32_t(start);
10059     note.length = uint32_t(end - start);
10060 
10061     return list.append(note);
10062 }
10063 
10064 void
finish(TryNoteArray * array)10065 CGTryNoteList::finish(TryNoteArray* array)
10066 {
10067     MOZ_ASSERT(length() == array->length);
10068 
10069     for (unsigned i = 0; i < length(); i++)
10070         array->vector[i] = list[i];
10071 }
10072 
10073 bool
append(uint32_t scopeIndex,uint32_t offset,bool inPrologue,uint32_t parent)10074 CGScopeNoteList::append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
10075                         uint32_t parent)
10076 {
10077     CGScopeNote note;
10078     mozilla::PodZero(&note);
10079 
10080     note.index = scopeIndex;
10081     note.start = offset;
10082     note.parent = parent;
10083     note.startInPrologue = inPrologue;
10084 
10085     return list.append(note);
10086 }
10087 
10088 void
recordEnd(uint32_t index,uint32_t offset,bool inPrologue)10089 CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset, bool inPrologue)
10090 {
10091     MOZ_ASSERT(index < length());
10092     MOZ_ASSERT(list[index].length == 0);
10093     list[index].end = offset;
10094     list[index].endInPrologue = inPrologue;
10095 }
10096 
10097 void
finish(ScopeNoteArray * array,uint32_t prologueLength)10098 CGScopeNoteList::finish(ScopeNoteArray* array, uint32_t prologueLength)
10099 {
10100     MOZ_ASSERT(length() == array->length);
10101 
10102     for (unsigned i = 0; i < length(); i++) {
10103         if (!list[i].startInPrologue)
10104             list[i].start += prologueLength;
10105         if (!list[i].endInPrologue && list[i].end != UINT32_MAX)
10106             list[i].end += prologueLength;
10107         MOZ_ASSERT(list[i].end >= list[i].start);
10108         list[i].length = list[i].end - list[i].start;
10109         array->vector[i] = list[i];
10110     }
10111 }
10112 
10113 void
finish(YieldOffsetArray & array,uint32_t prologueLength)10114 CGYieldOffsetList::finish(YieldOffsetArray& array, uint32_t prologueLength)
10115 {
10116     MOZ_ASSERT(length() == array.length());
10117 
10118     for (unsigned i = 0; i < length(); i++)
10119         array[i] = prologueLength + list[i];
10120 }
10121 
10122 /*
10123  * We should try to get rid of offsetBias (always 0 or 1, where 1 is
10124  * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR.
10125  */
10126 const JSSrcNoteSpec js_SrcNoteSpec[] = {
10127 #define DEFINE_SRC_NOTE_SPEC(sym, name, arity) { name, arity },
10128     FOR_EACH_SRC_NOTE_TYPE(DEFINE_SRC_NOTE_SPEC)
10129 #undef DEFINE_SRC_NOTE_SPEC
10130 };
10131 
10132 static int
SrcNoteArity(jssrcnote * sn)10133 SrcNoteArity(jssrcnote* sn)
10134 {
10135     MOZ_ASSERT(SN_TYPE(sn) < SRC_LAST);
10136     return js_SrcNoteSpec[SN_TYPE(sn)].arity;
10137 }
10138 
JS_FRIEND_API(unsigned)10139 JS_FRIEND_API(unsigned)
10140 js::SrcNoteLength(jssrcnote* sn)
10141 {
10142     unsigned arity;
10143     jssrcnote* base;
10144 
10145     arity = SrcNoteArity(sn);
10146     for (base = sn++; arity; sn++, arity--) {
10147         if (*sn & SN_4BYTE_OFFSET_FLAG)
10148             sn += 3;
10149     }
10150     return sn - base;
10151 }
10152 
JS_FRIEND_API(ptrdiff_t)10153 JS_FRIEND_API(ptrdiff_t)
10154 js::GetSrcNoteOffset(jssrcnote* sn, unsigned which)
10155 {
10156     /* Find the offset numbered which (i.e., skip exactly which offsets). */
10157     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
10158     MOZ_ASSERT((int) which < SrcNoteArity(sn));
10159     for (sn++; which; sn++, which--) {
10160         if (*sn & SN_4BYTE_OFFSET_FLAG)
10161             sn += 3;
10162     }
10163     if (*sn & SN_4BYTE_OFFSET_FLAG) {
10164         return (ptrdiff_t)(((uint32_t)(sn[0] & SN_4BYTE_OFFSET_MASK) << 24)
10165                            | (sn[1] << 16)
10166                            | (sn[2] << 8)
10167                            | sn[3]);
10168     }
10169     return (ptrdiff_t)*sn;
10170 }
10171