Merge tracemonkey to mozilla-central.

This commit is contained in:
Robert Sayre 2009-06-08 22:38:37 -04:00
Родитель 76c5ce284a e8c3b5830e
Коммит 581aa9e694
8 изменённых файлов: 141 добавлений и 31 удалений

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

@ -60,6 +60,7 @@
#include "jsparse.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jsstr.h"
#include "jsautooplen.h"
@ -1241,6 +1242,9 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
const char *filename, uintN lineno,
jsval *rval)
{
JS_ASSERT_NOT_ON_TRACE(cx);
JS_ASSERT(cx->fp);
JSObject *scobj;
JSScript *script;
JSBool ok;

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

@ -1987,13 +1987,29 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* pre-increment and pre-decrement ops, our caller will have to emit
* JSOP_POS, JSOP_ONE, and JSOP_ADD as well).
*
* Leave JSOP_DELNAME as is so it can be turned into JSOP_FALSE as
* appropriate, further below.
* Turn JSOP_DELNAME into JSOP_FALSE if dn is known, as all declared
* bindings visible to the compiler are permanent in JS unless the
* declaration originates in eval code. We detect eval code by testing
* cg->compiler->callerFrame, which is set only by eval or a debugger
* equivalent.
*
* Note that this callerFrame non-null test must be qualified by testing
* !cg->funbox to exclude function code nested in eval code, which is not
* subject to the deletable binding exception.
*/
switch (op) {
case JSOP_NAME:
case JSOP_SETCONST:
break;
case JSOP_DELNAME:
if (dn_kind != JSDefinition::UNKNOWN) {
if (cg->compiler->callerFrame && !cg->funbox)
JS_ASSERT(cg->flags & TCF_COMPILE_N_GO);
else
pn->pn_op = JSOP_FALSE;
pn->pn_dflags |= PND_BOUND;
return JS_TRUE;
}
break;
default:
if (pn->isConst())
@ -2228,7 +2244,6 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
case JSOP_DELNAME: op = JSOP_FALSE; break;
default: JS_NOT_REACHED("let");
}
break;
@ -2242,7 +2257,6 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case JSOP_DECNAME: op = JSOP_DECARG; break;
case JSOP_NAMEDEC: op = JSOP_ARGDEC; break;
case JSOP_FORNAME: op = JSOP_FORARG; break;
case JSOP_DELNAME: op = JSOP_FALSE; break;
default: JS_NOT_REACHED("arg");
}
JS_ASSERT(!pn->isConst());
@ -2254,10 +2268,6 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JS_ASSERT((cg->fun->flags & JSFUN_LAMBDA) && atom == cg->fun->atom);
switch (op) {
case JSOP_DELNAME:
if (!(cg->flags & TCF_FUN_HEAVYWEIGHT))
op = JSOP_FALSE;
break;
default:
/*
* Leave pn->pn_op == JSOP_NAME if cg->fun is heavyweight, as
@ -2270,6 +2280,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* lexically bound in an outer declarative environment from the
* function's activation. See jsfun.cpp:call_resolve.
*/
JS_ASSERT(op != JSOP_DELNAME);
if (!(cg->flags & TCF_FUN_HEAVYWEIGHT)) {
op = JSOP_CALLEE;
pn->pn_dflags |= PND_CONST;
@ -2295,7 +2306,6 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
case JSOP_DELNAME: op = JSOP_FALSE; break;
default: JS_NOT_REACHED("local");
}
JS_ASSERT_IF(dn_kind == JSDefinition::CONST, pn->pn_dflags & PND_CONST);
@ -6750,6 +6760,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (pn->pn_arity == PN_LIST) {
JS_ASSERT(pn->pn_count != 0);
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->pn_type == TOK_LC &&
js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
return JS_FALSE;
}
if (!js_EmitTree(cx, cg, pn2))
return JS_FALSE;
if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)

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

