Merge tracemonkey to mozilla-central.

This commit is contained in:
Robert Sayre 2009-04-08 23:55:18 -04:00
commit e45bf4929a
9 changed files with 85 additions and 31 deletions

View File

@ -4400,7 +4400,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
uint32 i = 0, n = uva->length;
for (; i < n; i++) {
JSObject *obj = parent;
for (uintN skip = UPVAR_FRAME_SKIP(uva->vector[i]); skip != 0; --skip) {
int skip = UPVAR_FRAME_SKIP(uva->vector[i]);
while (--skip > 0) {
if (!obj) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);

View File

@ -856,7 +856,7 @@ struct JSContext {
/*
* Classic Algol "display" static link optimization.
*/
#define JS_DISPLAY_SIZE 16
#define JS_DISPLAY_SIZE 16U
JSStackFrame *display[JS_DISPLAY_SIZE];

View File

@ -1508,14 +1508,15 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
}
JSStmtInfo *
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp)
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt)
{
JSStmtInfo *stmt;
JSObject *obj;
JSScope *scope;
JSScopeProperty *sprop;
for (stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) {
if (!stmt)
stmt = tc->topScopeStmt;
for (; stmt; stmt = stmt->downScope) {
if (stmt->type == STMT_WITH)
break;
@ -1912,6 +1913,14 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JSStackFrame *caller = cg->compiler->callerFrame;
if (caller) {
JS_ASSERT(cg->flags & TCF_COMPILE_N_GO);
/*
* Don't generate upvars on the left side of a for loop. See
* bug 470758.
*/
if (cg->flags & TCF_IN_FOR_INIT)
return JS_TRUE;
JS_ASSERT(caller->script);
if (!caller->fun || caller->varobj != cg->scopeChain)
return JS_TRUE;
@ -1922,18 +1931,16 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* Optimize access to function's arguments and variable and the
* arguments object.
*/
if (op != JSOP_NAME || cg->staticLevel >= JS_DISPLAY_SIZE)
if (op != JSOP_NAME)
return JS_TRUE;
JSLocalKind localKind = js_LookupLocal(cx, caller->fun, atom, &index);
if (localKind == JSLOCAL_NONE)
return JS_TRUE;
/*
* Don't generate upvars on the left side of a for loop. See
* bug 470758.
*/
if (cg->flags & TCF_IN_FOR_INIT)
uintN upvarLevel = caller->fun->u.i.script->staticLevel;
JS_ASSERT(cg->staticLevel > upvarLevel);
if (upvarLevel >= JS_DISPLAY_SIZE)
return JS_TRUE;
ale = cg->upvarList.lookup(atom);
@ -1962,8 +1969,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
index += caller->fun->nargs;
JS_ASSERT(index < JS_BIT(16));
JS_ASSERT(cg->staticLevel > caller->fun->u.i.script->staticLevel);
uintN skip = cg->staticLevel - caller->fun->u.i.script->staticLevel;
uintN skip = cg->staticLevel - upvarLevel;
cg->upvarMap.vector[ALE_INDEX(ale)] = MAKE_UPVAR_COOKIE(skip, index);
}
@ -2034,15 +2040,18 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
/*
* If op is a mutating opcode or the function is heavyweight, we fall
* back on JSOP_*NAME*.
* If op is a mutating opcode, this upvar's static level is too big to
* index into the display, or the function is heavyweight, we fall back
* on JSOP_*NAME*.
*/
if (op != JSOP_NAME || (cg->flags & TCF_FUN_HEAVYWEIGHT))
if (op != JSOP_NAME)
return JS_TRUE;
if (level >= JS_DISPLAY_SIZE)
return JS_TRUE;
if (cg->flags & TCF_FUN_HEAVYWEIGHT)
return JS_TRUE;
if (FUN_FLAT_CLOSURE(cg->fun)) {
/* Flat closure is formed one frame up from its static level. */
--skip;
op = JSOP_GETDSLOT;
} else {
/*

View File

@ -557,7 +557,8 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
* found. Otherwise return null.
*/
extern JSStmtInfo *
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp);
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp,
JSStmtInfo *stmt = NULL);
/*
* Emit code into cg for the tree rooted at pn.

View File

@ -2205,14 +2205,14 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun)
JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
JS_ASSERT(uva->length <= size_t(closure->dslots[-1]));
JSStackFrame *fp = js_GetTopStackFrame(cx);
for (uint32 i = 0, n = uva->length; i < n; i++) {
JSStackFrame *fp2 = fp;
for (uintN skip = UPVAR_FRAME_SKIP(uva->vector[i]); skip != 0; --skip)
fp2 = fp2->down;
uint32 cookie = uva->vector[i];
uintN slot = UPVAR_FRAME_SLOT(uva->vector[i]);
uintN upvarLevel = fun->u.i.script->staticLevel - UPVAR_FRAME_SKIP(cookie);
JS_ASSERT(upvarLevel <= JS_DISPLAY_SIZE);
JSStackFrame *fp2 = cx->display[upvarLevel];
uintN slot = UPVAR_FRAME_SLOT(cookie);
jsval *vp;
if (fp2->fun && slot < fp2->fun->nargs) {
vp = fp2->argv;

View File

@ -1352,6 +1352,7 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t
pnu->pn_lexdef = (JSDefinition *) pn;
pn->pn_dflags |= pnu->pn_dflags & (PND_ASSIGNED | PND_FUNARG);
}
pn->pn_dflags |= dn->pn_dflags & (PND_ASSIGNED | PND_FUNARG);
pn->dn_uses = dn;
dn->pn_defn = false;
@ -1659,6 +1660,19 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
JSParseNode *fn = funbox->node;
int fnlevel = level;
/*
* An eval can leak funbox, functions along its ancestor line, and its
* immediate kids. Since FindFunArgs uses DFS and the parser propagates
* TCF_FUN_HEAVYWEIGHT bottom up, funbox's ancestor function nodes have
* already been marked as funargs by this point. Therefore we have to
* flag only funbox->node and funbox->kids' nodes here.
*/
if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
fn->setFunArg();
for (JSFunctionBox *kid = funbox->kids; kid; kid = kid->siblings)
kid->node->setFunArg();
}
if (fn->isFunArg()) {
queue->push(funbox);
fnlevel = int(funbox->level);
@ -1676,7 +1690,7 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue)
JSDefinition *lexdep = ALE_DEFN(ale)->resolve();
if (!lexdep->isFreeVar() && int(lexdep->frameLevel()) <= fnlevel) {
fn->pn_dflags |= PND_FUNARG;
fn->setFunArg();
queue->push(funbox);
break;
}
@ -1724,7 +1738,7 @@ JSCompiler::markFunArgs(JSFunctionBox *funbox, uintN tcflags)
* which suppresses revisiting this function (namely the
* !lexdep->isFunArg() test just above).
*/
lexdep->pn_dflags |= PND_FUNARG;
lexdep->setFunArg();
JSFunctionBox *afunbox = lexdep->pn_funbox;
queue.push(afunbox);
@ -2280,7 +2294,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, JSTreeContext *tc,
if (!fn->pn_body)
return false;
fn->pn_body->pn_type = TOK_UPVARS;
fn->pn_pos = body->pn_pos;
fn->pn_body->pn_pos = body->pn_pos;
fn->pn_body->pn_names = funtc->upvars;
fn->pn_body->pn_tree = body;
funtc->upvars.clear();
@ -2958,6 +2972,19 @@ PopStatement(JSTreeContext *tc)
js_PopStatement(tc);
}
static inline bool
OuterLet(JSTreeContext *tc, JSStmtInfo *stmt, JSAtom *atom)
{
while (stmt->downScope) {
stmt = js_LexicalLookup(tc, atom, NULL, stmt->downScope);
if (!stmt)
return false;
if (stmt->type == STMT_BLOCK)
return true;
}
return false;
}
static JSBool
BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
{
@ -2996,8 +3023,10 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
} else {
if (JS_HAS_STRICT_OPTION(cx)
? op != JSOP_DEFVAR || dn_kind != JSDefinition::VAR
: op == JSOP_DEFCONST || dn_kind == JSDefinition::CONST ||
dn_kind == JSDefinition::LET) {
: op == JSOP_DEFCONST ||
dn_kind == JSDefinition::CONST ||
(dn_kind == JSDefinition::LET &&
(stmt->type != STMT_CATCH || OuterLet(tc, stmt, atom)))) {
name = js_AtomToPrintableString(cx, atom);
if (!name ||
!js_ReportCompileErrorNumber(cx, TS(tc->compiler), pn,

View File

@ -462,6 +462,7 @@ struct JSParseNode {
/* Defined below, see after struct JSDefinition. */
bool isAssigned() const;
bool isFunArg() const;
void setFunArg();
void become(JSParseNode *pn2);
void clear();
@ -725,6 +726,17 @@ JSParseNode::isFunArg() const
return test(PND_FUNARG);
}
inline void
JSParseNode::setFunArg()
{
if (pn_defn) {
((JSDefinition *)this)->pn_dflags |= PND_FUNARG;
} else if (pn_used) {
pn_lexdef->pn_dflags |= PND_FUNARG;
pn_dflags |= PND_FUNARG;
}
}
struct JSObjectBox {
JSObjectBox *traceLink;
JSObjectBox *emitLink;

View File

@ -7663,6 +7663,8 @@ TraceRecorder::record_JSOP_SETELEM()
jsid id;
if (!JSVAL_IS_INT(idx)) {
if (!JSVAL_IS_PRIMITIVE(idx))
ABORT_TRACE("non-primitive index");
// If index is not a string, turn it into a string.
if (!js_InternNonIntElementId(cx, obj, idx, &id))
ABORT_TRACE("failed to intern non-int element id");

View File

@ -204,7 +204,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
* before deserialization of bytecode. If the saved version does not match
* the current version, abort deserialization and invalidate the file.
*/
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 43)
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 44)
/*
* Library-private functions.