Merge tracemonkey to mozilla-central.
This commit is contained in:
Коммит
581aa9e694
|
@ -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)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче