mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 23:08:39 +09:00
Issue #2155 - Refactor BytecodeEmitter in preparation for *Emitter work
This removed a bit of reduncancy and makes stack building easier to follow.
- Move call context handling from BytecodeEmitter::emitGetNameAtLocation to BytecodeEmitter::emitCalleeAndThis
- Add stack comments for prop and elem related methods in BytecodeEmitter
- Remove emitAtopOp with NameNode*
- Pass JSOp to BytecodeEmitter::emitAssignment (modified)
- Add BytecodeEmitter::emitGetFunctionThis variant with offset
Based-on: m-c 1466000/{2-6}
This commit is contained in:
parent
da05c050e3
commit
a2fd8846b6
2 changed files with 245 additions and 153 deletions
|
|
@ -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 <typename RHSEmitter>
|
||||
|
|
@ -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<PropertyAccess>().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<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropLHS(&target->as<PropertyAccess>().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<PropertyByValue>().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<PropertyAccess>().isSuper())
|
||||
if (target->as<PropertyAccess>().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<PropertyByValue>().isSuper()) {
|
||||
if (target->as<PropertyByValue>().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<PropertyAccess>().isSuper()) {
|
||||
if (!emitSuperPropLHS(&lhs->as<PropertyAccess>().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<PropertyByValue>().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<PropertyAccess>().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<PropertyByValue>().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<PropertyAccess>().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<PropertyByValue>().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<uint32_t>& 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<PropertyAccess>().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<PropertyByValue>().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;
|
||||
|
|
|
|||
|
|
@ -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<uint32_t>& 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 <typename RHSEmitter>
|
||||
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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue