diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 428066a854..130c795b87 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -2805,13 +2805,6 @@ BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op) return emitIndexOp(op, index); } -bool -BytecodeEmitter::emitAtomOp(ParseNode* pn, JSOp op) -{ - MOZ_ASSERT(pn->pn_atom != nullptr); - return emitAtomOp(pn->pn_atom, op); -} - bool BytecodeEmitter::emitInternedScopeOp(uint32_t index, JSOp op) { @@ -3614,7 +3607,7 @@ BytecodeEmitter::emitToIteratorResult(bool done) } bool -BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bool callContext) +BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc) { switch (loc.kind()) { case NameLocation::Kind::Dynamic: @@ -3669,43 +3662,13 @@ BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bo MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization"); } - // Need to provide |this| value for call. - if (callContext) { - switch (loc.kind()) { - case NameLocation::Kind::Dynamic: { - JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS; - if (!emitAtomOp(name, thisOp)) - return false; - break; - } - - case NameLocation::Kind::Global: - if (!emitAtomOp(name, JSOP_GIMPLICITTHIS)) - return false; - break; - - case NameLocation::Kind::Intrinsic: - case NameLocation::Kind::NamedLambdaCallee: - case NameLocation::Kind::Import: - case NameLocation::Kind::ArgumentSlot: - case NameLocation::Kind::FrameSlot: - case NameLocation::Kind::EnvironmentCoordinate: - if (!emit1(JSOP_UNDEFINED)) - return false; - break; - - case NameLocation::Kind::DynamicAnnexBVar: - MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization"); - } - } - return true; } bool -BytecodeEmitter::emitGetName(ParseNode* pn, bool callContext) +BytecodeEmitter::emitGetName(ParseNode* pn) { - return emitGetName(pn->name(), callContext); + return emitGetName(pn->name()); } template @@ -3918,7 +3881,7 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn) do { /* Walk back up the list, emitting annotated name ops. */ - if (!emitAtomOp(pndot, JSOP_GETPROP)) + if (!emitAtomOp(pndot->pn_atom, JSOP_GETPROP)) return false; /* Reverse the pn_expr link again. */ @@ -3936,12 +3899,15 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn) bool BytecodeEmitter::emitSuperPropLHS(ParseNode* superBase, bool isCall) { - if (!emitGetThisForSuperBase(superBase)) + if (!emitGetThisForSuperBase(superBase)) { // THIS return false; - if (isCall && !emit1(JSOP_DUP)) + } + if (isCall && !emit1(JSOP_DUP)) { // THIS? THIS return false; - if (!emit1(JSOP_SUPERBASE)) + } + if (!emit1(JSOP_SUPERBASE)) { // THIS? THIS SUPERBASE return false; + } return true; } @@ -3956,7 +3922,7 @@ BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op) if (op == JSOP_CALLPROP && !emit1(JSOP_DUP)) return false; - if (!emitAtomOp(pn, op)) + if (!emitAtomOp(pn->pn_atom, op)) return false; if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP)) @@ -3969,15 +3935,18 @@ bool BytecodeEmitter::emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall) { ParseNode* base = &pn->as().expression(); - if (!emitSuperPropLHS(base, isCall)) - return false; - if (!emitAtomOp(pn, op)) + if (!emitSuperPropLHS(base, isCall)) { // THIS? THIS SUPERBASE return false; + } - if (isCall && !emit1(JSOP_SWAP)) + if (!emitAtomOp(pn->pn_atom, op)) { // THIS? PROP return false; + } + if (isCall && !emit1(JSOP_SWAP)) { // PROP THIS + return false; + } return true; } @@ -4002,36 +3971,58 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn) if (!emit1(JSOP_DUP)) // OBJ OBJ return false; } - if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V + if (!emitAtomOp(pn->pn_kid->pn_atom, isSuper ? JSOP_GETPROP_SUPER : JSOP_GETPROP)) { + return false; // THIS? OBJ V + } + if (!emit1(JSOP_POS)) { // ... N return false; - if (!emit1(JSOP_POS)) // OBJ N + } + if (post) { + if (!emit1(JSOP_DUP)) { // ... N N + return false; + } + } + if (!emit1(JSOP_ONE)) { // ... N? N 1 return false; - if (post && !emit1(JSOP_DUP)) // OBJ N? N - return false; - if (!emit1(JSOP_ONE)) // OBJ N? N 1 - return false; - if (!emit1(binop)) // OBJ N? N+1 + } + if (!emit1(binop)) { // ... N? N+1 return false; + } if (post) { - if (!emit2(JSOP_PICK, 2 + isSuper)) // N? N+1 OBJ - return false; - if (!emit1(JSOP_SWAP)) // N? OBJ N+1 - return false; - if (isSuper) { - if (!emit2(JSOP_PICK, 3)) // N THIS N+1 OBJ + if (isSuper) { // THIS OBJ N N+1 + if (!emit2(JSOP_PICK, 3)) { // OBJ N N+1 THIS return false; - if (!emit1(JSOP_SWAP)) // N THIS OBJ N+1 + } + if (!emit1(JSOP_SWAP)) { // OBJ N THIS N+1 return false; + } + if (!emit2(JSOP_PICK, 3)) { // N THIS N+1 OBJ + return false; + } + if (!emit1(JSOP_SWAP)) { // N THIS OBJ N+1 + return false; + } + } else { // OBJ N N+1 + if (!emit2(JSOP_PICK, 2)) { // N N+1 OBJ + return false; + } + if (!emit1(JSOP_SWAP)) { // N OBJ N+1 + return false; + + } } } JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER : sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP; - if (!emitAtomOp(pn->pn_kid, setOp)) // N? N+1 - return false; - if (post && !emit1(JSOP_POP)) // RESULT + if (!emitAtomOp(pn->pn_kid->pn_atom, setOp)) // N? N+1 return false; + if (post) { + if (!emit1(JSOP_POP)) { // N + return false; + } + } return true; } @@ -4048,7 +4039,7 @@ BytecodeEmitter::emitNameIncDec(ParseNode* pn) bool emittedBindOp) { JSAtom* name = pn->pn_kid->name(); - if (!bce->emitGetNameAtLocation(name, loc, false)) // SCOPE? V + if (!bce->emitGetNameAtLocation(name, loc)) // SCOPE? V return false; if (!bce->emit1(JSOP_POS)) // SCOPE? N return false; @@ -4083,25 +4074,25 @@ BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts) { MOZ_ASSERT(pn->isArity(PN_BINARY)); - if (!emitTree(pn->pn_left)) + if (!emitTree(pn->pn_left)) // OBJ return false; if (opts == EmitElemOption::IncDec) { - if (!emit1(JSOP_CHECKOBJCOERCIBLE)) + if (!emit1(JSOP_CHECKOBJCOERCIBLE)) // OBJ return false; } else if (opts == EmitElemOption::Call) { - if (!emit1(JSOP_DUP)) + if (!emit1(JSOP_DUP)) // OBJ OBJ return false; } - if (!emitTree(pn->pn_right)) + if (!emitTree(pn->pn_right)) // OBJ? OBJ KEY return false; if (opts == EmitElemOption::Set) { if (!emit2(JSOP_PICK, 2)) return false; } else if (opts == EmitElemOption::IncDec || opts == EmitElemOption::CompoundAssign) { - if (!emit1(JSOP_TOID)) + if (!emit1(JSOP_TOID)) // OBJ KEY return false; } return true; @@ -4167,7 +4158,13 @@ BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op) else if (op == JSOP_SETELEM || op == JSOP_STRICTSETELEM) opts = EmitElemOption::Set; - return emitElemOperands(pn, opts) && emitElemOpBase(op); + if (!emitElemOperands(pn, opts)) { // OBJ? OBJ KEY + return false; + } + if (!emitElemOpBase(op)) { // OBJ? ELEM + return false; + } + return true; } bool @@ -4184,8 +4181,11 @@ BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall) if (!emitElemOpBase(op)) return false; - if (isCall && !emit1(JSOP_SWAP)) - return false; + if (isCall) { + if (!emit1(JSOP_SWAP)) { // VALUE THIS + return false; + } + } return true; } @@ -4202,10 +4202,10 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn) // emit(Super)ElemOperands. if (isSuper) { if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec)) - return false; + return false; // THIS KEY OBJ } else { if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec)) - return false; + return false; // OBJ KEY } bool post; @@ -4228,7 +4228,7 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn) return false; getOp = JSOP_GETELEM; } - if (!emitElemOpBase(getOp)) // OBJ KEY V + if (!emitElemOpBase(getOp)) // OBJ KEY ELEM return false; if (!emit1(JSOP_POS)) // OBJ KEY N return false; @@ -4965,10 +4965,10 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) case PNK_DOT: { if (target->as().isSuper()) { if (!emitSuperPropLHS(&target->as().expression())) - return false; + return false; // THIS SUPERBASE *emitted = 2; } else { - if (!emitTree(target->pn_expr)) + if (!emitTree(target->pn_expr)) // OBJ return false; *emitted = 1; } @@ -4978,11 +4978,11 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) case PNK_ELEM: { if (target->as().isSuper()) { if (!emitSuperElemOperands(target, EmitElemOption::Ref)) - return false; + return false; // THIS KEY OBJ *emitted = 3; } else { if (!emitElemOperands(target, EmitElemOption::Ref)) - return false; + return false; // OBJ KEY *emitted = 2; } break; @@ -5082,26 +5082,26 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri case PNK_DOT: { // The reference is already pushed by emitDestructuringLHSRef. JSOp setOp; - if (target->as().isSuper()) + if (target->as().isSuper()) // THIS OBJ VAL setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER; - else + else // OBJ VAL setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP; - if (!emitAtomOp(target, setOp)) + if (!emitAtomOp(target->pn_atom, setOp)) // VAL return false; break; } case PNK_ELEM: { // The reference is already pushed by emitDestructuringLHSRef. - if (target->as().isSuper()) { + if (target->as().isSuper()) { // THIS KEY OBJ VAL JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER; // emitDestructuringLHSRef already did emitSuperElemOperands // part of emitSuperElemOp. Perform remaining part here. - if (!emitElemOpBase(setOp)) + if (!emitElemOpBase(setOp)) // VAL return false; - } else { + } else { // OBJ KEY VAL JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM; - if (!emitElemOpBase(setOp)) + if (!emitElemOpBase(setOp)) // VAL return false; } break; @@ -6139,17 +6139,20 @@ EmitAssignmentRhs(BytecodeEmitter* bce, ParseNode* rhs, uint8_t offset) } bool -BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) +BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs) { + bool isCompound = compoundOp != JSOP_NOP; + // Name assignments are handled separately because choosing ops and when // to emit BINDNAME is involved and should avoid duplication. if (lhs->isKind(PNK_NAME)) { - auto emitRhs = [op, lhs, rhs](BytecodeEmitter* bce, const NameLocation& lhsLoc, - bool emittedBindOp) + auto emitRhs = [lhs, compoundOp, rhs, isCompound](BytecodeEmitter* bce, + const NameLocation& lhsLoc, + bool emittedBindOp) { // For compound assignments, first get the LHS value, then emit - // the RHS and the op. - if (op != JSOP_NOP) { + // the RHS and the compoundOp. + if (isCompound) { if (lhsLoc.kind() == NameLocation::Kind::Dynamic) { // For dynamic accesses we can do better than a GETNAME // since the assignment already emitted a BINDNAME on the @@ -6157,7 +6160,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) // the name. if (!bce->emit1(JSOP_DUP)) return false; - if (!bce->emitAtomOp(lhs, JSOP_GETXPROP)) + if (!bce->emitAtomOp(lhs->pn_atom, JSOP_GETXPROP)) return false; } else { if (!bce->emitGetNameAtLocation(lhs->name(), lhsLoc)) @@ -6170,14 +6173,14 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) if (!EmitAssignmentRhs(bce, rhs, emittedBindOp ? 2 : 1)) return false; - if (!lhs->isInParens() && op == JSOP_NOP && rhs && rhs->isDirectRHSAnonFunction()) { + if (!lhs->isInParens() && !isCompound && rhs && rhs->isDirectRHSAnonFunction()) { RootedAtom name(bce->cx, lhs->name()); if (!bce->setOrEmitSetFunName(rhs, name, FunctionPrefixKind::None)) return false; } // Emit the compound assignment op if there is one. - if (op != JSOP_NOP && !bce->emit1(op)) + if (isCompound && !bce->emit1(compoundOp)) return false; return true; @@ -6194,10 +6197,10 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) case PNK_DOT: if (lhs->as().isSuper()) { if (!emitSuperPropLHS(&lhs->as().expression())) - return false; + return false; // THIS SUPERBASE offset += 2; } else { - if (!emitTree(lhs->expr())) + if (!emitTree(lhs->expr())) // OBJ return false; offset += 1; } @@ -6206,13 +6209,13 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) break; case PNK_ELEM: { MOZ_ASSERT(lhs->isArity(PN_BINARY)); - EmitElemOption opt = op == JSOP_NOP ? EmitElemOption::Get : EmitElemOption::CompoundAssign; + EmitElemOption opt = isCompound ? EmitElemOption::CompoundAssign : EmitElemOption::Get; if (lhs->as().isSuper()) { - if (!emitSuperElemOperands(lhs, opt)) + if (!emitSuperElemOperands(lhs, opt)) // THIS KEY OBJ return false; offset += 3; } else { - if (!emitElemOperands(lhs, opt)) + if (!emitElemOperands(lhs, opt)) // OBJ KEY return false; offset += 2; } @@ -6238,41 +6241,44 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) MOZ_ASSERT(0); } - if (op != JSOP_NOP) { + if (isCompound) { MOZ_ASSERT(rhs); switch (lhs->getKind()) { case PNK_DOT: { JSOp getOp; if (lhs->as().isSuper()) { - if (!emit1(JSOP_DUP2)) + if (!emit1(JSOP_DUP2)) // THIS OBJ THIS OBJ return false; getOp = JSOP_GETPROP_SUPER; } else { - if (!emit1(JSOP_DUP)) + if (!emit1(JSOP_DUP)) // OBJ OBJ return false; bool isLength = (lhs->pn_atom == cx->names().length); getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP; } - if (!emitIndex32(getOp, atomIndex)) + if (!emitIndex32(getOp, atomIndex)) // THIS? OBJ VAL return false; break; } case PNK_ELEM: { JSOp elemOp; if (lhs->as().isSuper()) { - if (!emitDupAt(2)) + if (!emitDupAt(2)) // THIS KEY OBJ THIS return false; - if (!emitDupAt(2)) + if (!emitDupAt(2)) // THIS KEY OBJ THIS KEY return false; - if (!emitDupAt(2)) + if (!emitDupAt(2)) // THIS KEY OBJ THIS KEY OBJ return false; elemOp = JSOP_GETELEM_SUPER; } else { - if (!emit1(JSOP_DUP2)) + if (!emit1(JSOP_DUP2)) // OBJ KEY OBJ KEY return false; elemOp = JSOP_GETELEM; } - if (!emitElemOpBase(elemOp)) + if (!emitElemOpBase(elemOp)) // [Super] + // // THIS KEY OBJ ELEM + // // [Other] + // // OBJ KEY ELEM return false; break; } @@ -6287,14 +6293,14 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) } } - if (!EmitAssignmentRhs(this, rhs, offset)) + if (!EmitAssignmentRhs(this, rhs, offset)) // ... VAL? RHS return false; /* If += etc., emit the binary operator with a source note. */ - if (op != JSOP_NOP) { + if (isCompound) { if (!newSrcNote(SRC_ASSIGNOP)) return false; - if (!emit1(op)) + if (!emit1(compoundOp)) // ... VAL return false; } @@ -6304,7 +6310,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) JSOp setOp = lhs->as().isSuper() ? (sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER) : (sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP); - if (!emitIndexOp(setOp, atomIndex)) + if (!emitIndexOp(setOp, atomIndex)) // VAL return false; break; } @@ -6315,7 +6321,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) JSOp setOp = lhs->as().isSuper() ? sc->strict() ? JSOP_STRICTSETELEM_SUPER : JSOP_SETELEM_SUPER : sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM; - if (!emit1(setOp)) + if (!emit1(setOp)) // VAL return false; break; } @@ -8460,10 +8466,26 @@ BytecodeEmitter::emitGetFunctionThis(ParseNode* pn) MOZ_ASSERT(pn->isKind(PNK_NAME)); MOZ_ASSERT(pn->name() == cx->names().dotThis); - if (!emitTree(pn)) - return false; - if (sc->needsThisTDZChecks() && !emit1(JSOP_CHECKTHIS)) + return emitGetFunctionThis(Some(pn->pn_pos.begin)); +} + +bool +BytecodeEmitter::emitGetFunctionThis(const mozilla::Maybe& offset) +{ + if (offset) { + if (!updateLineNumberNotes(*offset)) { + return false; + } + } + + if (!emitGetName(cx->names().dotThis)) { // THIS return false; + } + if (sc->needsThisTDZChecks()) { + if (!emit1(JSOP_CHECKTHIS)) { // THIS + return false; + } + } return true; } @@ -8472,7 +8494,7 @@ bool BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn) { MOZ_ASSERT(pn->isKind(PNK_SUPERBASE)); - return emitGetFunctionThis(pn->pn_kid); + return emitGetFunctionThis(pn->pn_kid); // THIS } bool @@ -8481,13 +8503,13 @@ BytecodeEmitter::emitThisLiteral(ParseNode* pn) MOZ_ASSERT(pn->isKind(PNK_THIS)); if (ParseNode* thisName = pn->pn_kid) - return emitGetFunctionThis(thisName); + return emitGetFunctionThis(thisName); // THIS if (sc->thisBinding() == ThisBinding::Module) - return emit1(JSOP_UNDEFINED); + return emit1(JSOP_UNDEFINED); // UNDEF MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global); - return emit1(JSOP_GLOBALTHIS); + return emit1(JSOP_GLOBALTHIS); // THIS } bool @@ -9077,7 +9099,7 @@ BytecodeEmitter::emitDeleteName(ParseNode* node) ParseNode* nameExpr = node->pn_kid; MOZ_ASSERT(nameExpr->isKind(PNK_NAME)); - return emitAtomOp(nameExpr, JSOP_DELNAME); + return emitAtomOp(nameExpr->pn_atom, JSOP_DELNAME); } bool @@ -9227,7 +9249,7 @@ BytecodeEmitter::emitDeletePropertyInOptChain( } JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP; - if (!emitAtomOp(propExpr, delOp)) { + if (!emitAtomOp(propExpr->pn_atom, delOp)) { return false; } @@ -9496,10 +9518,41 @@ BytecodeEmitter::emitOptionalCalleeAndThis( switch (calleeNode->getKind()) { case PNK_NAME: { - if (!emitGetName(calleeNode, isCall)) { - return false; - } - break; + JSAtom* name = calleeNode->name(); + NameLocation loc = lookupName(name); + if (!emitGetNameAtLocation(name, loc)) { // CALLEE + return false; + } + // Need to provide |this| value for call. + if (isCall) { + switch (loc.kind()) { + case NameLocation::Kind::Dynamic: { + JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS; + if (!emitAtomOp(name, thisOp)) + return false; + break; + } + + case NameLocation::Kind::Global: + if (!emitAtomOp(name, JSOP_GIMPLICITTHIS)) + return false; + break; + + case NameLocation::Kind::Intrinsic: + case NameLocation::Kind::NamedLambdaCallee: + case NameLocation::Kind::Import: + case NameLocation::Kind::ArgumentSlot: + case NameLocation::Kind::FrameSlot: + case NameLocation::Kind::EnvironmentCoordinate: + if (!emit1(JSOP_UNDEFINED)) + return false; + break; + + case NameLocation::Kind::DynamicAnnexBVar: + MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization"); + } + } + break; } case PNK_OPTDOT: { MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); @@ -9681,19 +9734,51 @@ BytecodeEmitter::emitCalleeAndThis( bool isCall) { switch (calleeNode->getKind()) { - case PNK_NAME: - if (!emitGetName(calleeNode, isCall)) { - return false; - } - break; + case PNK_NAME: { + JSAtom* name = calleeNode->name(); + NameLocation loc = lookupName(name); + if (!emitGetNameAtLocation(name, loc)) { // CALLEE + return false; + } + // Need to provide |this| value for call. + if (isCall) { + switch (loc.kind()) { + case NameLocation::Kind::Dynamic: { + JSOp thisOp = needsImplicitThis() ? JSOP_IMPLICITTHIS : JSOP_GIMPLICITTHIS; + if (!emitAtomOp(name, thisOp)) + return false; + break; + } + + case NameLocation::Kind::Global: + if (!emitAtomOp(name, JSOP_GIMPLICITTHIS)) + return false; + break; + + case NameLocation::Kind::Intrinsic: + case NameLocation::Kind::NamedLambdaCallee: + case NameLocation::Kind::Import: + case NameLocation::Kind::ArgumentSlot: + case NameLocation::Kind::FrameSlot: + case NameLocation::Kind::EnvironmentCoordinate: + if (!emit1(JSOP_UNDEFINED)) + return false; + break; + + case NameLocation::Kind::DynamicAnnexBVar: + MOZ_CRASH("Synthesized vars for Annex B.3.3 should only be used in initialization"); + } + } + break; + } case PNK_DOT: MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); if (calleeNode->as().isSuper()) { - if (!emitSuperPropOp(calleeNode, JSOP_GETPROP_SUPER, isCall)) { + if (!emitSuperPropOp(calleeNode, JSOP_GETPROP_SUPER, isCall)) { // CALLEE THIS? return false; } } else { - if (!emitPropOp(calleeNode, isCall ? JSOP_CALLPROP : JSOP_GETPROP)) { + if (!emitPropOp(calleeNode, isCall ? JSOP_CALLPROP : JSOP_GETPROP)) { // CALLEE THIS? return false; } } @@ -9701,15 +9786,19 @@ BytecodeEmitter::emitCalleeAndThis( case PNK_ELEM: MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting); if (calleeNode->as().isSuper()) { - if (!emitSuperElemOp(calleeNode, JSOP_GETELEM_SUPER, isCall)) { + if (!emitSuperElemOp(calleeNode, JSOP_GETELEM_SUPER, isCall)) { // CALLEE THIS? return false; } } else { - if (!emitElemOp(calleeNode, isCall ? JSOP_CALLELEM : JSOP_GETELEM)) { - return false; - } if (isCall) { - if (!emit1(JSOP_SWAP)) { + if (!emitElemOp(calleeNode, JSOP_CALLELEM)) { // THIS CALLEE + return false; + } + if (!emit1(JSOP_SWAP)) { // CALLEE THIS + return false; + } + } else { + if (!emitElemOp(calleeNode, JSOP_GETELEM)) { // CALLEE return false; } } @@ -11323,7 +11412,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: case PNK_TEMPLATE_STRING: case PNK_STRING: - if (!emitAtomOp(pn, JSOP_STRING)) + if (!emitAtomOp(pn->pn_atom, JSOP_STRING)) return false; break; @@ -11608,7 +11697,7 @@ BytecodeEmitter::emitOptionalDotExpression( } opForEmit = JSOP_GETPROP_SUPER; } - if (!emitAtomOp(calleeNode, opForEmit)) { + if (!emitAtomOp(calleeNode->pn_atom, opForEmit)) { return false; } if (isCall && !emit1(JSOP_SWAP)) { @@ -11666,13 +11755,17 @@ BytecodeEmitter::emitOptionalElemExpression( // Note: the two (2) conditionals below are more-or-less // equivalent to ElemOpEmitter::emitGet in a future refactor - if (!emitElemOpBase(isCall ? JSOP_CALLELEM : JSOP_GETELEM)) { - return false; - } if (isCall) { + if (!emitElemOpBase(JSOP_CALLELEM)) { + return false; + } if (!emit1(JSOP_SWAP)) { return false; } + } else { + if (!emitElemOpBase(JSOP_GETELEM)) { + return false; + } } return true; diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index af05510894..0da65a16d9 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -467,6 +467,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitThisLiteral(ParseNode* pn); MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn); + MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe& offset); MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn); MOZ_MUST_USE bool emitSetThis(ParseNode* pn); MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn(); @@ -493,7 +494,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitIndexOp(JSOp op, uint32_t index); MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op); - MOZ_MUST_USE bool emitAtomOp(ParseNode* pn, JSOp op); MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn); MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op); @@ -525,12 +525,11 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot); MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec); - MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, - bool callContext = false); - MOZ_MUST_USE bool emitGetName(JSAtom* name, bool callContext = false) { - return emitGetNameAtLocation(name, lookupName(name), callContext); + MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name, const NameLocation& loc); + MOZ_MUST_USE bool emitGetName(JSAtom* name) { + return emitGetNameAtLocation(name, lookupName(name)); } - MOZ_MUST_USE bool emitGetName(ParseNode* pn, bool callContext = false); + MOZ_MUST_USE bool emitGetName(ParseNode* pn); template MOZ_MUST_USE bool emitSetOrInitializeNameAtLocation(HandleAtom name, const NameLocation& loc, @@ -723,7 +722,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn); MOZ_MUST_USE bool emitTemplateString(ParseNode* pn); - MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs); + MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs); MOZ_MUST_USE bool emitReturn(ParseNode* pn); MOZ_MUST_USE bool emitStatement(ParseNode* pn);