@ -2460,10 +2460,12 @@ JSObject * JS_FASTCALL
js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
{
JS_ASSERT(FUN_FLAT_CLOSURE(fun));
JS_ASSERT(fun->u.i.script->upvarsOffset);
JS_ASSERT((fun->u.i.script->upvarsOffset
? JS_SCRIPT_UPVARS(fun->u.i.script)->length
: 0) == fun->u.i.nupvars);
JSObject *closure = js_CloneFunctionObject(cx, fun, scopeChain);
if (!closure)
if (!closure || fun->u.i.nupvars == 0)
return closure;
uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
@ -2482,8 +2484,8 @@ JSObject *
js_NewFlatClosure(JSContext *cx, JSFunction *fun)
{
JSObject *closure = js_AllocFlatClosure(cx, fun, cx->fp->scopeChain);
if (!closure)
return NULL;
if (!closure || fun->u.i.nupvars == 0)
return closure;
JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
JS_ASSERT(uva->length <= size_t(closure->dslots[-1]));

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

@ -3495,10 +3495,11 @@ typedef struct FindPropValEntry {
} FindPropValEntry;
#define ASSERT_VALID_PROPERTY_KEY(pnkey) \
JS_ASSERT((pnkey)->pn_arity == PN_NULLARY && \
((pnkey)->pn_type == TOK_NUMBER || \
(pnkey)->pn_type == TOK_STRING || \
(pnkey)->pn_type == TOK_NAME))
JS_ASSERT(((pnkey)->pn_arity == PN_NULLARY && \
((pnkey)->pn_type == TOK_NUMBER || \
(pnkey)->pn_type == TOK_STRING || \
(pnkey)->pn_type == TOK_NAME)) || \
(pnkey)->pn_arity == PN_NAME && (pnkey)->pn_type == TOK_NAME)
static JSDHashNumber
HashFindPropValKey(JSDHashTable *table, const void *key)
@ -3626,6 +3627,9 @@ FindPropertyValue(JSParseNode *pn, JSParseNode *pnid, FindPropValData *data)
* If data is null, the caller is AssignExpr and instead of binding variables,
* we specialize lvalues in the propery value positions of the left-hand side.
* If right is null, just check for well-formed lvalues.
*
* See also UndominateInitializers, immediately below. If you change either of
* these functions, you might have to change the other to match.
*/
static JSBool
CheckDestructuring(JSContext *cx, BindData *data,
@ -3778,6 +3782,86 @@ CheckDestructuring(JSContext *cx, BindData *data,
goto out;
}
/*
* This is a greatly pared down version of CheckDestructuring that extends the
* pn_pos.end source coordinate of each name in a destructuring binding such as
*
* var [x, y] = [function () y, 42];
*
* to cover its corresponding initializer, so that the initialized binding does
* not appear to dominate any closures in its initializer. See bug 496134.
*
* The quick-and-dirty dominance computation in JSCompiler::setFunctionKinds is
* not very precise. With one-pass SSA construction from structured source code
* (see "Single-Pass Generation of Static Single Assignment Form for Structured
* Languages", Brandis and Mössenböck), we could do much better.
*
* See CheckDestructuring, immediately above. If you change either of these
* functions, you might have to change the other to match.
*/
static JSBool
UndominateInitializers(JSParseNode *left, JSParseNode *right, JSTreeContext *tc)
{
FindPropValData fpvd;
JSParseNode *lhs, *rhs;
JS_ASSERT(left->pn_type != TOK_ARRAYCOMP);
JS_ASSERT(right);
#if JS_HAS_DESTRUCTURING_SHORTHAND
if (right->pn_arity == PN_LIST && (right->pn_xflags & PNX_DESTRUCT)) {
js_ReportCompileErrorNumber(tc->compiler->context, TS(tc->compiler), right,
JSREPORT_ERROR, JSMSG_BAD_OBJECT_INIT);
return JS_FALSE;
}
#endif
if (right->pn_type != left->pn_type)
return JS_TRUE;
fpvd.table.ops = NULL;
lhs = left->pn_head;
if (left->pn_type == TOK_RB) {
rhs = right->pn_head;
while (lhs && rhs) {
/* Nullary comma is an elision; binary comma is an expression.*/
if (lhs->pn_type != TOK_COMMA || lhs->pn_arity != PN_NULLARY) {
if (lhs->pn_type == TOK_RB || lhs->pn_type == TOK_RC) {
if (!UndominateInitializers(lhs, rhs, tc))
return JS_FALSE;
} else {
lhs->pn_pos.end = rhs->pn_pos.end;
}
}
lhs = lhs->pn_next;
rhs = rhs->pn_next;
}
} else {
JS_ASSERT(left->pn_type == TOK_RC);
fpvd.numvars = left->pn_count;
fpvd.maxstep = 0;
while (lhs) {
JS_ASSERT(lhs->pn_type == TOK_COLON);
JSParseNode *pn = lhs->pn_right;
rhs = FindPropertyValue(right, lhs->pn_left, &fpvd);
if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
if (rhs && !UndominateInitializers(pn, rhs, tc))
return JS_FALSE;
} else {
if (rhs)
pn->pn_pos.end = rhs->pn_pos.end;
}
lhs = lhs->pn_next;
}
}
return JS_TRUE;
}
static JSParseNode *
DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
JSTokenType tt)
@ -5488,10 +5572,10 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, bool inLetHead)
if (!pn2)
return NULL;
if (!CheckDestructuring(cx, &data, pn2, NULL, tc))
return NULL;
if ((tc->flags & TCF_IN_FOR_INIT) &&
js_PeekToken(cx, ts) == TOK_IN) {
if (!CheckDestructuring(cx, &data, pn2, NULL, tc))
return NULL;
pn->append(pn2);
continue;
}
@ -5514,13 +5598,12 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, bool inLetHead)
}
#endif
pn2 = NewBinary(TOK_ASSIGN, JSOP_NOP, pn2, init, tc);
if (!pn2 ||
!CheckDestructuring(cx, &data,
pn2->pn_left, pn2->pn_right,
tc)) {
if (!init || !UndominateInitializers(pn2, init, tc))
return NULL;
pn2 = NewBinary(TOK_ASSIGN, JSOP_NOP, pn2, init, tc);
if (!pn2)
return NULL;
}
pn->append(pn2);
continue;
}

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

