зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1217001 - Part 11: Get rid of the last goto in BytecodeEmitter::emitVariables(). r=shu.
--HG-- extra : commitid : 4CPmLmrWL1l extra : rebase_source : a44f203eb9d6dd35aa6914bc68c9ee7a285674de
This commit is contained in:
Родитель
c1ac383a91
Коммит
536ae59cee
|
@ -4226,7 +4226,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
|
|||
return false;
|
||||
next = binding->pn_next;
|
||||
|
||||
ParseNode* initializer;
|
||||
if (binding->isKind(PNK_ARRAY) || binding->isKind(PNK_OBJECT)) {
|
||||
// Destructuring BindingPattern in a `for` loop head:
|
||||
// for (let [x, y] of pts) ...;
|
||||
|
@ -4277,103 +4276,105 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
|
|||
* here and initialize the name.
|
||||
*/
|
||||
if (binding->pn_left->isKind(PNK_NAME)) {
|
||||
initializer = binding->pn_right;
|
||||
binding = binding->pn_left;
|
||||
goto do_name;
|
||||
}
|
||||
|
||||
initializer = binding->pn_left;
|
||||
if (!emitDestructuringDecls(pn->getOp(), initializer))
|
||||
return false;
|
||||
|
||||
if (!emitTree(binding->pn_right))
|
||||
return false;
|
||||
|
||||
if (!emitDestructuringOpsHelper(initializer, emitOption))
|
||||
return false;
|
||||
|
||||
if (emitOption == InitializeVars) {
|
||||
if (!emit1(JSOP_POP))
|
||||
if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
|
||||
return false;
|
||||
} else {
|
||||
ParseNode* initializer = binding->pn_left;
|
||||
if (!emitDestructuringDecls(pn->getOp(), initializer))
|
||||
return false;
|
||||
|
||||
if (!emitTree(binding->pn_right))
|
||||
return false;
|
||||
|
||||
if (!emitDestructuringOpsHelper(initializer, emitOption))
|
||||
return false;
|
||||
|
||||
if (emitOption == InitializeVars) {
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Load initializer early to share code above that jumps to
|
||||
* do_name. NB: if this var redeclares an existing binding, then
|
||||
* `binding` is linked on its definition's use-chain and pn_expr
|
||||
* has been overlayed with pn_lexdef.
|
||||
*/
|
||||
initializer = binding->maybeExpr();
|
||||
|
||||
do_name:
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
if (!bindNameToSlot(binding))
|
||||
if (!emitSingleVariable(pn, binding, binding->maybeExpr(), emitOption))
|
||||
return false;
|
||||
|
||||
JSOp op;
|
||||
op = binding->getOp();
|
||||
MOZ_ASSERT(op != JSOP_CALLEE);
|
||||
MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP));
|
||||
|
||||
jsatomid atomIndex;
|
||||
if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex))
|
||||
return false;
|
||||
|
||||
if (initializer) {
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
if (op == JSOP_SETNAME ||
|
||||
op == JSOP_STRICTSETNAME ||
|
||||
op == JSOP_SETGNAME ||
|
||||
op == JSOP_STRICTSETGNAME ||
|
||||
op == JSOP_SETINTRINSIC)
|
||||
{
|
||||
MOZ_ASSERT(emitOption != PushInitialValues);
|
||||
JSOp bindOp;
|
||||
if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME)
|
||||
bindOp = JSOP_BINDNAME;
|
||||
else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
|
||||
bindOp = JSOP_BINDGNAME;
|
||||
else
|
||||
bindOp = JSOP_BINDINTRINSIC;
|
||||
if (!emitIndex32(bindOp, atomIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool oldEmittingForInit = emittingForInit;
|
||||
emittingForInit = false;
|
||||
if (!emitTree(initializer))
|
||||
return false;
|
||||
emittingForInit = oldEmittingForInit;
|
||||
} else if (op == JSOP_INITLEXICAL ||
|
||||
op == JSOP_INITGLEXICAL ||
|
||||
emitOption == PushInitialValues)
|
||||
{
|
||||
// 'let' bindings cannot be used before they are
|
||||
// initialized. JSOP_INITLEXICAL distinguishes the binding site.
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
if (!emit1(JSOP_UNDEFINED))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are not initializing, nothing to pop. If we are initializing
|
||||
// lets, we must emit the pops.
|
||||
if (emitOption == InitializeVars) {
|
||||
MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr);
|
||||
if (!binding->pn_scopecoord.isFree()) {
|
||||
if (!emitVarOp(binding, op))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIndexOp(op, atomIndex))
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer,
|
||||
VarEmitOption emitOption)
|
||||
{
|
||||
// NB: if this var redeclares an existing binding, then `binding` is linked
|
||||
// on its definition's use-chain and pn_expr has been overlayed with
|
||||
// pn_lexdef.
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
if (!bindNameToSlot(binding))
|
||||
return false;
|
||||
|
||||
JSOp op = binding->getOp();
|
||||
MOZ_ASSERT(op != JSOP_CALLEE);
|
||||
MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP));
|
||||
|
||||
jsatomid atomIndex;
|
||||
if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex))
|
||||
return false;
|
||||
|
||||
if (initializer) {
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
if (op == JSOP_SETNAME ||
|
||||
op == JSOP_STRICTSETNAME ||
|
||||
op == JSOP_SETGNAME ||
|
||||
op == JSOP_STRICTSETGNAME ||
|
||||
op == JSOP_SETINTRINSIC)
|
||||
{
|
||||
MOZ_ASSERT(emitOption != PushInitialValues);
|
||||
JSOp bindOp;
|
||||
if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME)
|
||||
bindOp = JSOP_BINDNAME;
|
||||
else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
|
||||
bindOp = JSOP_BINDGNAME;
|
||||
else
|
||||
bindOp = JSOP_BINDINTRINSIC;
|
||||
if (!emitIndex32(bindOp, atomIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool oldEmittingForInit = emittingForInit;
|
||||
emittingForInit = false;
|
||||
if (!emitTree(initializer))
|
||||
return false;
|
||||
emittingForInit = oldEmittingForInit;
|
||||
} else if (op == JSOP_INITLEXICAL ||
|
||||
op == JSOP_INITGLEXICAL ||
|
||||
emitOption == PushInitialValues)
|
||||
{
|
||||
// 'let' bindings cannot be used before they are
|
||||
// initialized. JSOP_INITLEXICAL distinguishes the binding site.
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
if (!emit1(JSOP_UNDEFINED))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are not initializing, nothing to pop. If we are initializing
|
||||
// lets, we must emit the pops.
|
||||
if (emitOption == InitializeVars) {
|
||||
MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr);
|
||||
if (!binding->pn_scopecoord.isFree()) {
|
||||
if (!emitVarOp(binding, op))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIndexOp(op, atomIndex))
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
|
||||
{
|
||||
|
|
|
@ -470,6 +470,8 @@ struct BytecodeEmitter
|
|||
|
||||
bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result);
|
||||
bool emitVariables(ParseNode* pn, VarEmitOption emitOption);
|
||||
bool emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer,
|
||||
VarEmitOption emitOption);
|
||||
|
||||
bool emitNewInit(JSProtoKey key);
|
||||
bool emitSingletonInitialiser(ParseNode* pn);
|
||||
|
|
Загрузка…
Ссылка в новой задаче