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