@ -1903,15 +1903,14 @@ js_GetUpvarOnTrace(JSContext* cx, uint32 level, uint32 cookie, uint32 callDepth,
for (FrameInfo** fip2 = state->callstackBase; fip2 <= fip; fip2++)
nativeStackFramePos += (*fip2)->spdist;
nativeStackFramePos -= (2 + (*fip)->get_argc());
uint8* typemap = (uint8*) (fi+1);
return GetUpvarOnTraceTail(state, cookie, nativeStackFramePos,
typemap, result);
fi->get_typemap(), result);
}
}
if (state->outermostTree->script->staticLevel == upvarLevel) {
return GetUpvarOnTraceTail(state, cookie, 0,
state->outermostTree->stackTypeMap(), result);
return GetUpvarOnTraceTail(state, cookie, 0, state->callstackBase[0]->get_typemap(),
result);
}
/*
@ -2438,6 +2437,7 @@ TraceRecorder::snapshot(ExitType exitType)
for (unsigned n = 0; n < nexits; ++n) {
VMSideExit* e = exits[n];
if (e->pc == pc && e->imacpc == fp->imacpc &&
ngslots == e->numGlobalSlots &&
!memcmp(getFullTypeMap(exits[n]), typemap, typemap_size)) {
AUDIT(mergedLoopExits);
return e;

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

@ -317,6 +317,9 @@ struct FrameInfo {
}
uint16 get_argc() const { return argc & ~CONSTRUCTING_MASK; }
bool is_constructing() const { return (argc & CONSTRUCTING_MASK) != 0; }
// The typemap just before the callee is called.
uint8* get_typemap() { return (uint8*) (this+1); }
};
struct UnstableExit

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

@ -465,6 +465,7 @@ namespace nanojit
case LIR_ldq:
case LIR_qiand:
case LIR_qiadd:
case LIR_qjoin:
case LIR_qcmov:
case LIR_fadd:
case LIR_fsub:

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

@ -152,8 +152,11 @@ function process_cp_pre_genericize(fndecl)
let i;
for (i in xrange(stack.length - 1, -1, -1)) {
if (TREE_CODE(stack[i]) != NOP_EXPR)
break;
if (TREE_CODE(stack[i]) == NOP_EXPR ||
TREE_CODE(stack[i]) == COMPOUND_EXPR)
continue;
break;
}
let assign = stack[i];
switch (TREE_CODE(assign)) {