1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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 #include "frontend/FunctionEmitter.h"
8 
9 #include "mozilla/Assertions.h"  // MOZ_ASSERT
10 
11 #include "frontend/AsyncEmitter.h"         // AsyncEmitter
12 #include "frontend/BytecodeEmitter.h"      // BytecodeEmitter
13 #include "frontend/FunctionSyntaxKind.h"   // FunctionSyntaxKind
14 #include "frontend/ModuleSharedContext.h"  // ModuleSharedContext
15 #include "frontend/NameAnalysisTypes.h"    // NameLocation
16 #include "frontend/NameOpEmitter.h"        // NameOpEmitter
17 #include "frontend/SharedContext.h"        // SharedContext
18 #include "vm/ModuleBuilder.h"              // ModuleBuilder
19 #include "vm/Opcodes.h"                    // JSOp
20 #include "vm/Scope.h"                      // BindingKind
21 
22 using namespace js;
23 using namespace js::frontend;
24 
25 using mozilla::Maybe;
26 using mozilla::Some;
27 
FunctionEmitter(BytecodeEmitter * bce,FunctionBox * funbox,FunctionSyntaxKind syntaxKind,IsHoisted isHoisted)28 FunctionEmitter::FunctionEmitter(BytecodeEmitter* bce, FunctionBox* funbox,
29                                  FunctionSyntaxKind syntaxKind,
30                                  IsHoisted isHoisted)
31     : bce_(bce),
32       funbox_(funbox),
33       name_(funbox_->explicitName()),
34       syntaxKind_(syntaxKind),
35       isHoisted_(isHoisted) {}
36 
prepareForNonLazy()37 bool FunctionEmitter::prepareForNonLazy() {
38   MOZ_ASSERT(state_ == State::Start);
39 
40   MOZ_ASSERT(funbox_->isInterpreted());
41   MOZ_ASSERT(funbox_->emitBytecode);
42   MOZ_ASSERT(!funbox_->wasEmittedByEnclosingScript());
43 
44   //                [stack]
45 
46   funbox_->setWasEmittedByEnclosingScript(true);
47 
48 #ifdef DEBUG
49   state_ = State::NonLazy;
50 #endif
51   return true;
52 }
53 
emitNonLazyEnd()54 bool FunctionEmitter::emitNonLazyEnd() {
55   MOZ_ASSERT(state_ == State::NonLazy);
56 
57   //                [stack]
58 
59   if (!emitFunction()) {
60     //              [stack] FUN?
61     return false;
62   }
63 
64 #ifdef DEBUG
65   state_ = State::End;
66 #endif
67   return true;
68 }
69 
emitLazy()70 bool FunctionEmitter::emitLazy() {
71   MOZ_ASSERT(state_ == State::Start);
72 
73   MOZ_ASSERT(funbox_->isInterpreted());
74   MOZ_ASSERT(!funbox_->emitBytecode);
75   MOZ_ASSERT(!funbox_->wasEmittedByEnclosingScript());
76 
77   //                [stack]
78 
79   funbox_->setWasEmittedByEnclosingScript(true);
80 
81   // Prepare to update the inner lazy script now that it's parent is fully
82   // compiled. These updates will be applied in UpdateEmittedInnerFunctions().
83   funbox_->setEnclosingScopeForInnerLazyFunction(bce_->innermostScopeIndex());
84 
85   if (!emitFunction()) {
86     //              [stack] FUN?
87     return false;
88   }
89 
90 #ifdef DEBUG
91   state_ = State::End;
92 #endif
93   return true;
94 }
95 
emitAgain()96 bool FunctionEmitter::emitAgain() {
97   MOZ_ASSERT(state_ == State::Start);
98   MOZ_ASSERT(funbox_->wasEmittedByEnclosingScript());
99 
100   //                [stack]
101 
102   // Annex B block-scoped functions are hoisted like any other assignment
103   // that assigns the function to the outer 'var' binding.
104   if (!funbox_->isAnnexB) {
105 #ifdef DEBUG
106     state_ = State::End;
107 #endif
108     return true;
109   }
110 
111   // Get the location of the 'var' binding in the body scope. The
112   // name must be found, else there is a bug in the Annex B handling
113   // in Parser.
114   //
115   // In sloppy eval contexts, this location is dynamic.
116   Maybe<NameLocation> lhsLoc =
117       bce_->locationOfNameBoundInScope(name_, bce_->varEmitterScope);
118 
119   // If there are parameter expressions, the var name could be a
120   // parameter.
121   if (!lhsLoc && bce_->sc->isFunctionBox() &&
122       bce_->sc->asFunctionBox()->functionHasExtraBodyVarScope()) {
123     lhsLoc = bce_->locationOfNameBoundInScope(
124         name_, bce_->varEmitterScope->enclosingInFrame());
125   }
126 
127   if (!lhsLoc) {
128     lhsLoc = Some(NameLocation::DynamicAnnexBVar());
129   } else {
130     MOZ_ASSERT(lhsLoc->bindingKind() == BindingKind::Var ||
131                lhsLoc->bindingKind() == BindingKind::FormalParameter ||
132                (lhsLoc->bindingKind() == BindingKind::Let &&
133                 bce_->sc->asFunctionBox()->hasParameterExprs));
134   }
135 
136   NameOpEmitter noe(bce_, name_, *lhsLoc,
137                     NameOpEmitter::Kind::SimpleAssignment);
138   if (!noe.prepareForRhs()) {
139     //              [stack]
140     return false;
141   }
142 
143   if (!bce_->emitGetName(name_)) {
144     //              [stack] FUN
145     return false;
146   }
147 
148   if (!noe.emitAssignment()) {
149     //              [stack] FUN
150     return false;
151   }
152 
153   if (!bce_->emit1(JSOp::Pop)) {
154     //              [stack]
155     return false;
156   }
157 
158 #ifdef DEBUG
159   state_ = State::End;
160 #endif
161   return true;
162 }
163 
emitAsmJSModule()164 bool FunctionEmitter::emitAsmJSModule() {
165   MOZ_ASSERT(state_ == State::Start);
166 
167   MOZ_ASSERT(!funbox_->wasEmittedByEnclosingScript());
168   MOZ_ASSERT(funbox_->isAsmJSModule());
169 
170   //                [stack]
171 
172   funbox_->setWasEmittedByEnclosingScript(true);
173 
174   if (!emitFunction()) {
175     //              [stack]
176     return false;
177   }
178 
179 #ifdef DEBUG
180   state_ = State::End;
181 #endif
182   return true;
183 }
184 
emitFunction()185 bool FunctionEmitter::emitFunction() {
186   // Make the function object a literal in the outer script's pool.
187   GCThingIndex index;
188   if (!bce_->perScriptData().gcThingList().append(funbox_, &index)) {
189     return false;
190   }
191 
192   //                [stack]
193 
194   if (isHoisted_ == IsHoisted::No) {
195     return emitNonHoisted(index);
196     //              [stack] FUN?
197   }
198 
199   bool topLevelFunction;
200   if (bce_->sc->isFunctionBox() ||
201       (bce_->sc->isEvalContext() && bce_->sc->strict())) {
202     // No nested functions inside other functions are top-level.
203     topLevelFunction = false;
204   } else {
205     // In sloppy eval scripts, top-level functions are accessed dynamically.
206     // In global and module scripts, top-level functions are those bound in
207     // the var scope.
208     NameLocation loc = bce_->lookupName(name_);
209     topLevelFunction = loc.kind() == NameLocation::Kind::Dynamic ||
210                        loc.bindingKind() == BindingKind::Var;
211   }
212 
213   if (topLevelFunction) {
214     return emitTopLevelFunction(index);
215     //              [stack]
216   }
217 
218   return emitHoisted(index);
219   //                [stack]
220 }
221 
emitNonHoisted(GCThingIndex index)222 bool FunctionEmitter::emitNonHoisted(GCThingIndex index) {
223   // Non-hoisted functions simply emit their respective op.
224 
225   //                [stack]
226 
227   // JSOp::LambdaArrow is always preceded by a opcode that pushes new.target.
228   // See below.
229   MOZ_ASSERT(funbox_->isArrow() == (syntaxKind_ == FunctionSyntaxKind::Arrow));
230 
231   if (funbox_->isArrow()) {
232     if (!emitNewTargetForArrow()) {
233       //            [stack] NEW.TARGET/NULL
234       return false;
235     }
236   }
237 
238   if (syntaxKind_ == FunctionSyntaxKind::DerivedClassConstructor) {
239     //              [stack] PROTO
240     if (!bce_->emitGCIndexOp(JSOp::FunWithProto, index)) {
241       //            [stack] FUN
242       return false;
243     }
244     return true;
245   }
246 
247   // This is a FunctionExpression, ArrowFunctionExpression, or class
248   // constructor. Emit the single instruction (without location info).
249   JSOp op = syntaxKind_ == FunctionSyntaxKind::Arrow ? JSOp::LambdaArrow
250                                                      : JSOp::Lambda;
251   if (!bce_->emitGCIndexOp(op, index)) {
252     //              [stack] FUN
253     return false;
254   }
255 
256   return true;
257 }
258 
emitHoisted(GCThingIndex index)259 bool FunctionEmitter::emitHoisted(GCThingIndex index) {
260   MOZ_ASSERT(syntaxKind_ == FunctionSyntaxKind::Statement);
261 
262   //                [stack]
263 
264   // For functions nested within functions and blocks, make a lambda and
265   // initialize the binding name of the function in the current scope.
266 
267   NameOpEmitter noe(bce_, name_, NameOpEmitter::Kind::Initialize);
268   if (!noe.prepareForRhs()) {
269     //              [stack]
270     return false;
271   }
272 
273   if (!bce_->emitGCIndexOp(JSOp::Lambda, index)) {
274     //              [stack] FUN
275     return false;
276   }
277 
278   if (!noe.emitAssignment()) {
279     //              [stack] FUN
280     return false;
281   }
282 
283   if (!bce_->emit1(JSOp::Pop)) {
284     //              [stack]
285     return false;
286   }
287 
288   return true;
289 }
290 
emitTopLevelFunction(GCThingIndex index)291 bool FunctionEmitter::emitTopLevelFunction(GCThingIndex index) {
292   //                [stack]
293 
294   if (bce_->sc->isModuleContext()) {
295     // For modules, we record the function and instantiate the binding
296     // during ModuleInstantiate(), before the script is run.
297     return bce_->sc->asModuleContext()->builder.noteFunctionDeclaration(
298         bce_->cx, index);
299   }
300 
301   MOZ_ASSERT(bce_->sc->isGlobalContext() || bce_->sc->isEvalContext());
302   MOZ_ASSERT(syntaxKind_ == FunctionSyntaxKind::Statement);
303   MOZ_ASSERT(bce_->inPrologue());
304 
305   // NOTE: The `index` is not directly stored as an opcode, but we collect the
306   // range of indices in `BytecodeEmitter::emitDeclarationInstantiation` instead
307   // of discrete indices.
308   (void)index;
309 
310   return true;
311 }
312 
emitNewTargetForArrow()313 bool FunctionEmitter::emitNewTargetForArrow() {
314   //                [stack]
315 
316   if (bce_->sc->allowNewTarget()) {
317     if (!bce_->emit1(JSOp::NewTarget)) {
318       //            [stack] NEW.TARGET
319       return false;
320     }
321   } else {
322     if (!bce_->emit1(JSOp::Null)) {
323       //            [stack] NULL
324       return false;
325     }
326   }
327 
328   return true;
329 }
330 
prepareForParameters()331 bool FunctionScriptEmitter::prepareForParameters() {
332   MOZ_ASSERT(state_ == State::Start);
333   MOZ_ASSERT(bce_->inPrologue());
334 
335   //                [stack]
336 
337   if (paramStart_) {
338     bce_->setScriptStartOffsetIfUnset(*paramStart_);
339   }
340 
341   // The ordering of these EmitterScopes is important. The named lambda
342   // scope needs to enclose the function scope needs to enclose the extra
343   // var scope.
344 
345   if (funbox_->namedLambdaBindings()) {
346     namedLambdaEmitterScope_.emplace(bce_);
347     if (!namedLambdaEmitterScope_->enterNamedLambda(bce_, funbox_)) {
348       return false;
349     }
350   }
351 
352   if (funbox_->needsPromiseResult()) {
353     asyncEmitter_.emplace(bce_);
354   }
355 
356   if (bodyEnd_) {
357     bce_->setFunctionBodyEndPos(*bodyEnd_);
358   }
359 
360   if (paramStart_) {
361     if (!bce_->updateLineNumberNotes(*paramStart_)) {
362       return false;
363     }
364   }
365 
366   tdzCache_.emplace(bce_);
367   functionEmitterScope_.emplace(bce_);
368 
369   if (funbox_->hasParameterExprs) {
370     // There's parameter exprs, emit them in the main section.
371     //
372     // One caveat is that Debugger considers ops in the prologue to be
373     // unreachable (i.e. cannot set a breakpoint on it). If there are no
374     // parameter exprs, any unobservable environment ops (like pushing the
375     // call object, setting '.this', etc) need to go in the prologue, else it
376     // messes up breakpoint tests.
377     bce_->switchToMain();
378   }
379 
380   if (!functionEmitterScope_->enterFunction(bce_, funbox_)) {
381     return false;
382   }
383 
384   if (!bce_->emitInitializeFunctionSpecialNames()) {
385     //              [stack]
386     return false;
387   }
388 
389   if (!funbox_->hasParameterExprs) {
390     bce_->switchToMain();
391   }
392 
393   if (funbox_->needsPromiseResult()) {
394     if (funbox_->hasParameterExprs) {
395       if (!asyncEmitter_->prepareForParamsWithExpression()) {
396         return false;
397       }
398     } else {
399       if (!asyncEmitter_->prepareForParamsWithoutExpression()) {
400         return false;
401       }
402     }
403   }
404 
405 #ifdef DEBUG
406   state_ = State::Parameters;
407 #endif
408   return true;
409 }
410 
prepareForBody()411 bool FunctionScriptEmitter::prepareForBody() {
412   MOZ_ASSERT(state_ == State::Parameters);
413 
414   //                [stack]
415 
416   if (funbox_->needsPromiseResult()) {
417     if (!asyncEmitter_->emitParamsEpilogue()) {
418       return false;
419     }
420   }
421 
422   if (!emitExtraBodyVarScope()) {
423     //              [stack]
424     return false;
425   }
426 
427   if (funbox_->needsPromiseResult()) {
428     if (!asyncEmitter_->prepareForBody()) {
429       return false;
430     }
431   }
432 
433   if (funbox_->isClassConstructor()) {
434     if (!funbox_->isDerivedClassConstructor()) {
435       if (!bce_->emitInitializeInstanceMembers()) {
436         //          [stack]
437         return false;
438       }
439     }
440   }
441 
442 #ifdef DEBUG
443   state_ = State::Body;
444 #endif
445   return true;
446 }
447 
emitExtraBodyVarScope()448 bool FunctionScriptEmitter::emitExtraBodyVarScope() {
449   //                [stack]
450 
451   if (!funbox_->functionHasExtraBodyVarScope()) {
452     return true;
453   }
454 
455   extraBodyVarEmitterScope_.emplace(bce_);
456   if (!extraBodyVarEmitterScope_->enterFunctionExtraBodyVar(bce_, funbox_)) {
457     return false;
458   }
459 
460   if (!funbox_->extraVarScopeBindings() || !funbox_->functionScopeBindings()) {
461     return true;
462   }
463 
464   // After emitting expressions for all parameters, copy over any formal
465   // parameters which have been redeclared as vars. For example, in the
466   // following, the var y in the body scope is 42:
467   //
468   //   function f(x, y = 42) { var y; }
469   //
470   for (ParserBindingIter bi(*funbox_->functionScopeBindings(), true); bi;
471        bi++) {
472     auto name = bi.name();
473 
474     // There may not be a var binding of the same name.
475     if (!bce_->locationOfNameBoundInScope(name,
476                                           extraBodyVarEmitterScope_.ptr())) {
477       continue;
478     }
479 
480     // The '.this' and '.generator' function special
481     // bindings should never appear in the extra var
482     // scope. 'arguments', however, may.
483     MOZ_ASSERT(name != TaggedParserAtomIndex::WellKnown::dotThis() &&
484                name != TaggedParserAtomIndex::WellKnown::dotGenerator());
485 
486     NameOpEmitter noe(bce_, name, NameOpEmitter::Kind::Initialize);
487     if (!noe.prepareForRhs()) {
488       //            [stack]
489       return false;
490     }
491 
492     NameLocation paramLoc =
493         *bce_->locationOfNameBoundInScope(name, functionEmitterScope_.ptr());
494     if (!bce_->emitGetNameAtLocation(name, paramLoc)) {
495       //            [stack] VAL
496       return false;
497     }
498 
499     if (!noe.emitAssignment()) {
500       //            [stack] VAL
501       return false;
502     }
503 
504     if (!bce_->emit1(JSOp::Pop)) {
505       //            [stack]
506       return false;
507     }
508   }
509 
510   return true;
511 }
512 
emitEndBody()513 bool FunctionScriptEmitter::emitEndBody() {
514   MOZ_ASSERT(state_ == State::Body);
515   //                [stack]
516 
517   if (funbox_->needsFinalYield()) {
518     // If we fall off the end of a generator, do a final yield.
519     if (funbox_->needsIteratorResult()) {
520       MOZ_ASSERT(!funbox_->needsPromiseResult());
521       // Emit final yield bytecode for generators, for example:
522       // function gen * () { ... }
523       if (!bce_->emitPrepareIteratorResult()) {
524         //          [stack] RESULT
525         return false;
526       }
527 
528       if (!bce_->emit1(JSOp::Undefined)) {
529         //          [stack] RESULT? UNDEF
530         return false;
531       }
532 
533       if (!bce_->emitFinishIteratorResult(true)) {
534         //          [stack] RESULT
535         return false;
536       }
537 
538       if (!bce_->emit1(JSOp::SetRval)) {
539         //          [stack]
540         return false;
541       }
542 
543       if (!bce_->emitGetDotGeneratorInInnermostScope()) {
544         //          [stack] GEN
545         return false;
546       }
547 
548       // No need to check for finally blocks, etc as in EmitReturn.
549       if (!bce_->emitYieldOp(JSOp::FinalYieldRval)) {
550         //          [stack]
551         return false;
552       }
553     } else if (funbox_->needsPromiseResult()) {
554       // Emit final yield bytecode for async functions, for example:
555       // async function deferred() { ... }
556       if (!asyncEmitter_->emitEnd()) {
557         return false;
558       }
559     } else {
560       // Emit final yield bytecode for async generators, for example:
561       // async function asyncgen * () { ... }
562       if (!bce_->emit1(JSOp::Undefined)) {
563         //          [stack] RESULT? UNDEF
564         return false;
565       }
566 
567       if (!bce_->emit1(JSOp::SetRval)) {
568         //          [stack]
569         return false;
570       }
571 
572       if (!bce_->emitGetDotGeneratorInInnermostScope()) {
573         //          [stack] GEN
574         return false;
575       }
576 
577       // No need to check for finally blocks, etc as in EmitReturn.
578       if (!bce_->emitYieldOp(JSOp::FinalYieldRval)) {
579         //          [stack]
580         return false;
581       }
582     }
583   } else {
584     // Non-generator functions just return |undefined|. The
585     // JSOp::RetRval emitted below will do that, except if the
586     // script has a finally block: there can be a non-undefined
587     // value in the return value slot. Make sure the return value
588     // is |undefined|.
589     if (bce_->hasTryFinally) {
590       if (!bce_->emit1(JSOp::Undefined)) {
591         //          [stack] UNDEF
592         return false;
593       }
594       if (!bce_->emit1(JSOp::SetRval)) {
595         //          [stack]
596         return false;
597       }
598     }
599   }
600 
601   // Execute |CheckReturn| right before exiting the class constructor.
602   if (funbox_->isDerivedClassConstructor()) {
603     if (!bce_->emitJumpTargetAndPatch(bce_->endOfDerivedClassConstructorBody)) {
604       return false;
605     }
606 
607     if (!bce_->emitCheckDerivedClassConstructorReturn()) {
608       //            [stack]
609       return false;
610     }
611   }
612 
613   if (extraBodyVarEmitterScope_) {
614     if (!extraBodyVarEmitterScope_->leave(bce_)) {
615       return false;
616     }
617 
618     extraBodyVarEmitterScope_.reset();
619   }
620 
621   if (!functionEmitterScope_->leave(bce_)) {
622     return false;
623   }
624   functionEmitterScope_.reset();
625   tdzCache_.reset();
626 
627   if (bodyEnd_) {
628     if (!bce_->updateSourceCoordNotes(*bodyEnd_)) {
629       return false;
630     }
631   }
632 
633   // We only want to mark the end of a function as a breakable position if
634   // there is token there that the user can easily associate with the function
635   // as a whole. Since arrow function single-expression bodies have no closing
636   // curly bracket, we do not place a breakpoint at their end position.
637   if (!funbox_->hasExprBody()) {
638     if (!bce_->markSimpleBreakpoint()) {
639       return false;
640     }
641   }
642 
643   // Always end the script with a JSOp::RetRval. Some other parts of the
644   // codebase depend on this opcode,
645   // e.g. InterpreterRegs::setToEndOfScript.
646   if (!bce_->emitReturnRval()) {
647     //              [stack]
648     return false;
649   }
650 
651   if (namedLambdaEmitterScope_) {
652     if (!namedLambdaEmitterScope_->leave(bce_)) {
653       return false;
654     }
655     namedLambdaEmitterScope_.reset();
656   }
657 
658 #ifdef DEBUG
659   state_ = State::EndBody;
660 #endif
661   return true;
662 }
663 
intoStencil()664 bool FunctionScriptEmitter::intoStencil() {
665   MOZ_ASSERT(state_ == State::EndBody);
666 
667   if (!bce_->intoScriptStencil(funbox_->index())) {
668     return false;
669   }
670 
671 #ifdef DEBUG
672   state_ = State::End;
673 #endif
674 
675   return true;
676 }
677 
FunctionParamsEmitter(BytecodeEmitter * bce,FunctionBox * funbox)678 FunctionParamsEmitter::FunctionParamsEmitter(BytecodeEmitter* bce,
679                                              FunctionBox* funbox)
680     : bce_(bce),
681       funbox_(funbox),
682       functionEmitterScope_(bce_->innermostEmitterScope()) {}
683 
emitSimple(TaggedParserAtomIndex paramName)684 bool FunctionParamsEmitter::emitSimple(TaggedParserAtomIndex paramName) {
685   MOZ_ASSERT(state_ == State::Start);
686 
687   //                [stack]
688 
689   if (funbox_->hasParameterExprs) {
690     if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
691       //            [stack] ARG
692       return false;
693     }
694 
695     if (!emitAssignment(paramName)) {
696       //            [stack]
697       return false;
698     }
699   }
700 
701   argSlot_++;
702   return true;
703 }
704 
prepareForDefault()705 bool FunctionParamsEmitter::prepareForDefault() {
706   MOZ_ASSERT(state_ == State::Start);
707 
708   //                [stack]
709 
710   if (!prepareForInitializer()) {
711     //              [stack]
712     return false;
713   }
714 
715 #ifdef DEBUG
716   state_ = State::Default;
717 #endif
718   return true;
719 }
720 
emitDefaultEnd(TaggedParserAtomIndex paramName)721 bool FunctionParamsEmitter::emitDefaultEnd(TaggedParserAtomIndex paramName) {
722   MOZ_ASSERT(state_ == State::Default);
723 
724   //                [stack] DEFAULT
725 
726   if (!emitInitializerEnd()) {
727     //              [stack] ARG/DEFAULT
728     return false;
729   }
730   if (!emitAssignment(paramName)) {
731     //              [stack]
732     return false;
733   }
734 
735   argSlot_++;
736 
737 #ifdef DEBUG
738   state_ = State::Start;
739 #endif
740   return true;
741 }
742 
prepareForDestructuring()743 bool FunctionParamsEmitter::prepareForDestructuring() {
744   MOZ_ASSERT(state_ == State::Start);
745 
746   //                [stack]
747 
748   if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
749     //              [stack] ARG
750     return false;
751   }
752 
753 #ifdef DEBUG
754   state_ = State::Destructuring;
755 #endif
756   return true;
757 }
758 
emitDestructuringEnd()759 bool FunctionParamsEmitter::emitDestructuringEnd() {
760   MOZ_ASSERT(state_ == State::Destructuring);
761 
762   //                [stack] ARG
763 
764   if (!bce_->emit1(JSOp::Pop)) {
765     //              [stack]
766     return false;
767   }
768 
769   argSlot_++;
770 
771 #ifdef DEBUG
772   state_ = State::Start;
773 #endif
774   return true;
775 }
776 
prepareForDestructuringDefaultInitializer()777 bool FunctionParamsEmitter::prepareForDestructuringDefaultInitializer() {
778   MOZ_ASSERT(state_ == State::Start);
779 
780   //                [stack]
781 
782   if (!prepareForInitializer()) {
783     //              [stack]
784     return false;
785   }
786 
787 #ifdef DEBUG
788   state_ = State::DestructuringDefaultInitializer;
789 #endif
790   return true;
791 }
792 
prepareForDestructuringDefault()793 bool FunctionParamsEmitter::prepareForDestructuringDefault() {
794   MOZ_ASSERT(state_ == State::DestructuringDefaultInitializer);
795 
796   //                [stack] DEFAULT
797 
798   if (!emitInitializerEnd()) {
799     //              [stack] ARG/DEFAULT
800     return false;
801   }
802 
803 #ifdef DEBUG
804   state_ = State::DestructuringDefault;
805 #endif
806   return true;
807 }
808 
emitDestructuringDefaultEnd()809 bool FunctionParamsEmitter::emitDestructuringDefaultEnd() {
810   MOZ_ASSERT(state_ == State::DestructuringDefault);
811 
812   //                [stack] ARG/DEFAULT
813 
814   if (!bce_->emit1(JSOp::Pop)) {
815     //              [stack]
816     return false;
817   }
818 
819   argSlot_++;
820 
821 #ifdef DEBUG
822   state_ = State::Start;
823 #endif
824   return true;
825 }
826 
emitRest(TaggedParserAtomIndex paramName)827 bool FunctionParamsEmitter::emitRest(TaggedParserAtomIndex paramName) {
828   MOZ_ASSERT(state_ == State::Start);
829 
830   //                [stack]
831 
832   if (!emitRestArray()) {
833     //              [stack] REST
834     return false;
835   }
836   if (!emitAssignment(paramName)) {
837     //              [stack]
838     return false;
839   }
840 
841 #ifdef DEBUG
842   state_ = State::End;
843 #endif
844   return true;
845 }
846 
prepareForDestructuringRest()847 bool FunctionParamsEmitter::prepareForDestructuringRest() {
848   MOZ_ASSERT(state_ == State::Start);
849 
850   //                [stack]
851 
852   if (!emitRestArray()) {
853     //              [stack] REST
854     return false;
855   }
856 
857 #ifdef DEBUG
858   state_ = State::DestructuringRest;
859 #endif
860   return true;
861 }
862 
emitDestructuringRestEnd()863 bool FunctionParamsEmitter::emitDestructuringRestEnd() {
864   MOZ_ASSERT(state_ == State::DestructuringRest);
865 
866   //                [stack] REST
867 
868   if (!bce_->emit1(JSOp::Pop)) {
869     //              [stack]
870     return false;
871   }
872 
873 #ifdef DEBUG
874   state_ = State::End;
875 #endif
876   return true;
877 }
878 
prepareForInitializer()879 bool FunctionParamsEmitter::prepareForInitializer() {
880   //                [stack]
881 
882   // If we have an initializer, emit the initializer and assign it
883   // to the argument slot. TDZ is taken care of afterwards.
884   MOZ_ASSERT(funbox_->hasParameterExprs);
885   if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
886     //              [stack] ARG
887     return false;
888   }
889   default_.emplace(bce_);
890   if (!default_->prepareForDefault()) {
891     //              [stack]
892     return false;
893   }
894   return true;
895 }
896 
emitInitializerEnd()897 bool FunctionParamsEmitter::emitInitializerEnd() {
898   //                [stack] DEFAULT
899 
900   if (!default_->emitEnd()) {
901     //              [stack] ARG/DEFAULT
902     return false;
903   }
904   default_.reset();
905   return true;
906 }
907 
emitRestArray()908 bool FunctionParamsEmitter::emitRestArray() {
909   //                [stack]
910 
911   if (!bce_->emit1(JSOp::Rest)) {
912     //              [stack] REST
913     return false;
914   }
915   return true;
916 }
917 
emitAssignment(TaggedParserAtomIndex paramName)918 bool FunctionParamsEmitter::emitAssignment(TaggedParserAtomIndex paramName) {
919   //                [stack] ARG
920 
921   NameLocation paramLoc =
922       *bce_->locationOfNameBoundInScope(paramName, functionEmitterScope_);
923 
924   // RHS is already pushed in the caller side.
925   // Make sure prepareForRhs doesn't touch stack.
926   MOZ_ASSERT(paramLoc.kind() == NameLocation::Kind::ArgumentSlot ||
927              paramLoc.kind() == NameLocation::Kind::FrameSlot ||
928              paramLoc.kind() == NameLocation::Kind::EnvironmentCoordinate);
929 
930   NameOpEmitter noe(bce_, paramName, paramLoc, NameOpEmitter::Kind::Initialize);
931   if (!noe.prepareForRhs()) {
932     //              [stack] ARG
933     return false;
934   }
935 
936   if (!noe.emitAssignment()) {
937     //              [stack] ARG
938     return false;
939   }
940 
941   if (!bce_->emit1(JSOp::Pop)) {
942     //              [stack]
943     return false;
944   }
945 
946   return true;
947 }
948