mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fix trace/interp mismsatch in |this| computation (bug 636795, r=gal, a=dmandelin).
This commit is contained in:
parent
68cb362175
commit
45609c8105
@ -8152,7 +8152,8 @@ JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureArg, CONTEXT, OBJECT, CVIPTR, DOU
|
||||
* NameResult describes how to look up name; see comment for NameResult in jstracer.h
|
||||
*/
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameResult& nr)
|
||||
TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameResult& nr,
|
||||
JSObject** scopeObjp)
|
||||
{
|
||||
JS_ASSERT(chainHead == &cx->fp()->scopeChain());
|
||||
JS_ASSERT(chainHead != globalObj);
|
||||
@ -8173,6 +8174,9 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameR
|
||||
if (!prop)
|
||||
RETURN_STOP_A("failed to find name in non-global scope chain");
|
||||
|
||||
if (scopeObjp)
|
||||
*scopeObjp = obj;
|
||||
|
||||
if (obj == globalObj) {
|
||||
// Even if the property is on the global object, we must guard against
|
||||
// the creation of properties that shadow the property in the middle
|
||||
@ -13513,30 +13517,66 @@ TraceRecorder::record_JSOP_SETELEM()
|
||||
return setElem(-3, -2, -1);
|
||||
}
|
||||
|
||||
static JSBool FASTCALL
|
||||
CheckSameGlobal(JSObject *obj, JSObject *globalObj)
|
||||
{
|
||||
return obj->getGlobal() == globalObj;
|
||||
}
|
||||
JS_DEFINE_CALLINFO_2(static, BOOL, CheckSameGlobal, OBJECT, OBJECT, 0, ACCSET_STORE_ANY)
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_CALLNAME()
|
||||
{
|
||||
JSObject* obj = &cx->fp()->scopeChain();
|
||||
if (obj != globalObj) {
|
||||
JSObject* scopeObj = &cx->fp()->scopeChain();
|
||||
LIns *funobj_ins;
|
||||
JSObject *funobj;
|
||||
if (scopeObj != globalObj) {
|
||||
Value* vp;
|
||||
LIns* ins;
|
||||
NameResult nr;
|
||||
CHECK_STATUS_A(scopeChainProp(obj, vp, ins, nr));
|
||||
stack(0, ins);
|
||||
stack(1, w.immiUndefined());
|
||||
return ARECORD_CONTINUE;
|
||||
CHECK_STATUS_A(scopeChainProp(scopeObj, vp, funobj_ins, nr, &scopeObj));
|
||||
if (!nr.tracked)
|
||||
vp = &nr.v;
|
||||
if (!vp->isObject())
|
||||
RETURN_STOP_A("callee is not an object");
|
||||
funobj = &vp->toObject();
|
||||
if (!funobj->isFunction())
|
||||
RETURN_STOP_A("callee is not a function");
|
||||
} else {
|
||||
LIns* obj_ins = w.immpObjGC(globalObj);
|
||||
JSObject* obj2;
|
||||
PCVal pcval;
|
||||
|
||||
CHECK_STATUS_A(test_property_cache(scopeObj, obj_ins, obj2, pcval));
|
||||
|
||||
if (pcval.isNull() || !pcval.isFunObj())
|
||||
RETURN_STOP_A("callee is not a function");
|
||||
|
||||
funobj = &pcval.toFunObj();
|
||||
funobj_ins = w.immpObjGC(funobj);
|
||||
}
|
||||
|
||||
LIns* obj_ins = w.immpObjGC(globalObj);
|
||||
JSObject* obj2;
|
||||
PCVal pcval;
|
||||
// Detect crossed globals early. The interpreter could decide to compute
|
||||
// a non-Undefined |this| value, and we want to make sure that we'll (1)
|
||||
// abort in this case, and (2) bail out early if a callee will need special
|
||||
// |this| computation. Note that if (scopeObj != globalObj),
|
||||
// scopeChainProp() guarantees that scopeObj is a cacheable scope.
|
||||
if (scopeObj == globalObj) {
|
||||
JSFunction *fun = funobj->getFunctionPrivate();
|
||||
if (!fun->isInterpreted() || !fun->inStrictMode()) {
|
||||
if (funobj->getGlobal() != globalObj)
|
||||
RETURN_STOP_A("callee crosses globals");
|
||||
|
||||
CHECK_STATUS_A(test_property_cache(obj, obj_ins, obj2, pcval));
|
||||
// If the funobj is not constant, we need may a guard that the
|
||||
// callee will not cross globals. This is only the case for non-
|
||||
// compile-and-go trees.
|
||||
if (!funobj_ins->isImmP() && !tree->script->compileAndGo) {
|
||||
LIns* args[] = { w.immpObjGC(globalObj), funobj_ins };
|
||||
guard(false, w.eqi0(w.call(&CheckSameGlobal_ci, args)), MISMATCH_EXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pcval.isNull() || !pcval.isFunObj())
|
||||
RETURN_STOP_A("callee is not an object");
|
||||
|
||||
stack(0, w.immpObjGC(&pcval.toFunObj()));
|
||||
stack(0, funobj_ins);
|
||||
stack(1, w.immiUndefined());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
@ -1268,7 +1268,7 @@ class TraceRecorder
|
||||
JS_REQUIRES_STACK nanojit::LIns* entryFrameIns() const;
|
||||
JS_REQUIRES_STACK JSStackFrame* frameIfInRange(JSObject* obj, unsigned* depthp = NULL) const;
|
||||
JS_REQUIRES_STACK RecordingStatus traverseScopeChain(JSObject *obj, nanojit::LIns *obj_ins, JSObject *obj2, nanojit::LIns *&obj2_ins);
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, Value*& vp, nanojit::LIns*& ins, NameResult& nr);
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL);
|
||||
JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, Value*& vp, nanojit::LIns*& ins, NameResult& nr);
|
||||
|
||||
JS_REQUIRES_STACK nanojit::LIns* arg(unsigned n);
|
||||
|
Loading…
Reference in New Issue
Block a user