Bug 561359 - Predication of method optimization is too dynamic, causing "Assertion failure: &shape.methodObject() == &prev.toObject()". r=dvander.

--HG--
extra : rebase_source : 0a101adb7b237c56bde65ff7af3fdfcee0ad13df
This commit is contained in:
Jason Orendorff 2011-08-30 12:55:46 -05:00
Родитель 2d3dda6542
Коммит 81c001571c
9 изменённых файлов: 170 добавлений и 172 удалений

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

@ -0,0 +1,4 @@
for (let z = 0; z < 2; z++) {
with ({x: function () {}})
f = x;
}

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

@ -0,0 +1,8 @@
function f(s) {
var obj = {m: function () { return a; }};
eval(s);
return obj;
}
var obj = f("var a = 'right';");
var a = 'wrong';
assertEq(obj.m(), 'right');

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

@ -234,8 +234,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
/*
* Wrappers should really be parented to the wrapped parent of the wrapped
* object, but in that case a wrapped global object would have a NULL
* parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead
,
* parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead,
* we parent all wrappers to the global object in their home compartment.
* This loses us some transparency, and is generally very cheesy.
*/

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

@ -5014,7 +5014,7 @@ BEGIN_CASE(JSOP_LAMBDA)
if (fun->isNullClosure()) {
parent = &regs.fp()->scopeChain();
if (obj->getParent() == parent) {
if (fun->joinable()) {
jsbytecode *pc2 = AdvanceOverBlockchainOp(regs.pc + JSOP_LAMBDA_LENGTH);
JSOp op2 = JSOp(*pc2);
@ -5049,8 +5049,7 @@ BEGIN_CASE(JSOP_LAMBDA)
fun->setMethodAtom(script->getAtom(GET_FULL_INDEX(pc2 - regs.pc)));
break;
}
} else if (fun->joinable()) {
if (op2 == JSOP_CALL) {
} else if (op2 == JSOP_CALL) {
/*
* Array.prototype.sort and String.prototype.replace are
* optimized as if they are special form. We know that they
@ -5085,7 +5084,6 @@ BEGIN_CASE(JSOP_LAMBDA)
break;
}
}
}
} else {
parent = GetScopeChainFast(cx, regs.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
if (!parent)

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

@ -311,7 +311,9 @@ bool
JSFunctionBox::joinable() const
{
return function()->isNullClosure() &&
!(tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME));
(tcflags & (TCF_FUN_USES_ARGUMENTS |
TCF_FUN_USES_OWN_NAME |
TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO;
}
bool
@ -4434,8 +4436,6 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc)
#endif /* JS_HAS_DESTRUCTURING */
extern const char js_with_statement_str[];
static JSParseNode *
ContainsStmt(JSParseNode *pn, TokenKind tt)
{

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

@ -15456,7 +15456,8 @@ TraceRecorder::record_JSOP_LAMBDA()
* JSOP_INITMETHOD logic governing the early ARECORD_CONTINUE returns below
* must agree with the corresponding break-from-do-while(0) logic there.
*/
if (fun->isNullClosure() && fun->getParent() == &cx->fp()->scopeChain()) {
if (fun->isNullClosure()) {
if (fun->joinable()) {
jsbytecode *pc2 = AdvanceOverBlockchainOp(cx->regs().pc + JSOP_LAMBDA_LENGTH);
JSOp op2 = JSOp(*pc2);
@ -15472,14 +15473,13 @@ TraceRecorder::record_JSOP_LAMBDA()
stack(0, w.immpObjGC(fun));
return ARECORD_CONTINUE;
}
} else if (fun->joinable()) {
if (op2 == JSOP_CALL) {
} else if (op2 == JSOP_CALL) {
/*
* Array.prototype.sort and String.prototype.replace are
* optimized as if they are special form. We know that they
* won't leak the joined function object in obj, therefore
* we don't need to clone that compiler- created function
* object for identity/mutation reasons.
* won't leak the joined function object in obj, therefore we
* don't need to clone that compiler-created function object
* for identity/mutation reasons.
*/
int iargc = GET_ARGC(pc2);

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

@ -2465,19 +2465,25 @@ mjit::Compiler::generateMethod()
JSObjStubFun stub = stubs::Lambda;
uint32 uses = 0;
jsbytecode *pc2 = AdvanceOverBlockchainOp(PC + JSOP_LAMBDA_LENGTH);
jsbytecode *pc2 = NULL;
if (fun->joinable()) {
pc2 = AdvanceOverBlockchainOp(PC + JSOP_LAMBDA_LENGTH);
JSOp next = JSOp(*pc2);
if (next == JSOP_INITMETHOD) {
stub = stubs::LambdaForInit;
stub = stubs::LambdaJoinableForInit;
} else if (next == JSOP_SETMETHOD) {
stub = stubs::LambdaForSet;
stub = stubs::LambdaJoinableForSet;
uses = 1;
} else if (fun->joinable()) {
if (next == JSOP_CALL) {
} else if (next == JSOP_CALL) {
int iargc = GET_ARGC(pc2);
if (iargc == 1 || iargc == 2) {
stub = stubs::LambdaJoinableForCall;
uses = frame.frameSlots();
}
} else if (next == JSOP_NULL) {
pc2 += JSOP_NULL_LENGTH;
if (JSOp(*pc2) == JSOP_CALL && GET_ARGC(pc2) == 0)
stub = stubs::LambdaJoinableForNull;
}
}

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

@ -1481,28 +1481,23 @@ stubs::RegExp(VMFrame &f, JSObject *regex)
}
JSObject * JS_FASTCALL
stubs::LambdaForInit(VMFrame &f, JSFunction *fun)
stubs::LambdaJoinableForInit(VMFrame &f, JSFunction *fun)
{
JSObject *obj = fun;
jsbytecode *nextpc = (jsbytecode *) f.scratch;
if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
fun->setMethodAtom(f.script()->getAtom(GET_SLOTNO(nextpc)));
return obj;
}
return Lambda(f, fun);
JS_ASSERT(fun->joinable());
fun->setMethodAtom(f.fp()->script()->getAtom(GET_SLOTNO(nextpc)));
return fun;
}
JSObject * JS_FASTCALL
stubs::LambdaForSet(VMFrame &f, JSFunction *fun)
stubs::LambdaJoinableForSet(VMFrame &f, JSFunction *fun)
{
JSObject *obj = fun;
JS_ASSERT(fun->joinable());
jsbytecode *nextpc = (jsbytecode *) f.scratch;
if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
const Value &lref = f.regs.sp[-1];
if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
fun->setMethodAtom(f.script()->getAtom(GET_SLOTNO(nextpc)));
return obj;
}
fun->setMethodAtom(f.fp()->script()->getAtom(GET_SLOTNO(nextpc)));
return fun;
}
return Lambda(f, fun);
}
@ -1510,22 +1505,21 @@ stubs::LambdaForSet(VMFrame &f, JSFunction *fun)
JSObject * JS_FASTCALL
stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
{
JSObject *obj = fun;
JS_ASSERT(fun->joinable());
jsbytecode *nextpc = (jsbytecode *) f.scratch;
if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
/*
* Array.prototype.sort and String.prototype.replace are
* optimized as if they are special form. We know that they
* won't leak the joined function object in obj, therefore
* we don't need to clone that compiler- created function
* object for identity/mutation reasons.
* Array.prototype.sort and String.prototype.replace are optimized as if
* they are special form. We know that they won't leak the joined function
* object fun, therefore we don't need to clone that compiler-created
* function object for identity/mutation reasons.
*/
int iargc = GET_ARGC(nextpc);
/*
* Note that we have not yet pushed obj as the final argument,
* so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
* is the callee for this JSOP_CALL.
* Note that we have not yet pushed fun as the final argument, so
* regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)], is the callee
* for this JSOP_CALL.
*/
const Value &cref = f.regs.sp[1 - (iargc + 2)];
JSObject *callee;
@ -1536,10 +1530,9 @@ stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
if (native) {
if (iargc == 1 && native == array_sort)
return obj;
return fun;
if (iargc == 2 && native == str_replace)
return obj;
}
return fun;
}
}
return Lambda(f, fun);
@ -1548,23 +1541,13 @@ stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
JSObject * JS_FASTCALL
stubs::LambdaJoinableForNull(VMFrame &f, JSFunction *fun)
{
JSObject *obj = fun;
jsbytecode *nextpc = (jsbytecode *) f.scratch;
if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
jsbytecode *pc2 = nextpc + JSOP_NULL_LENGTH;
JSOp op2 = JSOp(*pc2);
if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
return obj;
}
return Lambda(f, fun);
JS_ASSERT(fun->joinable());
return fun;
}
JSObject * JS_FASTCALL
stubs::Lambda(VMFrame &f, JSFunction *fun)
{
JSObject *obj = fun;
JSObject *parent;
if (fun->isNullClosure()) {
parent = &f.fp()->scopeChain();
@ -1574,7 +1557,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun)
THROWV(NULL);
}
obj = CloneFunctionObject(f.cx, fun, parent, true);
JSObject *obj = CloneFunctionObject(f.cx, fun, parent, true);
if (!obj)
THROWV(NULL);

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

@ -156,8 +156,8 @@ JSObject * JS_FASTCALL DefLocalFun(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL RegExp(VMFrame &f, JSObject *regex);
JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaForInit(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaForSet(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForInit(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForSet(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForNull(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL FlatLambda(VMFrame &f, JSFunction *fun);