Bug 601398 - Use new instructions, rather than source notes, to obtain block chain (r=igor)

This commit is contained in:
Bill McCloskey 2010-10-06 10:40:07 -07:00
Родитель 5fcaf2d864
Коммит bf34ff421b
4 изменённых файлов: 51 добавлений и 28 удалений

Просмотреть файл

@ -1514,15 +1514,20 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt)
}
static JSBool
EmitBlockChain(JSContext *cx, JSCodeGenerator *cg)
EmitKnownBlockChain(JSContext *cx, JSCodeGenerator *cg, JSObjectBox *box)
{
JSObjectBox *box = cg->blockChainBox;
if (box)
return EmitIndexOp(cx, JSOP_BLOCKCHAIN, box->index, cg);
else
return js_Emit1(cx, cg, JSOP_NULLBLOCKCHAIN) >= 0;
}
static JSBool
EmitBlockChain(JSContext *cx, JSCodeGenerator *cg)
{
return EmitKnownBlockChain(cx, cg, cg->blockChainBox);
}
static ptrdiff_t
EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
ptrdiff_t *lastp, JSAtomListElement *label, JSSrcNoteType noteType)
@ -1541,7 +1546,14 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
if (index < 0)
return -1;
return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
ptrdiff_t result = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
if (result < 0)
return result;
if (!EmitBlockChain(cx, cg))
return -1;
return result;
}
static JSBool
@ -5368,16 +5380,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
tryEnd = CG_OFFSET(cg);
JSObjectBox *prevBox = NULL;
/* If this try has a catch block, emit it. */
pn2 = pn->pn_kid2;
lastCatch = NULL;
if (pn2) {
JSObjectBox *prevBox = NULL;
uintN count = 0; /* previous catch block's population */
/*
* The emitted code for a catch block looks like:
*
* blockchain
* [throwing] only if 2nd+ catch block
* [leaveblock] only if 2nd+ catch block
* enterblock with SRC_CATCH
@ -5403,6 +5416,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JS_ASSERT(cg->stackDepth == depth);
guardJump = GUARDJUMP(stmtInfo);
if (guardJump != -1) {
if (EmitKnownBlockChain(cx, cg, prevBox) < 0)
return JS_FALSE;
/* Fix up and clean up previous catch block. */
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, guardJump);
@ -5487,6 +5503,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* stack unbalanced.
*/
if (lastCatch && lastCatch->pn_kid2) {
if (EmitKnownBlockChain(cx, cg, prevBox) < 0)
return JS_FALSE;
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, GUARDJUMP(stmtInfo));
/* Sync the stack to take into account pushed exception. */
@ -5501,6 +5520,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
js_Emit1(cx, cg, JSOP_THROW) < 0) {
return JS_FALSE;
}
if (EmitBlockChain(cx, cg) < 0)
return JS_FALSE;
}
JS_ASSERT(cg->stackDepth == depth);
@ -5682,6 +5704,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
CG_BASE(cg)[top] = JSOP_SETRVAL;
if (js_Emit1(cx, cg, JSOP_RETRVAL) < 0)
return JS_FALSE;
if (EmitBlockChain(cx, cg) < 0)
return JS_FALSE;
}
break;

Просмотреть файл

@ -181,28 +181,29 @@ js_GetBlockChain(JSContext *cx, JSStackFrame *fp)
jsbytecode *pc = fp->hasImacropc() ? fp->imacropc() : fp->pc(cx);
JS_ASSERT(pc >= start && pc < script->code + script->length);
ptrdiff_t oplen;
JSObject *blockChain = NULL;
for (jsbytecode *p = start; p < pc; p += oplen) {
JSOp op = js_GetOpcode(cx, script, p);
const JSCodeSpec *cs = &js_CodeSpec[op];
oplen = cs->length;
if (oplen < 0)
oplen = js_GetVariableBytecodeLength(p);
if (op == JSOP_ENTERBLOCK) {
blockChain = script->getObject(GET_INDEX(p));
} else if (op == JSOP_LEAVEBLOCK || op == JSOP_LEAVEBLOCKEXPR) {
/*
* Some LEAVEBLOCK instructions are due to early exits via
* return/break/etc. from block-scoped loops and functions.
* We should ignore these instructions, since they don't really
* signal the end of the block.
*/
jssrcnote *sn = js_GetSrcNote(script, p);
if (!(sn && SN_TYPE(sn) == SRC_HIDDEN))
JSObject *blockChain = NULL;
if (*pc == JSOP_BLOCKCHAIN) {
blockChain = script->getObject(GET_INDEX(pc));
} else if (*pc == JSOP_NULLBLOCKCHAIN) {
blockChain = NULL;
} else {
ptrdiff_t oplen;
for (jsbytecode *p = start; p < pc; p += oplen) {
JSOp op = js_GetOpcode(cx, script, p);
const JSCodeSpec *cs = &js_CodeSpec[op];
oplen = cs->length;
if (oplen < 0)
oplen = js_GetVariableBytecodeLength(p);
if (op == JSOP_ENTERBLOCK)
blockChain = script->getObject(GET_INDEX(p));
else if (op == JSOP_LEAVEBLOCK || op == JSOP_LEAVEBLOCKEXPR)
blockChain = blockChain->getParent();
else if (op == JSOP_BLOCKCHAIN)
blockChain = script->getObject(GET_INDEX(p));
else if (op == JSOP_NULLBLOCKCHAIN)
blockChain = NULL;
}
}
@ -6746,8 +6747,6 @@ END_CASE(JSOP_ARRAYPUSH)
switch (tn->kind) {
case JSTRY_CATCH:
JS_ASSERT(js_GetOpcode(cx, regs.fp->script(), regs.pc) == JSOP_ENTERBLOCK);
#if JS_HAS_GENERATORS
/* Catch cannot intercept the closing of a generator. */
if (JS_UNLIKELY(cx->exception.isMagic(JS_GENERATOR_CLOSING)))

Просмотреть файл

@ -4,7 +4,7 @@ x = "notset";
function myparent(nested) {
if (nested) {
/* noop call in myparent */
trap(myparent, 49, "success()");
trap(myparent, 50, "success()");
} else {
myparent(true);
x = "failure";

Просмотреть файл

@ -13,7 +13,7 @@ function myparent(nested) {
}
}
/* JSOP_CALL to doNothing in myparent with nested = false. */
trap(myparent, 35, "myparent(true)");
trap(myparent, 36, "myparent(true)");
function success() {
x = "success";