tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FunctionEmitter.cpp (25544B)


      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    222 bool FunctionEmitter::emitNonHoisted(GCThingIndex index) {
    223  // Non-hoisted functions simply emit their respective op.
    224 
    225  //                [stack]
    226 
    227  if (syntaxKind_ == FunctionSyntaxKind::DerivedClassConstructor) {
    228    //              [stack] PROTO
    229    if (!bce_->emitGCIndexOp(JSOp::FunWithProto, index)) {
    230      //            [stack] FUN
    231      return false;
    232    }
    233    return true;
    234  }
    235 
    236  // This is a FunctionExpression, ArrowFunctionExpression, or class
    237  // constructor. Emit the single instruction (without location info).
    238  if (!bce_->emitGCIndexOp(JSOp::Lambda, index)) {
    239    //              [stack] FUN
    240    return false;
    241  }
    242 
    243  return true;
    244 }
    245 
    246 bool FunctionEmitter::emitHoisted(GCThingIndex index) {
    247  MOZ_ASSERT(syntaxKind_ == FunctionSyntaxKind::Statement);
    248 
    249  //                [stack]
    250 
    251  // For functions nested within functions and blocks, make a lambda and
    252  // initialize the binding name of the function in the current scope.
    253 
    254  NameOpEmitter noe(bce_, name_, NameOpEmitter::Kind::Initialize);
    255  if (!noe.prepareForRhs()) {
    256    //              [stack]
    257    return false;
    258  }
    259 
    260  if (!bce_->emitGCIndexOp(JSOp::Lambda, index)) {
    261    //              [stack] FUN
    262    return false;
    263  }
    264 
    265  if (!noe.emitAssignment()) {
    266    //              [stack] FUN
    267    return false;
    268  }
    269 
    270  if (!bce_->emit1(JSOp::Pop)) {
    271    //              [stack]
    272    return false;
    273  }
    274 
    275  return true;
    276 }
    277 
    278 bool FunctionEmitter::emitTopLevelFunction(GCThingIndex index) {
    279  //                [stack]
    280 
    281  if (bce_->sc->isModuleContext()) {
    282    // For modules, we record the function and instantiate the binding
    283    // during ModuleInstantiate(), before the script is run.
    284    return bce_->sc->asModuleContext()->builder.noteFunctionDeclaration(
    285        bce_->fc, index);
    286  }
    287 
    288  MOZ_ASSERT(bce_->sc->isGlobalContext() || bce_->sc->isEvalContext());
    289  MOZ_ASSERT(syntaxKind_ == FunctionSyntaxKind::Statement);
    290  MOZ_ASSERT(bce_->inPrologue());
    291 
    292  // NOTE: The `index` is not directly stored as an opcode, but we collect the
    293  // range of indices in `BytecodeEmitter::emitDeclarationInstantiation` instead
    294  // of discrete indices.
    295  (void)index;
    296 
    297  return true;
    298 }
    299 
    300 bool FunctionScriptEmitter::prepareForParameters() {
    301  MOZ_ASSERT(state_ == State::Start);
    302  MOZ_ASSERT(bce_->inPrologue());
    303 
    304  //                [stack]
    305 
    306  if (paramStart_) {
    307    bce_->setScriptStartOffsetIfUnset(*paramStart_);
    308  }
    309 
    310  // The ordering of these EmitterScopes is important. The named lambda
    311  // scope needs to enclose the function scope needs to enclose the extra
    312  // var scope.
    313 
    314  if (funbox_->namedLambdaBindings()) {
    315    namedLambdaEmitterScope_.emplace(bce_);
    316    if (!namedLambdaEmitterScope_->enterNamedLambda(bce_, funbox_)) {
    317      return false;
    318    }
    319  }
    320 
    321  if (funbox_->needsPromiseResult()) {
    322    asyncEmitter_.emplace(bce_);
    323  }
    324 
    325  if (bodyEnd_) {
    326    bce_->setFunctionBodyEndPos(*bodyEnd_);
    327  }
    328 
    329  if (paramStart_) {
    330    if (!bce_->updateLineNumberNotes(*paramStart_)) {
    331      return false;
    332    }
    333  }
    334 
    335  tdzCache_.emplace(bce_);
    336  functionEmitterScope_.emplace(bce_);
    337 
    338  if (!functionEmitterScope_->enterFunction(bce_, funbox_)) {
    339    return false;
    340  }
    341 
    342  if (!emitInitializeClosedOverArgumentBindings()) {
    343    //              [stack]
    344    return false;
    345  }
    346 
    347  if (funbox_->hasParameterExprs) {
    348    // There's parameter exprs, emit them in the main section.
    349    //
    350    // One caveat is that Debugger considers ops in the prologue to be
    351    // unreachable (i.e. cannot set a breakpoint on it). If there are no
    352    // parameter exprs, any unobservable environment ops (like pushing the
    353    // call object, setting '.this', etc) need to go in the prologue, else it
    354    // messes up breakpoint tests.
    355    bce_->switchToMain();
    356  }
    357 
    358  if (!bce_->emitInitializeFunctionSpecialNames()) {
    359    //              [stack]
    360    return false;
    361  }
    362 
    363  if (!funbox_->hasParameterExprs) {
    364    bce_->switchToMain();
    365  }
    366 
    367  if (funbox_->needsPromiseResult()) {
    368    if (funbox_->hasParameterExprs || funbox_->hasDestructuringArgs) {
    369      if (!asyncEmitter_->prepareForParamsWithExpressionOrDestructuring()) {
    370        return false;
    371      }
    372    } else {
    373      if (!asyncEmitter_->prepareForParamsWithoutExpressionOrDestructuring()) {
    374        return false;
    375      }
    376    }
    377  }
    378 
    379  if (funbox_->isClassConstructor()) {
    380    if (!funbox_->isDerivedClassConstructor()) {
    381      if (!bce_->emitInitializeInstanceMembers(false)) {
    382        //          [stack]
    383        return false;
    384      }
    385    }
    386  }
    387 
    388 #ifdef DEBUG
    389  state_ = State::Parameters;
    390 #endif
    391  return true;
    392 }
    393 
    394 bool FunctionScriptEmitter::emitInitializeClosedOverArgumentBindings() {
    395  // Initialize CallObject slots for closed-over arguments. If the function has
    396  // parameter expressions, these are lexical bindings and we initialize the
    397  // slots to the magic TDZ value. If the function doesn't have parameter
    398  // expressions, we copy the frame's arguments.
    399 
    400  MOZ_ASSERT(bce_->inPrologue());
    401 
    402  auto* bindings = funbox_->functionScopeBindings();
    403  if (!bindings) {
    404    return true;
    405  }
    406 
    407  const bool hasParameterExprs = funbox_->hasParameterExprs;
    408 
    409  bool pushedUninitialized = false;
    410  for (ParserPositionalFormalParameterIter fi(*bindings, hasParameterExprs); fi;
    411       fi++) {
    412    if (!fi.closedOver()) {
    413      continue;
    414    }
    415 
    416    if (hasParameterExprs) {
    417      NameLocation nameLoc = bce_->lookupName(fi.name());
    418      if (!pushedUninitialized) {
    419        if (!bce_->emit1(JSOp::Uninitialized)) {
    420          //          [stack] UNINITIALIZED
    421          return false;
    422        }
    423        pushedUninitialized = true;
    424      }
    425      if (!bce_->emitEnvCoordOp(JSOp::InitAliasedLexical,
    426                                nameLoc.environmentCoordinate())) {
    427        //            [stack] UNINITIALIZED
    428        return false;
    429      }
    430    } else {
    431      NameOpEmitter noe(bce_, fi.name(), NameOpEmitter::Kind::Initialize);
    432      if (!noe.prepareForRhs()) {
    433        //            [stack]
    434        return false;
    435      }
    436 
    437      if (!bce_->emitArgOp(JSOp::GetFrameArg, fi.argumentSlot())) {
    438        //            [stack] VAL
    439        return false;
    440      }
    441 
    442      if (!noe.emitAssignment()) {
    443        //            [stack] VAL
    444        return false;
    445      }
    446 
    447      if (!bce_->emit1(JSOp::Pop)) {
    448        //            [stack]
    449        return false;
    450      }
    451    }
    452  }
    453 
    454  if (pushedUninitialized) {
    455    MOZ_ASSERT(hasParameterExprs);
    456    if (!bce_->emit1(JSOp::Pop)) {
    457      //              [stack]
    458      return false;
    459    }
    460  }
    461 
    462  return true;
    463 }
    464 
    465 bool FunctionScriptEmitter::prepareForBody() {
    466  MOZ_ASSERT(state_ == State::Parameters);
    467 
    468  //                [stack]
    469 
    470  if (funbox_->needsPromiseResult()) {
    471    if (!asyncEmitter_->emitParamsEpilogue()) {
    472      return false;
    473    }
    474  }
    475 
    476  if (!emitExtraBodyVarScope()) {
    477    //              [stack]
    478    return false;
    479  }
    480 
    481  if (funbox_->needsPromiseResult()) {
    482    if (!asyncEmitter_->prepareForBody()) {
    483      return false;
    484    }
    485  }
    486 
    487 #ifdef DEBUG
    488  state_ = State::Body;
    489 #endif
    490  return true;
    491 }
    492 
    493 bool FunctionScriptEmitter::emitExtraBodyVarScope() {
    494  //                [stack]
    495 
    496  if (!funbox_->functionHasExtraBodyVarScope()) {
    497    return true;
    498  }
    499 
    500  extraBodyVarEmitterScope_.emplace(bce_);
    501  if (!extraBodyVarEmitterScope_->enterFunctionExtraBodyVar(bce_, funbox_)) {
    502    return false;
    503  }
    504 
    505  if (!funbox_->extraVarScopeBindings() || !funbox_->functionScopeBindings()) {
    506    return true;
    507  }
    508 
    509  // After emitting expressions for all parameters, copy over any formal
    510  // parameters which have been redeclared as vars. For example, in the
    511  // following, the var y in the body scope is 42:
    512  //
    513  //   function f(x, y = 42) { var y; }
    514  //
    515  for (ParserBindingIter bi(*funbox_->functionScopeBindings(), true); bi;
    516       bi++) {
    517    auto name = bi.name();
    518 
    519    // There may not be a var binding of the same name.
    520    if (!bce_->locationOfNameBoundInScope(name,
    521                                          extraBodyVarEmitterScope_.ptr())) {
    522      continue;
    523    }
    524 
    525    // The '.this', '.newTarget', and '.generator' function special binding
    526    // should never appear in the extra var scope. 'arguments', however, may.
    527    MOZ_ASSERT(name != TaggedParserAtomIndex::WellKnown::dot_this_() &&
    528               name != TaggedParserAtomIndex::WellKnown::dot_newTarget_() &&
    529               name != TaggedParserAtomIndex::WellKnown::dot_generator_());
    530 
    531    NameOpEmitter noe(bce_, name, NameOpEmitter::Kind::Initialize);
    532    if (!noe.prepareForRhs()) {
    533      //            [stack]
    534      return false;
    535    }
    536 
    537    NameLocation paramLoc =
    538        *bce_->locationOfNameBoundInScope(name, functionEmitterScope_.ptr());
    539    if (!bce_->emitGetNameAtLocation(name, paramLoc)) {
    540      //            [stack] VAL
    541      return false;
    542    }
    543 
    544    if (!noe.emitAssignment()) {
    545      //            [stack] VAL
    546      return false;
    547    }
    548 
    549    if (!bce_->emit1(JSOp::Pop)) {
    550      //            [stack]
    551      return false;
    552    }
    553  }
    554 
    555  return true;
    556 }
    557 
    558 bool FunctionScriptEmitter::emitEndBody() {
    559  MOZ_ASSERT(state_ == State::Body);
    560  //                [stack]
    561 
    562  if (bodyEnd_) {
    563    if (!bce_->updateSourceCoordNotes(*bodyEnd_)) {
    564      return false;
    565    }
    566  }
    567 
    568  if (funbox_->needsFinalYield()) {
    569    // If we fall off the end of a generator or async function, we
    570    // do a final yield with an |undefined| payload. We put all
    571    // the code to do this in one place, both to reduce bytecode
    572    // size and to prevent any OOM or debugger exception that occurs
    573    // at this point from being caught inside the function.
    574    if (!bce_->emit1(JSOp::Undefined)) {
    575      //          [stack] UNDEF
    576      return false;
    577    }
    578    if (!bce_->emit1(JSOp::SetRval)) {
    579      //          [stack]
    580      return false;
    581    }
    582 
    583    // Return statements in the body of the function will jump here
    584    // with the return payload in rval.
    585    if (!bce_->emitJumpTargetAndPatch(bce_->finalYields)) {
    586      //          [stack]
    587      return false;
    588    }
    589 
    590    if (funbox_->needsIteratorResult()) {
    591      MOZ_ASSERT(!funbox_->needsPromiseResult());
    592      // Emit final yield bytecode for generators, for example:
    593      // function gen * () { ... }
    594      if (!bce_->emitPrepareIteratorResult()) {
    595        //          [stack] RESULT
    596        return false;
    597      }
    598 
    599      if (!bce_->emit1(JSOp::GetRval)) {
    600        //          [stack] RESULT RVAL
    601        return false;
    602      }
    603 
    604      if (!bce_->emitFinishIteratorResult(true)) {
    605        //          [stack] RESULT
    606        return false;
    607      }
    608 
    609      if (!bce_->emit1(JSOp::SetRval)) {
    610        //          [stack]
    611        return false;
    612      }
    613 
    614    } else if (funbox_->needsPromiseResult()) {
    615      // Emit final yield bytecode for async functions, for example:
    616      // async function deferred() { ... }
    617      if (!bce_->emit1(JSOp::GetRval)) {
    618        //          [stack] RVAL
    619        return false;
    620      }
    621 
    622      if (!bce_->emitGetDotGeneratorInInnermostScope()) {
    623        //          [stack] RVAL GEN
    624        return false;
    625      }
    626 
    627      if (!bce_->emit1(JSOp::AsyncResolve)) {
    628        //          [stack] PROMISE
    629        return false;
    630      }
    631 
    632      if (!bce_->emit1(JSOp::SetRval)) {
    633        //          [stack]
    634        return false;
    635      }
    636    }
    637 
    638    // Emit the final yield.
    639    if (!bce_->emitGetDotGeneratorInInnermostScope()) {
    640      //          [stack] GEN
    641      return false;
    642    }
    643 
    644    if (!bce_->emitYieldOp(JSOp::FinalYieldRval)) {
    645      return false;
    646    }
    647 
    648    if (funbox_->needsPromiseResult()) {
    649      // Emit the reject catch block.
    650      if (!asyncEmitter_->emitEndFunction()) {
    651        return false;
    652      }
    653    }
    654 
    655  } else {
    656    // Non-generator functions just return |undefined|. The
    657    // JSOp::RetRval emitted below will do that, except if the
    658    // script has a finally block: there can be a non-undefined
    659    // value in the return value slot. Make sure the return value
    660    // is |undefined|.
    661    if (bce_->hasTryFinally) {
    662      if (!bce_->emit1(JSOp::Undefined)) {
    663        //          [stack] UNDEF
    664        return false;
    665      }
    666      if (!bce_->emit1(JSOp::SetRval)) {
    667        //          [stack]
    668        return false;
    669      }
    670    }
    671  }
    672 
    673  // Execute |CheckReturn| right before exiting the class constructor.
    674  if (funbox_->isDerivedClassConstructor()) {
    675    if (!bce_->emitJumpTargetAndPatch(bce_->endOfDerivedClassConstructorBody)) {
    676      return false;
    677    }
    678 
    679    if (!bce_->emitCheckDerivedClassConstructorReturn()) {
    680      //            [stack]
    681      return false;
    682    }
    683  }
    684 
    685  if (extraBodyVarEmitterScope_) {
    686    if (!extraBodyVarEmitterScope_->leave(bce_)) {
    687      return false;
    688    }
    689 
    690    extraBodyVarEmitterScope_.reset();
    691  }
    692 
    693  if (!functionEmitterScope_->leave(bce_)) {
    694    return false;
    695  }
    696  functionEmitterScope_.reset();
    697  tdzCache_.reset();
    698 
    699  // We only want to mark the end of a function as a breakable position if
    700  // there is token there that the user can easily associate with the function
    701  // as a whole. Since arrow function single-expression bodies have no closing
    702  // curly bracket, we do not place a breakpoint at their end position.
    703  if (!funbox_->hasExprBody()) {
    704    if (!bce_->markSimpleBreakpoint()) {
    705      return false;
    706    }
    707  }
    708 
    709  // Emit JSOp::RetRval except for sync arrow function with expression body
    710  // which always ends with JSOp::Return. Other parts of the codebase depend
    711  // on these opcodes being the last opcode.
    712  // See JSScript::lastPC and BaselineCompiler::emitBody.
    713  if (!funbox_->hasExprBody() || funbox_->isAsync()) {
    714    if (!bce_->emitReturnRval()) {
    715      //            [stack]
    716      return false;
    717    }
    718  }
    719 
    720  if (namedLambdaEmitterScope_) {
    721    if (!namedLambdaEmitterScope_->leave(bce_)) {
    722      return false;
    723    }
    724    namedLambdaEmitterScope_.reset();
    725  }
    726 
    727 #ifdef DEBUG
    728  state_ = State::EndBody;
    729 #endif
    730  return true;
    731 }
    732 
    733 bool FunctionScriptEmitter::intoStencil() {
    734  MOZ_ASSERT(state_ == State::EndBody);
    735 
    736  if (!bce_->intoScriptStencil(funbox_->index())) {
    737    return false;
    738  }
    739 
    740 #ifdef DEBUG
    741  state_ = State::End;
    742 #endif
    743 
    744  return true;
    745 }
    746 
    747 FunctionParamsEmitter::FunctionParamsEmitter(BytecodeEmitter* bce,
    748                                             FunctionBox* funbox)
    749    : bce_(bce),
    750      funbox_(funbox),
    751      functionEmitterScope_(bce_->innermostEmitterScope()) {}
    752 
    753 bool FunctionParamsEmitter::emitSimple(TaggedParserAtomIndex paramName) {
    754  MOZ_ASSERT(state_ == State::Start);
    755 
    756  //                [stack]
    757 
    758  if (funbox_->hasParameterExprs) {
    759    if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
    760      //            [stack] ARG
    761      return false;
    762    }
    763 
    764    if (!emitAssignment(paramName)) {
    765      //            [stack]
    766      return false;
    767    }
    768  }
    769 
    770  argSlot_++;
    771  return true;
    772 }
    773 
    774 bool FunctionParamsEmitter::prepareForDefault() {
    775  MOZ_ASSERT(state_ == State::Start);
    776 
    777  //                [stack]
    778 
    779  if (!prepareForInitializer()) {
    780    //              [stack]
    781    return false;
    782  }
    783 
    784 #ifdef DEBUG
    785  state_ = State::Default;
    786 #endif
    787  return true;
    788 }
    789 
    790 bool FunctionParamsEmitter::emitDefaultEnd(TaggedParserAtomIndex paramName) {
    791  MOZ_ASSERT(state_ == State::Default);
    792 
    793  //                [stack] DEFAULT
    794 
    795  if (!emitInitializerEnd()) {
    796    //              [stack] ARG/DEFAULT
    797    return false;
    798  }
    799  if (!emitAssignment(paramName)) {
    800    //              [stack]
    801    return false;
    802  }
    803 
    804  argSlot_++;
    805 
    806 #ifdef DEBUG
    807  state_ = State::Start;
    808 #endif
    809  return true;
    810 }
    811 
    812 bool FunctionParamsEmitter::prepareForDestructuring() {
    813  MOZ_ASSERT(state_ == State::Start);
    814 
    815  //                [stack]
    816 
    817  if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
    818    //              [stack] ARG
    819    return false;
    820  }
    821 
    822 #ifdef DEBUG
    823  state_ = State::Destructuring;
    824 #endif
    825  return true;
    826 }
    827 
    828 bool FunctionParamsEmitter::emitDestructuringEnd() {
    829  MOZ_ASSERT(state_ == State::Destructuring);
    830 
    831  //                [stack] ARG
    832 
    833  if (!bce_->emit1(JSOp::Pop)) {
    834    //              [stack]
    835    return false;
    836  }
    837 
    838  argSlot_++;
    839 
    840 #ifdef DEBUG
    841  state_ = State::Start;
    842 #endif
    843  return true;
    844 }
    845 
    846 bool FunctionParamsEmitter::prepareForDestructuringDefaultInitializer() {
    847  MOZ_ASSERT(state_ == State::Start);
    848 
    849  //                [stack]
    850 
    851  if (!prepareForInitializer()) {
    852    //              [stack]
    853    return false;
    854  }
    855 
    856 #ifdef DEBUG
    857  state_ = State::DestructuringDefaultInitializer;
    858 #endif
    859  return true;
    860 }
    861 
    862 bool FunctionParamsEmitter::prepareForDestructuringDefault() {
    863  MOZ_ASSERT(state_ == State::DestructuringDefaultInitializer);
    864 
    865  //                [stack] DEFAULT
    866 
    867  if (!emitInitializerEnd()) {
    868    //              [stack] ARG/DEFAULT
    869    return false;
    870  }
    871 
    872 #ifdef DEBUG
    873  state_ = State::DestructuringDefault;
    874 #endif
    875  return true;
    876 }
    877 
    878 bool FunctionParamsEmitter::emitDestructuringDefaultEnd() {
    879  MOZ_ASSERT(state_ == State::DestructuringDefault);
    880 
    881  //                [stack] ARG/DEFAULT
    882 
    883  if (!bce_->emit1(JSOp::Pop)) {
    884    //              [stack]
    885    return false;
    886  }
    887 
    888  argSlot_++;
    889 
    890 #ifdef DEBUG
    891  state_ = State::Start;
    892 #endif
    893  return true;
    894 }
    895 
    896 bool FunctionParamsEmitter::emitRest(TaggedParserAtomIndex paramName) {
    897  MOZ_ASSERT(state_ == State::Start);
    898 
    899  //                [stack]
    900 
    901  if (!emitRestArray()) {
    902    //              [stack] REST
    903    return false;
    904  }
    905  if (!emitAssignment(paramName)) {
    906    //              [stack]
    907    return false;
    908  }
    909 
    910 #ifdef DEBUG
    911  state_ = State::End;
    912 #endif
    913  return true;
    914 }
    915 
    916 bool FunctionParamsEmitter::prepareForDestructuringRest() {
    917  MOZ_ASSERT(state_ == State::Start);
    918 
    919  //                [stack]
    920 
    921  if (!emitRestArray()) {
    922    //              [stack] REST
    923    return false;
    924  }
    925 
    926 #ifdef DEBUG
    927  state_ = State::DestructuringRest;
    928 #endif
    929  return true;
    930 }
    931 
    932 bool FunctionParamsEmitter::emitDestructuringRestEnd() {
    933  MOZ_ASSERT(state_ == State::DestructuringRest);
    934 
    935  //                [stack] REST
    936 
    937  if (!bce_->emit1(JSOp::Pop)) {
    938    //              [stack]
    939    return false;
    940  }
    941 
    942 #ifdef DEBUG
    943  state_ = State::End;
    944 #endif
    945  return true;
    946 }
    947 
    948 bool FunctionParamsEmitter::prepareForInitializer() {
    949  //                [stack]
    950 
    951  // If we have an initializer, emit the initializer and assign it
    952  // to the argument slot. TDZ is taken care of afterwards.
    953  MOZ_ASSERT(funbox_->hasParameterExprs);
    954  if (!bce_->emitArgOp(JSOp::GetArg, argSlot_)) {
    955    //              [stack] ARG
    956    return false;
    957  }
    958  default_.emplace(bce_);
    959  if (!default_->prepareForDefault()) {
    960    //              [stack]
    961    return false;
    962  }
    963  return true;
    964 }
    965 
    966 bool FunctionParamsEmitter::emitInitializerEnd() {
    967  //                [stack] DEFAULT
    968 
    969  if (!default_->emitEnd()) {
    970    //              [stack] ARG/DEFAULT
    971    return false;
    972  }
    973  default_.reset();
    974  return true;
    975 }
    976 
    977 bool FunctionParamsEmitter::emitRestArray() {
    978  //                [stack]
    979 
    980  if (!bce_->emit1(JSOp::Rest)) {
    981    //              [stack] REST
    982    return false;
    983  }
    984  return true;
    985 }
    986 
    987 bool FunctionParamsEmitter::emitAssignment(TaggedParserAtomIndex paramName) {
    988  //                [stack] ARG
    989 
    990  NameLocation paramLoc =
    991      *bce_->locationOfNameBoundInScope(paramName, functionEmitterScope_);
    992 
    993  // RHS is already pushed in the caller side.
    994  // Make sure prepareForRhs doesn't touch stack.
    995  MOZ_ASSERT(paramLoc.kind() == NameLocation::Kind::ArgumentSlot ||
    996             paramLoc.kind() == NameLocation::Kind::FrameSlot ||
    997             paramLoc.kind() == NameLocation::Kind::EnvironmentCoordinate);
    998 
    999  NameOpEmitter noe(bce_, paramName, paramLoc, NameOpEmitter::Kind::Initialize);
   1000  if (!noe.prepareForRhs()) {
   1001    //              [stack] ARG
   1002    return false;
   1003  }
   1004 
   1005  if (!noe.emitAssignment()) {
   1006    //              [stack] ARG
   1007    return false;
   1008  }
   1009 
   1010  if (!bce_->emit1(JSOp::Pop)) {
   1011    //              [stack]
   1012    return false;
   1013  }
   1014 
   1015  return true;
   1016 }