зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
2d3dda6542
Коммит
81c001571c
|
@ -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 = ®s.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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче