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