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