diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index f2530db2a..6355c9b51 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -3716,53 +3716,21 @@ BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp, MOZ_ASSERT_IF(isInit, lhs->isKind(PNK_DOT) || lhs->isKind(PNK_ELEM)); - // Name assignments are handled separately because choosing ops and when - // to emit BINDNAME is involved and should avoid duplication. - if (lhs->isKind(PNK_NAME)) { - NameOpEmitter noe(this, - lhs->name(), - isCompound - ? NameOpEmitter::Kind::CompoundAssignment - : NameOpEmitter::Kind::SimpleAssignment); - if (!noe.prepareForRhs()) { // ENV? VAL? - return false; - } - - // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on - // the top of the stack and we need to pick the right RHS value. - uint8_t offset = noe.emittedBindOp() ? 2 : 1; - if (!EmitAssignmentRhs(this, rhs, offset)) { // ENV? VAL? RHS - return false; - } - // Assign inferred function name, unless the lhs is parenthesized - if (rhs && rhs->isDirectRHSAnonFunction() && !lhs->isInParens()) { - MOZ_ASSERT(!isCompound); - RootedAtom name(cx, lhs->name()); - if (!setOrEmitSetFunName(rhs, name)) { // ENV? VAL? RHS - return false; - } - } - - // Emit the compound assignment op if there is one. - if (isCompound) { - if (!emit1(compoundOp)) { // ENV? VAL - return false; - } - } - if (!noe.emitAssignment()) { // VAL - return false; - } - - return true; - } - + Maybe noe; Maybe poe; Maybe eoe; - // Deal with non-name assignments. uint8_t offset = 1; switch (lhs->getKind()) { + case PNK_NAME: { + noe.emplace(this, + lhs->name(), + isCompound + ? NameOpEmitter::Kind::CompoundAssignment + : NameOpEmitter::Kind::SimpleAssignment); + break; + } case PNK_DOT: { PropertyAccess* prop = &lhs->as(); bool isSuper = prop->isSuper(); @@ -3867,6 +3835,15 @@ BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp, } switch (lhs->getKind()) { + case PNK_NAME: + if (!noe->prepareForRhs()) { // ENV? VAL? + return false; + } + // If we emitted a BIND[G]NAME, then the scope is on + // the top of the stack and we need to pick the right RHS value. + if (noe->emittedBindOp()) + offset += 1; + break; case PNK_DOT: if (!poe->prepareForRhs()) { // [Simple,Super] // // THIS SUPERBASE @@ -3898,6 +3875,17 @@ BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp, if (!EmitAssignmentRhs(this, rhs, offset)) // ... VAL? RHS return false; + if (lhs->isKind(PNK_NAME)) { + // Assign inferred function name, unless the lhs is parenthesized + if (rhs && rhs->isDirectRHSAnonFunction() && !lhs->isInParens()) { + MOZ_ASSERT(!isCompound); + RootedAtom name(cx, lhs->name()); + if (!setOrEmitSetFunName(rhs, name)) { // ENV? VAL? RHS + return false; + } + } + } + /* If += etc., emit the binary operator with a source note. */ if (isCompound) { if (!newSrcNote(SRC_ASSIGNOP)) @@ -3908,6 +3896,14 @@ BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, JSOp compoundOp, /* Finally, emit the specialized assignment bytecode. */ switch (lhs->getKind()) { + case PNK_NAME: { + if (!noe->emitAssignment()) { // VAL + return false; + } + + noe.reset(); + break; + } case PNK_DOT: { PropertyAccess* prop = &lhs->as(); if (!poe->emitAssignment(prop->key().atom())) { // VAL