mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-14 15:37:55 +00:00
Bug 576148: Factor out js::UpvarCookie. (r=mrbkap, dvander)
This commit is contained in:
parent
c85e6d2711
commit
c97ac5de82
@ -4139,7 +4139,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
uint32 i = 0, n = uva->length;
|
||||
for (; i < n; i++) {
|
||||
JSObject *obj = parent;
|
||||
int skip = UPVAR_FRAME_SKIP(uva->vector[i]);
|
||||
int skip = uva->vector[i].level();
|
||||
while (--skip > 0) {
|
||||
if (!obj) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
|
@ -1860,12 +1860,12 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
|
||||
JSDefinition *dn = (JSDefinition *) JSVAL_TO_PRIVATE(v);
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
JS_ASSERT(uintN(dn->frameSlot() + depth) < JS_BIT(16));
|
||||
dn->pn_cookie += depth;
|
||||
dn->pn_cookie.set(dn->pn_cookie.level(), dn->frameSlot() + depth);
|
||||
#ifdef DEBUG
|
||||
for (JSParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
|
||||
JS_ASSERT(pnu->pn_lexdef == dn);
|
||||
JS_ASSERT(!(pnu->pn_dflags & PND_BOUND));
|
||||
JS_ASSERT(pnu->pn_cookie == FREE_UPVAR_COOKIE);
|
||||
JS_ASSERT(pnu->pn_cookie.isFree());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1942,13 +1942,13 @@ MakeUpvarForEval(JSParseNode *pn, JSCodeGenerator *cg)
|
||||
return false;
|
||||
JS_ASSERT(ALE_INDEX(ale) == cg->upvarList.count - 1);
|
||||
|
||||
uint32 *vector = cg->upvarMap.vector;
|
||||
UpvarCookie *vector = cg->upvarMap.vector;
|
||||
uint32 length = cg->upvarMap.length;
|
||||
|
||||
JS_ASSERT(ALE_INDEX(ale) <= length);
|
||||
if (ALE_INDEX(ale) == length) {
|
||||
length = 2 * JS_MAX(2, length);
|
||||
vector = (uint32 *) cx->realloc(vector, length * sizeof *vector);
|
||||
vector = reinterpret_cast<UpvarCookie *>(cx->realloc(vector, length * sizeof *vector));
|
||||
if (!vector)
|
||||
return false;
|
||||
cg->upvarMap.vector = vector;
|
||||
@ -1960,11 +1960,11 @@ MakeUpvarForEval(JSParseNode *pn, JSCodeGenerator *cg)
|
||||
JS_ASSERT(index < JS_BIT(16));
|
||||
|
||||
uintN skip = cg->staticLevel - upvarLevel;
|
||||
vector[ALE_INDEX(ale)] = MAKE_UPVAR_COOKIE(skip, index);
|
||||
vector[ALE_INDEX(ale)].set(skip, index);
|
||||
}
|
||||
|
||||
pn->pn_op = JSOP_GETUPVAR;
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(cg->staticLevel, ALE_INDEX(ale));
|
||||
pn->pn_cookie.set(cg->staticLevel, ALE_INDEX(ale));
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
}
|
||||
@ -1992,7 +1992,6 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
JSDefinition *dn;
|
||||
JSOp op;
|
||||
JSAtom *atom;
|
||||
uint32 cookie;
|
||||
JSDefinition::Kind dn_kind;
|
||||
JSAtomListElement *ale;
|
||||
uintN index;
|
||||
@ -2011,7 +2010,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
* definitions, unless a with statement or direct eval intervened.
|
||||
*/
|
||||
if (pn->pn_used) {
|
||||
JS_ASSERT(pn->pn_cookie == FREE_UPVAR_COOKIE);
|
||||
JS_ASSERT(pn->pn_cookie.isFree());
|
||||
dn = pn->pn_lexdef;
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
if (pn->isDeoptimized())
|
||||
@ -2029,7 +2028,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
atom = pn->pn_atom;
|
||||
cookie = dn->pn_cookie;
|
||||
UpvarCookie cookie = dn->pn_cookie;
|
||||
dn_kind = dn->kind();
|
||||
|
||||
/*
|
||||
@ -2066,7 +2065,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
pn->pn_op = op = JSOP_NAME;
|
||||
}
|
||||
|
||||
if (cookie == FREE_UPVAR_COOKIE) {
|
||||
if (cookie.isFree()) {
|
||||
JSStackFrame *caller = cg->parser->callerFrame;
|
||||
if (caller) {
|
||||
JS_ASSERT(cg->compileAndGo());
|
||||
@ -2153,12 +2152,12 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
default: JS_NOT_REACHED("gvar");
|
||||
}
|
||||
pn->pn_op = op;
|
||||
pn->pn_cookie = cookie;
|
||||
pn->pn_cookie.set(cookie);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
uintN level = UPVAR_FRAME_SKIP(cookie);
|
||||
uintN level = cookie.level();
|
||||
JS_ASSERT(cg->staticLevel >= level);
|
||||
|
||||
/*
|
||||
@ -2209,8 +2208,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
uintN skip = cg->staticLevel - level;
|
||||
if (skip != 0) {
|
||||
JS_ASSERT(cg->inFunction());
|
||||
JS_ASSERT_IF(UPVAR_FRAME_SLOT(cookie) != CALLEE_UPVAR_SLOT,
|
||||
cg->lexdeps.lookup(atom));
|
||||
JS_ASSERT_IF(cookie.slot() != UpvarCookie::CALLEE_SLOT, cg->lexdeps.lookup(atom));
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
JS_ASSERT(cg->fun->u.i.skipmin <= skip);
|
||||
|
||||
@ -2263,11 +2261,11 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
index = ALE_INDEX(ale);
|
||||
JS_ASSERT(index == cg->upvarList.count - 1);
|
||||
|
||||
uint32 *vector = cg->upvarMap.vector;
|
||||
UpvarCookie *vector = cg->upvarMap.vector;
|
||||
if (!vector) {
|
||||
uint32 length = cg->lexdeps.count;
|
||||
|
||||
vector = (uint32 *) js_calloc(length * sizeof *vector);
|
||||
vector = (UpvarCookie *) js_calloc(length * sizeof *vector);
|
||||
if (!vector) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
@ -2276,8 +2274,8 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
cg->upvarMap.length = length;
|
||||
}
|
||||
|
||||
uintN slot = UPVAR_FRAME_SLOT(cookie);
|
||||
if (slot != CALLEE_UPVAR_SLOT && dn_kind != JSDefinition::ARG) {
|
||||
uintN slot = cookie.slot();
|
||||
if (slot != UpvarCookie::CALLEE_SLOT && dn_kind != JSDefinition::ARG) {
|
||||
JSTreeContext *tc = cg;
|
||||
do {
|
||||
tc = tc->parent;
|
||||
@ -2286,11 +2284,12 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
slot += tc->fun->nargs;
|
||||
}
|
||||
|
||||
vector[index] = MAKE_UPVAR_COOKIE(skip, slot);
|
||||
vector[index].set(skip, slot);
|
||||
}
|
||||
|
||||
pn->pn_op = op;
|
||||
pn->pn_cookie = index;
|
||||
JS_ASSERT((index & JS_BITMASK(16)) == index);
|
||||
pn->pn_cookie.set(0, index);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -2380,7 +2379,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
|
||||
JS_ASSERT(op != PN_OP(pn));
|
||||
pn->pn_op = op;
|
||||
pn->pn_cookie = UPVAR_FRAME_SLOT(cookie);
|
||||
pn->pn_cookie.set(0, cookie.slot());
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -2556,7 +2555,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
||||
if (!BindNameToSlot(cx, cg, pn))
|
||||
return JS_FALSE;
|
||||
if (pn->pn_op != JSOP_ARGUMENTS && pn->pn_op != JSOP_CALLEE &&
|
||||
pn->pn_cookie == FREE_UPVAR_COOKIE) {
|
||||
pn->pn_cookie.isFree()) {
|
||||
/*
|
||||
* Not an argument or local variable use, and not a use of a
|
||||
* unshadowed named function expression's given name, so this
|
||||
@ -2636,8 +2635,8 @@ EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
||||
if (callContext && js_Emit1(cx, cg, JSOP_NULL) < 0)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (pn->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
EMIT_UINT16_IMM_OP(op, pn->pn_cookie);
|
||||
if (!pn->pn_cookie.isFree()) {
|
||||
EMIT_UINT16_IMM_OP(op, pn->pn_cookie.asInteger());
|
||||
} else {
|
||||
if (!EmitAtomOp(cx, pn, op, cg))
|
||||
return JS_FALSE;
|
||||
@ -2748,7 +2747,7 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
|
||||
if (!ale)
|
||||
return JS_FALSE;
|
||||
atomIndex = ALE_INDEX(ale);
|
||||
return EmitSlotIndexOp(cx, op, pn2->pn_cookie, atomIndex, cg);
|
||||
return EmitSlotIndexOp(cx, op, pn2->pn_cookie.asInteger(), atomIndex, cg);
|
||||
}
|
||||
|
||||
default:;
|
||||
@ -3621,8 +3620,8 @@ MaybeEmitVarDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
|
||||
jsatomid atomIndex;
|
||||
JSAtomListElement *ale;
|
||||
|
||||
if (pn->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
atomIndex = (jsatomid) UPVAR_FRAME_SLOT(pn->pn_cookie);
|
||||
if (!pn->pn_cookie.isFree()) {
|
||||
atomIndex = (jsatomid) pn->pn_cookie.slot();
|
||||
} else {
|
||||
ale = cg->atomList.add(cg->parser, pn->pn_atom);
|
||||
if (!ale)
|
||||
@ -3699,8 +3698,6 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
|
||||
static JSBool
|
||||
EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
{
|
||||
jsuint slot;
|
||||
|
||||
/*
|
||||
* Now emit the lvalue opcode sequence. If the lvalue is a nested
|
||||
* destructuring initialiser-form, call ourselves to handle it, then
|
||||
@ -3737,17 +3734,21 @@ EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
break;
|
||||
|
||||
case JSOP_SETLOCAL:
|
||||
slot = (jsuint) pn->pn_cookie;
|
||||
{
|
||||
jsuint slot = pn->pn_cookie.asInteger();
|
||||
EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, slot);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_SETARG:
|
||||
case JSOP_SETGVAR:
|
||||
slot = (jsuint) pn->pn_cookie;
|
||||
{
|
||||
jsuint slot = pn->pn_cookie.asInteger();
|
||||
EMIT_UINT16_IMM_OP(PN_OP(pn), slot);
|
||||
if (js_Emit1(cx, cg, JSOP_POP) < 0)
|
||||
return JS_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
@ -4141,7 +4142,7 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
||||
#endif
|
||||
} else {
|
||||
JS_ASSERT(op != JSOP_CALLEE);
|
||||
JS_ASSERT(pn2->pn_cookie != FREE_UPVAR_COOKIE || !let);
|
||||
JS_ASSERT(!pn2->pn_cookie.isFree() || !let);
|
||||
if (!MaybeEmitVarDecl(cx, cg, PN_OP(pn), pn2, &atomIndex))
|
||||
return JS_FALSE;
|
||||
|
||||
@ -4207,7 +4208,7 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
||||
if (op == JSOP_ARGUMENTS) {
|
||||
if (js_Emit1(cx, cg, op) < 0)
|
||||
return JS_FALSE;
|
||||
} else if (pn2->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
} else if (!pn2->pn_cookie.isFree()) {
|
||||
EMIT_UINT16_IMM_OP(op, atomIndex);
|
||||
} else {
|
||||
EMIT_INDEX_OP(op, atomIndex);
|
||||
@ -4773,7 +4774,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
: SRC_DECL_LET) < 0) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (pn3->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
if (!pn3->pn_cookie.isFree()) {
|
||||
op = PN_OP(pn3);
|
||||
switch (op) {
|
||||
case JSOP_GETARG: /* FALL THROUGH */
|
||||
@ -4795,8 +4796,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
JSMSG_BAD_FOR_LEFTSIDE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (pn3->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
atomIndex = (jsatomid) pn3->pn_cookie;
|
||||
if (!pn3->pn_cookie.isFree()) {
|
||||
atomIndex = (jsatomid) pn3->pn_cookie.asInteger();
|
||||
EMIT_UINT16_IMM_OP(op, atomIndex);
|
||||
} else {
|
||||
if (!EmitAtomOp(cx, pn3, op, cg))
|
||||
@ -5383,8 +5384,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
|
||||
case TOK_NAME:
|
||||
/* Inline and specialize BindNameToSlot for pn2. */
|
||||
JS_ASSERT(pn2->pn_cookie != FREE_UPVAR_COOKIE);
|
||||
EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, pn2->pn_cookie);
|
||||
JS_ASSERT(!pn2->pn_cookie.isFree());
|
||||
EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, pn2->pn_cookie.asInteger());
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -5719,8 +5720,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
case TOK_NAME:
|
||||
if (!BindNameToSlot(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
if (pn2->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
atomIndex = (jsatomid) pn2->pn_cookie;
|
||||
if (!pn2->pn_cookie.isFree()) {
|
||||
atomIndex = (jsatomid) pn2->pn_cookie.asInteger();
|
||||
} else {
|
||||
ale = cg->atomList.add(cg->parser, pn2->pn_atom);
|
||||
if (!ale)
|
||||
@ -6135,8 +6136,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
||||
if (op == JSOP_CALLEE) {
|
||||
if (js_Emit1(cx, cg, op) < 0)
|
||||
return JS_FALSE;
|
||||
} else if (pn2->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
atomIndex = (jsatomid) pn2->pn_cookie;
|
||||
} else if (!pn2->pn_cookie.isFree()) {
|
||||
atomIndex = (jsatomid) pn2->pn_cookie.asInteger();
|
||||
EMIT_UINT16_IMM_OP(op, atomIndex);
|
||||
} else {
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
|
@ -1306,23 +1306,23 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsval&
|
||||
js_GetUpvar(JSContext *cx, uintN level, uintN cookie)
|
||||
jsval &
|
||||
js_GetUpvar(JSContext *cx, uintN level, UpvarCookie cookie)
|
||||
{
|
||||
level -= UPVAR_FRAME_SKIP(cookie);
|
||||
level -= cookie.level();
|
||||
JS_ASSERT(level < JS_DISPLAY_SIZE);
|
||||
|
||||
JSStackFrame *fp = cx->display[level];
|
||||
JS_ASSERT(fp->script);
|
||||
|
||||
uintN slot = UPVAR_FRAME_SLOT(cookie);
|
||||
uintN slot = cookie.slot();
|
||||
jsval *vp;
|
||||
|
||||
if (!fp->fun || (fp->flags & JSFRAME_EVAL)) {
|
||||
vp = fp->slots() + fp->script->nfixed;
|
||||
} else if (slot < fp->fun->nargs) {
|
||||
vp = fp->argv;
|
||||
} else if (slot == CALLEE_UPVAR_SLOT) {
|
||||
} else if (slot == UpvarCookie::CALLEE_SLOT) {
|
||||
vp = &fp->argv[-2];
|
||||
slot = 0;
|
||||
} else {
|
||||
|
@ -353,8 +353,8 @@ js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
|
||||
* Given an active context, a static scope level, and an upvar cookie, return
|
||||
* the value of the upvar.
|
||||
*/
|
||||
extern jsval&
|
||||
js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
|
||||
extern jsval &
|
||||
js_GetUpvar(JSContext *cx, uintN level, js::UpvarCookie cookie);
|
||||
|
||||
/*
|
||||
* JS_LONE_INTERPRET indicates that the compiler should see just the code for
|
||||
|
@ -2879,7 +2879,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
}
|
||||
#endif
|
||||
uva = jp->script->upvars();
|
||||
index = UPVAR_FRAME_SLOT(uva->vector[index]);
|
||||
index = uva->vector[index].slot();
|
||||
}
|
||||
atom = GetArgOrVarAtom(jp, index);
|
||||
goto do_name;
|
||||
|
@ -609,7 +609,7 @@ inline void
|
||||
NameNode::initCommon(JSTreeContext *tc)
|
||||
{
|
||||
pn_expr = NULL;
|
||||
pn_cookie = FREE_UPVAR_COOKIE;
|
||||
pn_cookie.makeFree();
|
||||
pn_dflags = tc->atTopLevel() ? PND_TOPLEVEL : 0;
|
||||
if (!tc->topStmt || tc->topStmt->type == STMT_BLOCK)
|
||||
pn_dflags |= PND_BLOCKCHILD;
|
||||
@ -687,21 +687,16 @@ Parser::parse(JSObject *chain)
|
||||
return pn;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(FREE_STATIC_LEVEL == JS_BITMASK(JSFB_LEVEL_BITS));
|
||||
JS_STATIC_ASSERT(UpvarCookie::FREE_LEVEL == JS_BITMASK(JSFB_LEVEL_BITS));
|
||||
|
||||
static inline bool
|
||||
SetStaticLevel(JSTreeContext *tc, uintN staticLevel)
|
||||
{
|
||||
/*
|
||||
* Reserve FREE_STATIC_LEVEL (0xffff) in order to reserve FREE_UPVAR_COOKIE
|
||||
* (0xffffffff) and other cookies with that level.
|
||||
*
|
||||
* This is a lot simpler than error-checking every MAKE_UPVAR_COOKIE, and
|
||||
* practically speaking it leaves more than enough room for upvars. In fact
|
||||
* we might want to split cookie fields giving fewer bits for skip and more
|
||||
* for slot, but only based on evidence.
|
||||
* This is a lot simpler than error-checking every UpvarCookie::set, and
|
||||
* practically speaking it leaves more than enough room for upvars.
|
||||
*/
|
||||
if (staticLevel >= FREE_STATIC_LEVEL) {
|
||||
if (UpvarCookie::isLevelReserved(staticLevel)) {
|
||||
JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
|
||||
JSMSG_TOO_DEEP, js_function_str);
|
||||
return false;
|
||||
@ -1453,7 +1448,7 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t
|
||||
dn->pn_defn = false;
|
||||
dn->pn_used = true;
|
||||
dn->pn_lexdef = (JSDefinition *) pn;
|
||||
dn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
dn->pn_cookie.makeFree();
|
||||
dn->pn_dflags &= ~PND_BOUND;
|
||||
return dn;
|
||||
}
|
||||
@ -1497,7 +1492,7 @@ DefineArg(JSParseNode *pn, JSAtom *atom, uintN i, JSTreeContext *tc)
|
||||
argsbody->append(argpn);
|
||||
|
||||
argpn->pn_op = JSOP_GETARG;
|
||||
argpn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, i);
|
||||
argpn->pn_cookie.set(tc->staticLevel, i);
|
||||
argpn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
}
|
||||
@ -1540,7 +1535,7 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
|
||||
JSParseNode *fn = FunctionNode::create(&funcg);
|
||||
if (fn) {
|
||||
fn->pn_body = NULL;
|
||||
fn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
fn->pn_cookie.makeFree();
|
||||
|
||||
uintN nargs = fun->nargs;
|
||||
if (nargs) {
|
||||
@ -1675,7 +1670,7 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
|
||||
if (!BindLocalVariable(cx, tc->fun, atom, JSLOCAL_VAR, true))
|
||||
return JS_FALSE;
|
||||
pn->pn_op = JSOP_SETLOCAL;
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, index);
|
||||
pn->pn_cookie.set(tc->staticLevel, index);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -1765,7 +1760,7 @@ Parser::analyzeFunctions(JSFunctionBox *funbox, uint32& tcflags)
|
||||
static uintN
|
||||
FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
|
||||
{
|
||||
uintN allskipmin = FREE_STATIC_LEVEL;
|
||||
uintN allskipmin = UpvarCookie::FREE_LEVEL;
|
||||
|
||||
do {
|
||||
JSParseNode *fn = funbox->node;
|
||||
@ -1790,7 +1785,7 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
|
||||
* an upvar, whether used directly by fun, or indirectly by a function
|
||||
* nested in fun.
|
||||
*/
|
||||
uintN skipmin = FREE_STATIC_LEVEL;
|
||||
uintN skipmin = UpvarCookie::FREE_LEVEL;
|
||||
JSParseNode *pn = fn->pn_body;
|
||||
|
||||
if (pn->pn_type == TOK_UPVARS) {
|
||||
@ -1836,7 +1831,7 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
|
||||
uintN kidskipmin = FindFunArgs(funbox->kids, fnlevel, queue);
|
||||
|
||||
JS_ASSERT(kidskipmin != 0);
|
||||
if (kidskipmin != FREE_STATIC_LEVEL) {
|
||||
if (kidskipmin != UpvarCookie::FREE_LEVEL) {
|
||||
--kidskipmin;
|
||||
if (kidskipmin != 0 && kidskipmin < skipmin)
|
||||
skipmin = kidskipmin;
|
||||
@ -1849,7 +1844,7 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
|
||||
* with allskipmin, but minimize across funbox and all of its siblings,
|
||||
* to compute our return value.
|
||||
*/
|
||||
if (skipmin != FREE_STATIC_LEVEL) {
|
||||
if (skipmin != UpvarCookie::FREE_LEVEL) {
|
||||
fun->u.i.skipmin = skipmin;
|
||||
if (skipmin < allskipmin)
|
||||
allskipmin = skipmin;
|
||||
@ -1908,7 +1903,7 @@ Parser::markFunArgs(JSFunctionBox *funbox, uintN tcflags)
|
||||
* See bug 545980.
|
||||
*/
|
||||
afunbox = funbox;
|
||||
uintN calleeLevel = UPVAR_FRAME_SKIP(lexdep->pn_cookie);
|
||||
uintN calleeLevel = lexdep->pn_cookie.level();
|
||||
uintN staticLevel = afunbox->level + 1U;
|
||||
while (staticLevel != calleeLevel) {
|
||||
afunbox = afunbox->parent;
|
||||
@ -2433,7 +2428,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, JSAtom *funAtom = NULL,
|
||||
|
||||
if (atom == funAtom && lambda != 0) {
|
||||
dn->pn_op = JSOP_CALLEE;
|
||||
dn->pn_cookie = MAKE_UPVAR_COOKIE(funtc->staticLevel, CALLEE_UPVAR_SLOT);
|
||||
dn->pn_cookie.set(funtc->staticLevel, UpvarCookie::CALLEE_SLOT);
|
||||
dn->pn_dflags |= PND_BOUND;
|
||||
|
||||
/*
|
||||
@ -2556,7 +2551,7 @@ Parser::functionDef(uintN lambda, bool namePermitted)
|
||||
if (!pn)
|
||||
return NULL;
|
||||
pn->pn_body = NULL;
|
||||
pn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
pn->pn_cookie.makeFree();
|
||||
|
||||
/*
|
||||
* If a lambda, give up on JSOP_{GET,CALL}UPVAR usage unless this function
|
||||
@ -2636,7 +2631,7 @@ Parser::functionDef(uintN lambda, bool namePermitted)
|
||||
fn->pn_arity = PN_FUNC;
|
||||
fn->pn_pos.begin = pn->pn_pos.begin;
|
||||
fn->pn_body = NULL;
|
||||
fn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
fn->pn_cookie.makeFree();
|
||||
|
||||
tc->lexdeps.rawRemove(tc->parser, ale, hep);
|
||||
RecycleTree(pn, tc);
|
||||
@ -2679,7 +2674,7 @@ Parser::functionDef(uintN lambda, bool namePermitted)
|
||||
/* FALL THROUGH */
|
||||
|
||||
case JSLOCAL_VAR:
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, index);
|
||||
pn->pn_cookie.set(tc->staticLevel, index);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
break;
|
||||
|
||||
@ -2753,7 +2748,7 @@ Parser::functionDef(uintN lambda, bool namePermitted)
|
||||
return NULL;
|
||||
rhs->pn_type = TOK_NAME;
|
||||
rhs->pn_op = JSOP_GETARG;
|
||||
rhs->pn_cookie = MAKE_UPVAR_COOKIE(funtc.staticLevel, slot);
|
||||
rhs->pn_cookie.set(funtc.staticLevel, slot);
|
||||
rhs->pn_dflags |= PND_BOUND;
|
||||
|
||||
item = JSParseNode::newBinaryOrAppend(TOK_ASSIGN, JSOP_NOP, lhs, rhs, &funtc);
|
||||
@ -3173,7 +3168,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
||||
* include script->nfixed.
|
||||
*/
|
||||
pn->pn_op = JSOP_GETLOCAL;
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, n);
|
||||
pn->pn_cookie.set(tc->staticLevel, n);
|
||||
pn->pn_dflags |= PND_LET | PND_BOUND;
|
||||
|
||||
/*
|
||||
@ -3271,7 +3266,7 @@ BindGvar(JSParseNode *pn, JSTreeContext *tc, bool inWith = false)
|
||||
|
||||
if (!inWith) {
|
||||
pn->pn_op = JSOP_GETGVAR;
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, slot);
|
||||
pn->pn_cookie.set(tc->staticLevel, slot);
|
||||
pn->pn_dflags |= PND_BOUND | PND_GVAR;
|
||||
}
|
||||
}
|
||||
@ -3454,7 +3449,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
||||
if (!BindLocalVariable(cx, tc->fun, atom, localKind, false))
|
||||
return JS_FALSE;
|
||||
pn->pn_op = JSOP_GETLOCAL;
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(tc->staticLevel, index);
|
||||
pn->pn_cookie.set(tc->staticLevel, index);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -3506,16 +3501,8 @@ NoteLValue(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN dflag = PND_
|
||||
|
||||
dn->pn_dflags |= dflag;
|
||||
|
||||
if (dn->frameLevel() != tc->staticLevel) {
|
||||
/*
|
||||
* The above condition takes advantage of the all-ones nature of
|
||||
* FREE_UPVAR_COOKIE, and the reserved level FREE_STATIC_LEVEL.
|
||||
* We make a stronger assertion by excluding FREE_UPVAR_COOKIE.
|
||||
*/
|
||||
JS_ASSERT_IF(dn->pn_cookie != FREE_UPVAR_COOKIE,
|
||||
dn->frameLevel() < tc->staticLevel);
|
||||
if (dn->pn_cookie.isFree() || dn->frameLevel() < tc->staticLevel)
|
||||
tc->flags |= TCF_FUN_SETS_OUTER_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
pn->pn_dflags |= dflag;
|
||||
@ -4285,7 +4272,7 @@ PushLexicalScope(JSContext *cx, TokenStream *ts, JSTreeContext *tc,
|
||||
pn->pn_type = TOK_LEXICALSCOPE;
|
||||
pn->pn_op = JSOP_LEAVEBLOCK;
|
||||
pn->pn_objbox = blockbox;
|
||||
pn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
pn->pn_cookie.makeFree();
|
||||
pn->pn_dflags = 0;
|
||||
if (!GenerateBlockId(tc, stmt->blockid))
|
||||
return NULL;
|
||||
@ -6317,17 +6304,17 @@ class CompExprTransplanter {
|
||||
static bool
|
||||
BumpStaticLevel(JSParseNode *pn, JSTreeContext *tc)
|
||||
{
|
||||
if (pn->pn_cookie != FREE_UPVAR_COOKIE) {
|
||||
uintN level = UPVAR_FRAME_SKIP(pn->pn_cookie) + 1;
|
||||
if (!pn->pn_cookie.isFree()) {
|
||||
uintN level = pn->pn_cookie.level() + 1;
|
||||
|
||||
JS_ASSERT(level >= tc->staticLevel);
|
||||
if (level >= FREE_STATIC_LEVEL) {
|
||||
if (level >= UpvarCookie::FREE_LEVEL) {
|
||||
JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
|
||||
JSMSG_TOO_DEEP, js_function_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
pn->pn_cookie = MAKE_UPVAR_COOKIE(level, UPVAR_FRAME_SLOT(pn->pn_cookie));
|
||||
pn->pn_cookie.set(level, pn->pn_cookie.slot());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -6414,7 +6401,7 @@ CompExprTransplanter::transplant(JSParseNode *pn)
|
||||
return false;
|
||||
} else if (pn->pn_used) {
|
||||
JS_ASSERT(pn->pn_op != JSOP_NOP);
|
||||
JS_ASSERT(pn->pn_cookie == FREE_UPVAR_COOKIE);
|
||||
JS_ASSERT(pn->pn_cookie.isFree());
|
||||
|
||||
JSDefinition *dn = pn->pn_lexdef;
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
@ -7145,7 +7132,7 @@ Parser::propertySelector()
|
||||
pn->pn_op = JSOP_QNAMEPART;
|
||||
pn->pn_arity = PN_NAME;
|
||||
pn->pn_atom = tokenStream.currentToken().t_atom;
|
||||
pn->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
pn->pn_cookie.makeFree();
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
@ -7174,7 +7161,7 @@ Parser::qualifiedSuffix(JSParseNode *pn)
|
||||
? context->runtime->atomState.starAtom
|
||||
: tokenStream.currentToken().t_atom;
|
||||
pn2->pn_expr = pn;
|
||||
pn2->pn_cookie = FREE_UPVAR_COOKIE;
|
||||
pn2->pn_cookie.makeFree();
|
||||
return pn2;
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ struct JSParseNode {
|
||||
base object of TOK_DOT */
|
||||
JSDefinition *lexdef; /* lexical definition for this use */
|
||||
};
|
||||
uint32 cookie; /* upvar cookie with absolute frame
|
||||
js::UpvarCookie cookie; /* upvar cookie with absolute frame
|
||||
level (not relative skip), possibly
|
||||
in current frame */
|
||||
uint32 dflags:12, /* definition/use flags, see below */
|
||||
@ -465,12 +465,12 @@ public:
|
||||
|
||||
uintN frameLevel() const {
|
||||
JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
|
||||
return UPVAR_FRAME_SKIP(pn_cookie);
|
||||
return pn_cookie.level();
|
||||
}
|
||||
|
||||
uintN frameSlot() const {
|
||||
JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
|
||||
return UPVAR_FRAME_SLOT(pn_cookie);
|
||||
return pn_cookie.slot();
|
||||
}
|
||||
|
||||
inline bool test(uintN flag) const;
|
||||
@ -767,7 +767,7 @@ struct JSDefinition : public JSParseNode
|
||||
|
||||
bool isFreeVar() const {
|
||||
JS_ASSERT(pn_defn);
|
||||
return pn_cookie == FREE_UPVAR_COOKIE || test(PND_GVAR);
|
||||
return pn_cookie.isFree() || test(PND_GVAR);
|
||||
}
|
||||
|
||||
// Grr, windows.h or something under it #defines CONST...
|
||||
|
@ -327,7 +327,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript,
|
||||
}
|
||||
}
|
||||
for (i = 0; i != nupvars; ++i) {
|
||||
if (!JS_XDRUint32(xdr, &script->upvars()->vector[i]))
|
||||
if (!JS_XDRUint32(xdr, reinterpret_cast<uint32 *>(&script->upvars()->vector[i])))
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i != nregexps; ++i) {
|
||||
@ -894,7 +894,7 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
||||
*/
|
||||
if (nupvars != 0) {
|
||||
script->upvars()->length = nupvars;
|
||||
script->upvars()->vector = (uint32 *)cursor;
|
||||
script->upvars()->vector = reinterpret_cast<UpvarCookie *>(cursor);
|
||||
vectorSize = nupvars * sizeof(script->upvars()->vector[0]);
|
||||
memset(cursor, 0, vectorSize);
|
||||
cursor += vectorSize;
|
||||
|
@ -59,6 +59,50 @@ typedef enum JSTryNoteKind {
|
||||
JSTRY_ITER
|
||||
} JSTryNoteKind;
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Indicates a location in the stack that an upvar value can be retrieved from
|
||||
* as a two tuple of (level, slot).
|
||||
*
|
||||
* Some existing client code uses the level value as a delta, or level "skip"
|
||||
* quantity. We could probably document that through use of more types at some
|
||||
* point in the future.
|
||||
*
|
||||
* Existing XDR code wants this to be backed by a 32b integer for serialization,
|
||||
* so we oblige.
|
||||
*
|
||||
* TODO: consider giving more bits to the slot value and takings ome from the level.
|
||||
*/
|
||||
class UpvarCookie
|
||||
{
|
||||
uint32 value;
|
||||
|
||||
static const uint32 FREE_VALUE = 0xfffffffful;
|
||||
|
||||
public:
|
||||
/*
|
||||
* All levels above-and-including FREE_LEVEL are reserved so that
|
||||
* FREE_VALUE can be used as a special value.
|
||||
*/
|
||||
static const uint16 FREE_LEVEL = 0x3fff;
|
||||
static const uint16 CALLEE_SLOT = 0xffff;
|
||||
static bool isLevelReserved(uint16 level) { return level >= FREE_LEVEL; }
|
||||
|
||||
bool isFree() const { return value == FREE_VALUE; }
|
||||
uint32 asInteger() const { return value; }
|
||||
/* isFree check should be performed before using these accessors. */
|
||||
uint16 level() const { JS_ASSERT(!isFree()); return value >> 16; }
|
||||
uint16 slot() const { JS_ASSERT(!isFree()); return value; }
|
||||
|
||||
void set(const UpvarCookie &other) { set(other.level(), other.slot()); }
|
||||
void set(uint16 newLevel, uint16 newSlot) { value = (uint32(newLevel) << 16) | newSlot; }
|
||||
void makeFree() { set(0xffff, 0xffff); JS_ASSERT(isFree()); }
|
||||
};
|
||||
JS_STATIC_ASSERT(sizeof(UpvarCookie) == sizeof(uint32));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception handling record.
|
||||
*/
|
||||
@ -82,17 +126,10 @@ typedef struct JSObjectArray {
|
||||
} JSObjectArray;
|
||||
|
||||
typedef struct JSUpvarArray {
|
||||
uint32 *vector; /* array of indexed upvar cookies */
|
||||
js::UpvarCookie *vector; /* array of indexed upvar cookies */
|
||||
uint32 length; /* count of indexed upvar cookies */
|
||||
} JSUpvarArray;
|
||||
|
||||
#define CALLEE_UPVAR_SLOT 0xffff
|
||||
#define FREE_STATIC_LEVEL 0x3fff
|
||||
#define FREE_UPVAR_COOKIE 0xffffffff
|
||||
#define MAKE_UPVAR_COOKIE(skip,slot) ((skip) << 16 | (slot))
|
||||
#define UPVAR_FRAME_SKIP(cookie) ((uint32)(cookie) >> 16)
|
||||
#define UPVAR_FRAME_SLOT(cookie) ((uint16)(cookie))
|
||||
|
||||
#define JS_OBJECT_ARRAY_SIZE(length) \
|
||||
(offsetof(JSObjectArray, vector) + sizeof(JSObject *) * (length))
|
||||
|
||||
|
@ -12509,7 +12509,7 @@ TraceRecorder::upvar(JSScript* script, JSUpvarArray* uva, uintN index, jsval& v)
|
||||
* It does not work to assign the result to v, because v is an already
|
||||
* existing reference that points to something else.
|
||||
*/
|
||||
uint32 cookie = uva->vector[index];
|
||||
UpvarCookie cookie = uva->vector[index];
|
||||
jsval& vr = js_GetUpvar(cx, script->staticLevel, cookie);
|
||||
v = vr;
|
||||
|
||||
@ -12520,8 +12520,8 @@ TraceRecorder::upvar(JSScript* script, JSUpvarArray* uva, uintN index, jsval& v)
|
||||
* The upvar is not in the current trace, so get the upvar value exactly as
|
||||
* the interpreter does and unbox.
|
||||
*/
|
||||
uint32 level = script->staticLevel - UPVAR_FRAME_SKIP(cookie);
|
||||
uint32 cookieSlot = UPVAR_FRAME_SLOT(cookie);
|
||||
uint32 level = script->staticLevel - cookie.level();
|
||||
uint32 cookieSlot = cookie.slot();
|
||||
JSStackFrame* fp = cx->display[level];
|
||||
const CallInfo* ci;
|
||||
int32 slot;
|
||||
@ -12531,7 +12531,7 @@ TraceRecorder::upvar(JSScript* script, JSUpvarArray* uva, uintN index, jsval& v)
|
||||
} else if (cookieSlot < fp->fun->nargs) {
|
||||
ci = &GetUpvarArgOnTrace_ci;
|
||||
slot = cookieSlot;
|
||||
} else if (cookieSlot == CALLEE_UPVAR_SLOT) {
|
||||
} else if (cookieSlot == UpvarCookie::CALLEE_SLOT) {
|
||||
ci = &GetUpvarArgOnTrace_ci;
|
||||
slot = -2;
|
||||
} else {
|
||||
|
@ -1772,12 +1772,10 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive)
|
||||
|
||||
for (uint32 i = 0, n = uva->length; i < n; i++) {
|
||||
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[upvar_base + i]);
|
||||
uint32 cookie = uva->vector[i];
|
||||
UpvarCookie cookie = uva->vector[i];
|
||||
|
||||
printf(" %s: {skip:%u, slot:%u},\n",
|
||||
js_AtomToPrintableString(cx, atom),
|
||||
UPVAR_FRAME_SKIP(cookie),
|
||||
UPVAR_FRAME_SLOT(cookie));
|
||||
js_AtomToPrintableString(cx, atom), cookie.level(), cookie.slot());
|
||||
}
|
||||
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
|
Loading…
Reference in New Issue
Block a user