mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 636820: Use new |this| computation in mjit implementation of callgname, r=dvander,gal, a=blocking
This commit is contained in:
parent
ccbfde2165
commit
8e2207d22a
14
js/src/jit-test/tests/basic/testBug634590ma.js
Normal file
14
js/src/jit-test/tests/basic/testBug634590ma.js
Normal file
@ -0,0 +1,14 @@
|
||||
// |jit-test| mjitalways;
|
||||
|
||||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
assertEq(evalcx('this.f = parent.f;\n' +
|
||||
'var s = "";\n' +
|
||||
'for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
's',
|
||||
sb),
|
||||
"innerinnerinnerinnerinnerinnerinnerinnerinnerinner");
|
@ -1889,7 +1889,7 @@ mjit::Compiler::generateMethod()
|
||||
BEGIN_CASE(JSOP_CALLGNAME)
|
||||
jsop_getgname(fullAtomIndex(PC));
|
||||
if (op == JSOP_CALLGNAME)
|
||||
frame.push(UndefinedValue());
|
||||
jsop_callgname_epilogue();
|
||||
END_CASE(JSOP_GETGNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_SETGNAME)
|
||||
@ -4368,6 +4368,77 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate just the epilogue code that is specific to callgname. The rest
|
||||
* is shared with getgname.
|
||||
*/
|
||||
void
|
||||
mjit::Compiler::jsop_callgname_epilogue()
|
||||
{
|
||||
/*
|
||||
* This slow path does the same thing as the interpreter.
|
||||
*/
|
||||
if (!script->compileAndGo) {
|
||||
prepareStubCall(Uses(1));
|
||||
INLINE_STUBCALL(stubs::PushImplicitThisForGlobal);
|
||||
frame.pushSynced();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fast path for known-not-an-object callee. */
|
||||
FrameEntry *fval = frame.peek(-1);
|
||||
if (fval->isNotType(JSVAL_TYPE_OBJECT)) {
|
||||
frame.push(UndefinedValue());
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimized version. This inlines the common case, calling a
|
||||
* (non-proxied) function that has the same global as the current
|
||||
* script. To make the code simpler, we:
|
||||
* 1. test the stronger property that the callee's parent is
|
||||
* equal to the global of the current script, and
|
||||
* 2. bake in the global of the current script, which is why
|
||||
* this optimized path requires compile-and-go.
|
||||
*/
|
||||
|
||||
/* If the callee is not an object, jump to the inline fast path. */
|
||||
MaybeRegisterID typeReg = frame.maybePinType(fval);
|
||||
RegisterID objReg = frame.copyDataIntoReg(fval);
|
||||
|
||||
MaybeJump isNotObj;
|
||||
if (!fval->isType(JSVAL_TYPE_OBJECT)) {
|
||||
isNotObj = frame.testObject(Assembler::NotEqual, fval);
|
||||
frame.maybeUnpinReg(typeReg);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the callee is not a function, jump to OOL slow path.
|
||||
*/
|
||||
Jump notFunction = masm.testFunction(Assembler::NotEqual, objReg);
|
||||
stubcc.linkExit(notFunction, Uses(1));
|
||||
|
||||
/*
|
||||
* If the callee's parent is not equal to the global, jump to
|
||||
* OOL slow path.
|
||||
*/
|
||||
masm.loadPtr(Address(objReg, offsetof(JSObject, parent)), objReg);
|
||||
Jump globalMismatch = masm.branchPtr(Assembler::NotEqual, objReg, ImmPtr(globalObj));
|
||||
stubcc.linkExit(globalMismatch, Uses(1));
|
||||
frame.freeReg(objReg);
|
||||
|
||||
/* OOL stub call path. */
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::PushImplicitThisForGlobal);
|
||||
|
||||
/* Fast path. */
|
||||
if (isNotObj.isSet())
|
||||
isNotObj.getJump().linkTo(masm.label(), &masm);
|
||||
frame.pushUntypedValue(UndefinedValue());
|
||||
|
||||
stubcc.rejoin(Changes(1));
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::jsop_setgname_slow(JSAtom *atom, bool usePropertyCache)
|
||||
{
|
||||
|
@ -446,6 +446,7 @@ class Compiler : public BaseCompiler
|
||||
void jsop_eleminc(JSOp op, VoidStub);
|
||||
void jsop_getgname(uint32 index);
|
||||
void jsop_getgname_slow(uint32 index);
|
||||
void jsop_callgname_epilogue();
|
||||
void jsop_setgname(JSAtom *atom, bool usePropertyCache);
|
||||
void jsop_setgname_slow(JSAtom *atom, bool usePropertyCache);
|
||||
void jsop_bindgname();
|
||||
|
@ -375,6 +375,26 @@ FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
|
||||
regstate[payload].associate(fe, RematInfo::DATA);
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::pushUntypedValue(Value &v)
|
||||
{
|
||||
FrameEntry *fe = rawPush();
|
||||
|
||||
fe->clear();
|
||||
|
||||
masm.storeValue(v, addressOf(fe));
|
||||
|
||||
/* The forceful type sync will assert otherwise. */
|
||||
#ifdef DEBUG
|
||||
fe->type.unsync();
|
||||
#endif
|
||||
fe->type.setMemory();
|
||||
fe->data.unsync();
|
||||
fe->data.setMemory();
|
||||
fe->setNotCopied();
|
||||
fe->setCopyOf(NULL);
|
||||
}
|
||||
|
||||
inline JSC::MacroAssembler::RegisterID
|
||||
FrameState::tempRegForType(FrameEntry *fe, RegisterID fallback)
|
||||
{
|
||||
|
@ -288,6 +288,13 @@ class FrameState
|
||||
*/
|
||||
inline void pushUntypedPayload(JSValueType type, RegisterID payload);
|
||||
|
||||
/*
|
||||
* Pushes a value onto the operation stack. This must be used when the
|
||||
* value is known, but its type cannot be propagated because it is not
|
||||
* known to be correct at a slow-path merge point.
|
||||
*/
|
||||
inline void pushUntypedValue(Value &value);
|
||||
|
||||
/*
|
||||
* Pushes a number onto the operation stack.
|
||||
*
|
||||
|
@ -319,6 +319,16 @@ stubs::SetGlobalName(VMFrame &f, JSAtom *atom)
|
||||
template void JS_FASTCALL stubs::SetGlobalName<true>(VMFrame &f, JSAtom *atom);
|
||||
template void JS_FASTCALL stubs::SetGlobalName<false>(VMFrame &f, JSAtom *atom);
|
||||
|
||||
static inline void
|
||||
PushImplicitThis(VMFrame &f, JSObject *obj, Value &rval)
|
||||
{
|
||||
Value thisv;
|
||||
|
||||
if (!ComputeImplicitThis(f.cx, obj, rval, &thisv))
|
||||
return;
|
||||
*f.regs.sp++ = thisv;
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
NameOp(VMFrame &f, JSObject *obj, bool callname = false)
|
||||
{
|
||||
@ -377,13 +387,9 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
|
||||
|
||||
*f.regs.sp++ = rval;
|
||||
|
||||
if (callname) {
|
||||
Value thisv;
|
||||
if (callname)
|
||||
PushImplicitThis(f, obj, rval);
|
||||
|
||||
if (!ComputeImplicitThis(cx, obj, rval, &thisv))
|
||||
return NULL;
|
||||
*f.regs.sp++ = thisv;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -579,6 +585,17 @@ stubs::CallName(VMFrame &f)
|
||||
THROW();
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the implicit this value, with the assumption that the callee
|
||||
* (which is on top of the stack) was read as a property from the
|
||||
* global object.
|
||||
*/
|
||||
void JS_FASTCALL
|
||||
stubs::PushImplicitThisForGlobal(VMFrame &f)
|
||||
{
|
||||
return PushImplicitThis(f, f.fp()->scopeChain().getGlobal(), f.regs.sp[-1]);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::BitOr(VMFrame &f)
|
||||
{
|
||||
|
@ -136,6 +136,7 @@ void JS_FASTCALL CallElem(VMFrame &f);
|
||||
template<JSBool strict> void JS_FASTCALL SetElem(VMFrame &f);
|
||||
void JS_FASTCALL Length(VMFrame &f);
|
||||
void JS_FASTCALL CallName(VMFrame &f);
|
||||
void JS_FASTCALL PushImplicitThisForGlobal(VMFrame &f);
|
||||
void JS_FASTCALL GetUpvar(VMFrame &f, uint32 index);
|
||||
void JS_FASTCALL GetGlobalName(VMFrame &f);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user