зеркало из https://github.com/mozilla/gecko-dev.git
[INFER] Reapply f1c585415dd4 7c89b0ff453d 19794de530f1 (bug 686000).
This commit is contained in:
Родитель
bdae2afd0e
Коммит
e7ad41c28f
|
@ -0,0 +1,13 @@
|
|||
|
||||
// TI does not account for GETELEM accessing strings, so the GETELEM PIC must
|
||||
// update type constraints according to generated stubs.
|
||||
function foo(a, b) {
|
||||
for (var j = 0; j < 5; j++)
|
||||
a[b[j]] + " what";
|
||||
}
|
||||
var a = {a:"zero", b:"one", c:"two", d:"three", e:"four"};
|
||||
var b = ["a", "b", "c", "d", "e"];
|
||||
foo(a, b);
|
||||
foo(a, b);
|
||||
a.e = 4;
|
||||
foo(a, b);
|
|
@ -145,6 +145,7 @@ class Bytecode
|
|||
* hints about the script for use during compilation.
|
||||
*/
|
||||
bool arrayWriteHole: 1; /* SETELEM which has written to an array hole. */
|
||||
bool getStringElement:1; /* GETELEM which has accessed string properties. */
|
||||
bool accessGetter: 1; /* Property read on a shape with a getter hook. */
|
||||
|
||||
/* Stack depth before this opcode. */
|
||||
|
|
|
@ -3903,13 +3903,13 @@ BEGIN_CASE(JSOP_GETELEM)
|
|||
}
|
||||
}
|
||||
|
||||
if (JSID_IS_STRING(id) && script->hasAnalysis() && !regs.fp()->hasImacropc())
|
||||
script->analysis()->getCode(regs.pc).getStringElement = true;
|
||||
|
||||
if (!obj->getProperty(cx, id, &rval))
|
||||
goto error;
|
||||
copyFrom = &rval;
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
TypeScript::MonitorUnknown(cx, script, regs.pc);
|
||||
|
||||
end_getelem:
|
||||
regs.sp--;
|
||||
regs.sp[-1] = *copyFrom;
|
||||
|
@ -3947,8 +3947,6 @@ BEGIN_CASE(JSOP_CALLELEM)
|
|||
regs.sp[-1] = thisv;
|
||||
}
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
TypeScript::MonitorUnknown(cx, script, regs.pc);
|
||||
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
|
||||
}
|
||||
END_CASE(JSOP_CALLELEM)
|
||||
|
@ -3975,7 +3973,7 @@ BEGIN_CASE(JSOP_SETELEM)
|
|||
obj->setDenseArrayElementWithType(cx, i, regs.sp[-1]);
|
||||
goto end_setelem;
|
||||
} else {
|
||||
if (script->hasAnalysis())
|
||||
if (script->hasAnalysis() && !regs.fp()->hasImacropc())
|
||||
script->analysis()->getCode(regs.pc).arrayWriteHole = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4199,6 +4199,7 @@ mjit::Compiler::jsop_getprop_slow(JSAtom *atom, bool usePropCache)
|
|||
prepareStubCall(Uses(1));
|
||||
if (usePropCache) {
|
||||
INLINE_STUBCALL(stubs::GetProp, rejoin);
|
||||
testPushedType(rejoin, -1, /* ool = */ false);
|
||||
} else {
|
||||
masm.move(ImmPtr(atom), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::GetPropNoCache, rejoin);
|
||||
|
@ -4214,6 +4215,7 @@ mjit::Compiler::jsop_callprop_slow(JSAtom *atom)
|
|||
prepareStubCall(Uses(1));
|
||||
masm.move(ImmPtr(atom), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -1, /* ool = */ false);
|
||||
frame.pop();
|
||||
pushSyncedEntry(0);
|
||||
pushSyncedEntry(1);
|
||||
|
@ -4309,6 +4311,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
|
|||
stubcc.linkExit(notObject, Uses(1));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetProp, rejoin);
|
||||
if (rejoin == REJOIN_GETTER)
|
||||
testPushedType(rejoin, -1);
|
||||
}
|
||||
RegisterID reg = frame.tempRegForData(top);
|
||||
frame.pop();
|
||||
|
@ -4329,6 +4333,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
|
|||
stubcc.linkExit(notObject, Uses(1));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetProp, rejoin);
|
||||
if (rejoin == REJOIN_GETTER)
|
||||
testPushedType(rejoin, -1);
|
||||
}
|
||||
RegisterID reg = frame.copyDataIntoReg(top);
|
||||
frame.pop();
|
||||
|
@ -4391,6 +4397,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
|
|||
stubcc.linkExit(notObject, Uses(1));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetProp, rejoin);
|
||||
if (rejoin == REJOIN_GETTER)
|
||||
testPushedType(rejoin, -1);
|
||||
}
|
||||
RegisterID reg = frame.tempRegForData(top);
|
||||
frame.pop();
|
||||
|
@ -4454,7 +4462,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
|
|||
* type barrier if inference is enabled (known property types do not
|
||||
* reflect properties with getter hooks).
|
||||
*/
|
||||
pic.canCallHook = usePropCache && JSOp(*PC) == JSOP_GETPROP && analysis->getCode(PC).accessGetter;
|
||||
pic.canCallHook = pic.forcedTypeBarrier =
|
||||
usePropCache && JSOp(*PC) == JSOP_GETPROP && analysis->getCode(PC).accessGetter;
|
||||
if (pic.canCallHook)
|
||||
frame.syncAndKillEverything();
|
||||
|
||||
|
@ -4478,6 +4487,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
|
|||
passICAddress(&pic);
|
||||
pic.slowPathCall = OOL_STUBCALL(usePropCache ? ic::GetProp : ic::GetPropNoCache, rejoin);
|
||||
CHECK_OOL_SPACE();
|
||||
if (rejoin == REJOIN_GETTER)
|
||||
testPushedType(rejoin, -1);
|
||||
|
||||
/* Load the base slot address. */
|
||||
Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, offsetof(JSObject, slots)),
|
||||
|
@ -4561,7 +4572,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
|
|||
pic.shapeReg = shapeReg;
|
||||
pic.atom = atom;
|
||||
|
||||
pic.canCallHook = analysis->getCode(PC).accessGetter;
|
||||
pic.canCallHook = pic.forcedTypeBarrier = analysis->getCode(PC).accessGetter;
|
||||
if (pic.canCallHook)
|
||||
frame.syncAndKillEverything();
|
||||
|
||||
|
@ -4599,6 +4610,8 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
|
|||
pic.slowPathCall = OOL_STUBCALL(ic::CallProp, REJOIN_FALLTHROUGH);
|
||||
CHECK_OOL_SPACE();
|
||||
|
||||
testPushedType(REJOIN_FALLTHROUGH, -1);
|
||||
|
||||
/* Load the base slot address. */
|
||||
Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, offsetof(JSObject, slots)),
|
||||
objReg);
|
||||
|
@ -4731,7 +4744,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
|
|||
objReg = frame.copyDataIntoReg(top);
|
||||
}
|
||||
|
||||
pic.canCallHook = analysis->getCode(PC).accessGetter;
|
||||
pic.canCallHook = pic.forcedTypeBarrier = analysis->getCode(PC).accessGetter;
|
||||
if (pic.canCallHook)
|
||||
frame.syncAndKillEverything();
|
||||
|
||||
|
@ -4753,6 +4766,8 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
|
|||
pic.slowPathCall = OOL_STUBCALL(ic::CallProp, REJOIN_FALLTHROUGH);
|
||||
CHECK_OOL_SPACE();
|
||||
|
||||
testPushedType(REJOIN_FALLTHROUGH, -1);
|
||||
|
||||
/* Load the base slot address. */
|
||||
Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, offsetof(JSObject, slots)),
|
||||
objReg);
|
||||
|
@ -5044,6 +5059,7 @@ mjit::Compiler::jsop_callprop_dispatch(JSAtom *atom)
|
|||
stubcc.leave();
|
||||
stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
|
||||
OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -1);
|
||||
|
||||
frame.dup();
|
||||
// THIS THIS
|
||||
|
@ -5074,6 +5090,7 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
|
|||
stubcc.leave();
|
||||
stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
|
||||
OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -1);
|
||||
}
|
||||
|
||||
// THIS
|
||||
|
@ -5344,6 +5361,7 @@ mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
|
|||
passICAddress(&pic);
|
||||
pic.slowPathCall = OOL_STUBCALL(isCall ? ic::CallName : ic::Name, rejoin);
|
||||
CHECK_OOL_SPACE();
|
||||
testPushedType(rejoin, 0);
|
||||
}
|
||||
pic.fastPathRejoin = masm.label();
|
||||
|
||||
|
@ -5431,6 +5449,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
|
|||
passICAddress(&pic);
|
||||
pic.slowPathCall = OOL_STUBCALL(ic::XName, REJOIN_GETTER);
|
||||
CHECK_OOL_SPACE();
|
||||
testPushedType(REJOIN_GETTER, -1);
|
||||
}
|
||||
|
||||
pic.fastPathRejoin = masm.label();
|
||||
|
@ -5527,7 +5546,8 @@ void
|
|||
mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
|
||||
{
|
||||
prepareStubCall(Uses(0));
|
||||
INLINE_STUBCALL(isCall ? stubs::CallName : stubs::Name, REJOIN_FALLTHROUGH);
|
||||
INLINE_STUBCALL(isCall ? stubs::CallName : stubs::Name, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, 0, /* ool = */ false);
|
||||
frame.pushSynced(type);
|
||||
if (isCall)
|
||||
frame.pushSynced(JSVAL_TYPE_UNKNOWN);
|
||||
|
@ -5903,6 +5923,7 @@ mjit::Compiler::jsop_getgname_slow(uint32 index)
|
|||
{
|
||||
prepareStubCall(Uses(0));
|
||||
INLINE_STUBCALL(stubs::GetGlobalName, REJOIN_GETTER);
|
||||
testPushedType(REJOIN_GETTER, 0, /* ool = */ false);
|
||||
frame.pushSynced(JSVAL_TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
|
@ -6016,6 +6037,10 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
|||
passMICAddress(ic);
|
||||
ic.slowPathCall = OOL_STUBCALL(ic::GetGlobalName, REJOIN_GETTER);
|
||||
|
||||
CHECK_IC_SPACE();
|
||||
|
||||
testPushedType(REJOIN_GETTER, 0);
|
||||
|
||||
/* Garbage value. */
|
||||
uint32 slot = 1 << 24;
|
||||
|
||||
|
@ -6029,8 +6054,6 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
|||
|
||||
ic.load = masm.loadValueWithAddressOffsetPatch(address, treg, dreg);
|
||||
|
||||
CHECK_IC_SPACE();
|
||||
|
||||
frame.pushRegs(treg, dreg, type);
|
||||
|
||||
/*
|
||||
|
@ -6289,6 +6312,7 @@ mjit::Compiler::jsop_getelem_slow()
|
|||
{
|
||||
prepareStubCall(Uses(2));
|
||||
INLINE_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2, /* ool = */ false);
|
||||
frame.popn(2);
|
||||
pushSyncedEntry(0);
|
||||
}
|
||||
|
@ -7033,6 +7057,7 @@ mjit::Compiler::jsop_callelem_slow()
|
|||
{
|
||||
prepareStubCall(Uses(2));
|
||||
INLINE_STUBCALL(stubs::CallElem, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2, /* ool = */ false);
|
||||
frame.popn(2);
|
||||
pushSyncedEntry(0);
|
||||
pushSyncedEntry(1);
|
||||
|
@ -7535,3 +7560,38 @@ mjit::Compiler::finishBarrier(const BarrierState &barrier, RejoinState rejoin, u
|
|||
OOL_STUBCALL(stubs::TypeBarrierHelper, rejoin);
|
||||
stubcc.rejoin(Changes(0));
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::testPushedType(RejoinState rejoin, int which, bool ool)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !(js_CodeSpec[*PC].format & JOF_TYPESET))
|
||||
return;
|
||||
|
||||
types::TypeSet *types = analysis->bytecodeTypes(PC);
|
||||
if (types->unknown())
|
||||
return;
|
||||
|
||||
Assembler &masm = ool ? stubcc.masm : this->masm;
|
||||
|
||||
JS_ASSERT(which <= 0);
|
||||
Address address = (which == 0) ? frame.addressOfTop() : frame.addressOf(frame.peek(which));
|
||||
|
||||
Vector<Jump> mismatches(cx);
|
||||
if (!masm.generateTypeCheck(cx, address, types, &mismatches)) {
|
||||
oomInVector = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Jump j = masm.jump();
|
||||
|
||||
for (unsigned i = 0; i < mismatches.length(); i++)
|
||||
mismatches[i].linkTo(masm.label(), &masm);
|
||||
|
||||
masm.move(Imm32(which), Registers::ArgReg1);
|
||||
if (ool)
|
||||
OOL_STUBCALL(stubs::StubTypeHelper, rejoin);
|
||||
else
|
||||
INLINE_STUBCALL(stubs::StubTypeHelper, rejoin);
|
||||
|
||||
j.linkTo(masm.label(), &masm);
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ class Compiler : public BaseCompiler
|
|||
};
|
||||
|
||||
struct BaseICInfo {
|
||||
BaseICInfo(JSOp op) : op(op), canCallHook(false)
|
||||
BaseICInfo(JSOp op) : op(op), canCallHook(false), forcedTypeBarrier(false)
|
||||
{ }
|
||||
Label fastPathStart;
|
||||
Label fastPathRejoin;
|
||||
|
@ -193,6 +193,7 @@ class Compiler : public BaseCompiler
|
|||
DataLabelPtr paramAddr;
|
||||
JSOp op;
|
||||
bool canCallHook;
|
||||
bool forcedTypeBarrier;
|
||||
|
||||
void copyTo(ic::BaseIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) {
|
||||
to.fastPathStart = full.locationOf(fastPathStart);
|
||||
|
@ -200,6 +201,7 @@ class Compiler : public BaseCompiler
|
|||
to.slowPathStart = stub.locationOf(slowPathStart);
|
||||
to.slowPathCall = stub.locationOf(slowPathCall);
|
||||
to.canCallHook = canCallHook;
|
||||
to.forcedTypeBarrier = forcedTypeBarrier;
|
||||
to.op = op;
|
||||
JS_ASSERT(to.op == op);
|
||||
}
|
||||
|
@ -571,6 +573,8 @@ class Compiler : public BaseCompiler
|
|||
bool force = false);
|
||||
void finishBarrier(const BarrierState &barrier, RejoinState rejoin, uint32 which);
|
||||
|
||||
void testPushedType(RejoinState rejoin, int which, bool ool = true);
|
||||
|
||||
/* Non-emitting helpers. */
|
||||
void pushSyncedEntry(uint32 pushed);
|
||||
uint32 fullAtomIndex(jsbytecode *pc);
|
||||
|
|
|
@ -1746,6 +1746,7 @@ mjit::Compiler::jsop_getelem_dense(bool isPacked)
|
|||
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2);
|
||||
|
||||
frame.popn(2);
|
||||
|
||||
|
@ -1837,6 +1838,7 @@ mjit::Compiler::jsop_getelem_args()
|
|||
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2);
|
||||
|
||||
frame.popn(2);
|
||||
frame.pushRegs(typeReg, dataReg, knownPushedType(0));
|
||||
|
@ -1968,6 +1970,7 @@ mjit::Compiler::jsop_getelem_typed(int atype)
|
|||
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2);
|
||||
|
||||
frame.popn(2);
|
||||
|
||||
|
@ -2149,13 +2152,17 @@ mjit::Compiler::jsop_getelem(bool isCall)
|
|||
ic.slowPathCall = OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
|
||||
#endif
|
||||
|
||||
testPushedType(REJOIN_FALLTHROUGH, -2);
|
||||
|
||||
ic.fastPathRejoin = masm.label();
|
||||
ic.forcedTypeBarrier = analysis->getCode(PC).getStringElement;
|
||||
|
||||
CHECK_IC_SPACE();
|
||||
|
||||
frame.popn(2);
|
||||
frame.pushRegs(ic.typeReg, ic.objReg, knownPushedType(0));
|
||||
BarrierState barrier = testBarrier(ic.typeReg, ic.objReg, false);
|
||||
BarrierState barrier = testBarrier(ic.typeReg, ic.objReg, false, false,
|
||||
/* force = */ ic.forcedTypeBarrier);
|
||||
if (isCall)
|
||||
frame.pushSynced(knownPushedType(1));
|
||||
|
||||
|
|
|
@ -1360,10 +1360,6 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
|||
/* Release this reference on the orphaned native stub. */
|
||||
RemoveOrphanedNative(cx, fp);
|
||||
|
||||
/*
|
||||
* Note: there is no need to monitor the result of the native, the stub
|
||||
* will always do a type check before finishing.
|
||||
*/
|
||||
f.regs.pc = nextpc;
|
||||
break;
|
||||
}
|
||||
|
@ -1582,6 +1578,16 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
|||
nextDepth = analysis->getCode(f.regs.pc).stackDepth;
|
||||
f.regs.sp = fp->base() + nextDepth;
|
||||
|
||||
/*
|
||||
* Monitor the result of the previous op when finishing a JOF_TYPESET op.
|
||||
* The result may not have been marked if we bailed out while inside a stub
|
||||
* for the op.
|
||||
*/
|
||||
if (f.regs.pc == nextpc && (js_CodeSpec[op].format & JOF_TYPESET)) {
|
||||
int which = (js_CodeSpec[op].format & JOF_CALLOP) ? -2 : -1; /* Yuck. */
|
||||
types::TypeScript::Monitor(cx, script, pc, f.regs.sp[which]);
|
||||
}
|
||||
|
||||
/* Mark the entry frame as unfinished, and update the regs to resume at. */
|
||||
JaegerStatus status = skipTrap ? Jaeger_UnfinishedAtTrap : Jaeger_Unfinished;
|
||||
cx->compartment->jaegerCompartment()->setLastUnfinished(status);
|
||||
|
|
|
@ -1940,11 +1940,9 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
|||
THROW();
|
||||
JSString *str = f.regs.sp[-1].toString();
|
||||
f.regs.sp[-1].setInt32(str->length());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
} else if (f.regs.sp[-1].isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
f.regs.sp[-1].setInt32(f.regs.fp()->numActualArgs());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
} else if (!f.regs.sp[-1].isPrimitive()) {
|
||||
JSObject *obj = &f.regs.sp[-1].toObject();
|
||||
|
@ -1969,15 +1967,12 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
|||
JSString *str = obj->getPrimitiveThis().toString();
|
||||
f.regs.sp[-1].setInt32(str->length());
|
||||
}
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
atom = f.cx->runtime->atomState.lengthAtom;
|
||||
}
|
||||
|
||||
bool usePropCache = pic->usePropCache;
|
||||
|
||||
/*
|
||||
* ValueToObject can trigger recompilations if it lazily initializes any
|
||||
* of the primitive classes (Boolean, Number, String). :XXX: if these
|
||||
|
@ -2004,16 +1999,6 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
|||
if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v))
|
||||
THROW();
|
||||
|
||||
/*
|
||||
* Ignore undefined reads for the 'prototype' property in constructors,
|
||||
* which will be at the start of the script and are never holes due to fun_resolve.
|
||||
* Any undefined value was explicitly stored here, and is known by inference.
|
||||
* :FIXME: looking under the usePropCache abstraction, which is only unset for
|
||||
* reads of the prototype.
|
||||
*/
|
||||
if (usePropCache)
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), v);
|
||||
|
||||
f.regs.sp[-1] = v;
|
||||
}
|
||||
|
||||
|
@ -2183,8 +2168,6 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
|
|||
}
|
||||
#endif
|
||||
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), regs.sp[-2]);
|
||||
|
||||
if (monitor.recompiled())
|
||||
return;
|
||||
|
||||
|
@ -2234,8 +2217,6 @@ ic::XName(VMFrame &f, ic::PICInfo *pic)
|
|||
if (!cc.retrieve(&rval, NULL, PICInfo::XNAME))
|
||||
THROW();
|
||||
f.regs.sp[-1] = rval;
|
||||
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), rval);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
|
@ -2253,8 +2234,6 @@ ic::Name(VMFrame &f, ic::PICInfo *pic)
|
|||
if (!cc.retrieve(&rval, NULL, PICInfo::NAME))
|
||||
THROW();
|
||||
f.regs.sp[0] = rval;
|
||||
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), rval);
|
||||
}
|
||||
|
||||
static void JS_FASTCALL
|
||||
|
@ -2280,8 +2259,6 @@ ic::CallName(VMFrame &f, ic::PICInfo *pic)
|
|||
|
||||
f.regs.sp[0] = rval;
|
||||
f.regs.sp[1] = thisval;
|
||||
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), rval);
|
||||
}
|
||||
|
||||
static void JS_FASTCALL
|
||||
|
@ -2458,6 +2435,12 @@ GetElementIC::attachGetProp(VMFrame &f, JSContext *cx, JSObject *obj, const Valu
|
|||
if (status != Lookup_Cacheable)
|
||||
return status;
|
||||
|
||||
// With TI enabled, string property stubs can only be added to an opcode if
|
||||
// the value read will go through a type barrier afterwards. TI only
|
||||
// accounts for integer-valued properties accessed by GETELEM/CALLELEM.
|
||||
if (cx->typeInferenceEnabled() && !forcedTypeBarrier)
|
||||
return disable(cx, "string element access may not have type barrier");
|
||||
|
||||
Assembler masm;
|
||||
|
||||
// Guard on the string's type and identity.
|
||||
|
@ -2921,9 +2904,6 @@ ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
|
|||
// If the result can be cached, the value was already retrieved.
|
||||
JS_ASSERT(!f.regs.sp[-2].isMagic());
|
||||
f.regs.sp[-1].setObject(*thisObj);
|
||||
if (!JSID_IS_INT(id))
|
||||
types::TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2943,9 +2923,6 @@ ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
|
|||
{
|
||||
f.regs.sp[-1] = thisv;
|
||||
}
|
||||
if (!JSID_IS_INT(id))
|
||||
types::TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
|
@ -2987,18 +2964,12 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic)
|
|||
|
||||
// If the result can be cached, the value was already retrieved.
|
||||
JS_ASSERT(!f.regs.sp[-2].isMagic());
|
||||
if (!JSID_IS_INT(id))
|
||||
types::TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!obj->getProperty(cx, id, &f.regs.sp[-2]))
|
||||
THROW();
|
||||
if (!JSID_IS_INT(id))
|
||||
types::TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
|
||||
types::TypeScript::Monitor(f.cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
#define APPLY_STRICTNESS(f, s) \
|
||||
|
|
|
@ -96,6 +96,9 @@ struct BaseIC : public MacroAssemblerTypedefs {
|
|||
// Whether getter/setter hooks can be called from IC stubs.
|
||||
bool canCallHook : 1;
|
||||
|
||||
// Whether a type barrier is in place for the result of the op.
|
||||
bool forcedTypeBarrier : 1;
|
||||
|
||||
// Number of stubs generated.
|
||||
uint32 stubsGenerated : 5;
|
||||
|
||||
|
@ -105,6 +108,7 @@ struct BaseIC : public MacroAssemblerTypedefs {
|
|||
void reset() {
|
||||
hit = false;
|
||||
slowCallPatched = false;
|
||||
forcedTypeBarrier = false;
|
||||
stubsGenerated = 0;
|
||||
secondShapeGuard = 0;
|
||||
}
|
||||
|
|
|
@ -375,7 +375,6 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
|
|||
if (op2 == JSOP_TYPEOF) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), f.regs.sp[-1]);
|
||||
return obj;
|
||||
}
|
||||
ReportAtomNotDefined(cx, atom);
|
||||
|
@ -402,8 +401,6 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
|
|||
AddTypePropertyId(cx, obj, id, Type::UndefinedType());
|
||||
}
|
||||
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), rval);
|
||||
|
||||
*f.regs.sp++ = rval;
|
||||
|
||||
if (callname)
|
||||
|
@ -443,7 +440,6 @@ stubs::GetElem(VMFrame &f)
|
|||
if (!str)
|
||||
THROW();
|
||||
f.regs.sp[-2].setString(str);
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +447,6 @@ stubs::GetElem(VMFrame &f)
|
|||
if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
|
||||
regs.sp[-2] = regs.fp()->canonicalActualArg(rref.toInt32());
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
MarkArgumentsCreated(cx, f.script());
|
||||
|
@ -508,12 +503,8 @@ stubs::GetElem(VMFrame &f)
|
|||
THROW();
|
||||
copyFrom = &rval;
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
TypeScript::MonitorUnknown(cx, f.script(), f.pc());
|
||||
|
||||
end_getelem:
|
||||
f.regs.sp[-2] = *copyFrom;
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -559,9 +550,6 @@ stubs::CallElem(VMFrame &f)
|
|||
{
|
||||
regs.sp[-1] = thisv;
|
||||
}
|
||||
if (!JSID_IS_INT(id))
|
||||
TypeScript::MonitorUnknown(cx, f.script(), f.pc());
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), regs.sp[-2]);
|
||||
}
|
||||
|
||||
template<JSBool strict>
|
||||
|
@ -1573,7 +1561,6 @@ InlineGetProp(VMFrame &f)
|
|||
if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
JS_ASSERT(js_GetOpcode(cx, f.script(), f.pc()) == JSOP_LENGTH);
|
||||
regs.sp[-1] = Int32Value(regs.fp()->numActualArgs());
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), regs.sp[-1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1622,8 +1609,6 @@ InlineGetProp(VMFrame &f)
|
|||
}
|
||||
} while(0);
|
||||
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), rval);
|
||||
|
||||
regs.sp[-1] = rval;
|
||||
return true;
|
||||
}
|
||||
|
@ -1742,7 +1727,6 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
|
|||
THROW();
|
||||
}
|
||||
#endif
|
||||
TypeScript::Monitor(cx, f.script(), f.pc(), rval);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
|
@ -2394,6 +2378,19 @@ stubs::TypeBarrierHelper(VMFrame &f, uint32 which)
|
|||
TypeScript::Monitor(f.cx, f.script(), f.pc(), result);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::StubTypeHelper(VMFrame &f, int32 which)
|
||||
{
|
||||
const Value &result = f.regs.sp[which];
|
||||
|
||||
if (f.script()->hasAnalysis() && f.script()->analysis()->ranInference()) {
|
||||
AutoEnterTypeInference enter(f.cx);
|
||||
f.script()->analysis()->breakTypeBarriers(f.cx, f.pc() - f.script()->code, false);
|
||||
}
|
||||
|
||||
TypeScript::Monitor(f.cx, f.script(), f.pc(), result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variant of TypeBarrierHelper for checking types after making a native call.
|
||||
* The stack is already correct, and no fixup should be performed.
|
||||
|
@ -2411,25 +2408,6 @@ stubs::NegZeroHelper(VMFrame &f)
|
|||
TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::CallPropSwap(VMFrame &f)
|
||||
{
|
||||
/*
|
||||
* CALLPROP operations on strings are implemented in terms of GETPROP.
|
||||
* If we rejoin from such a GETPROP, we come here at the end of the
|
||||
* CALLPROP to fix up the stack. Right now the stack looks like:
|
||||
*
|
||||
* STRING PROP
|
||||
*
|
||||
* We need it to be:
|
||||
*
|
||||
* PROP STRING
|
||||
*/
|
||||
Value v = f.regs.sp[-1];
|
||||
f.regs.sp[-1] = f.regs.sp[-2];
|
||||
f.regs.sp[-2] = v;
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::CheckArgumentTypes(VMFrame &f)
|
||||
{
|
||||
|
|
|
@ -210,7 +210,8 @@ void JS_FASTCALL TypeBarrierHelper(VMFrame &f, uint32 which);
|
|||
void JS_FASTCALL TypeBarrierReturn(VMFrame &f, Value *vp);
|
||||
void JS_FASTCALL NegZeroHelper(VMFrame &f);
|
||||
|
||||
void JS_FASTCALL CallPropSwap(VMFrame &f);
|
||||
void JS_FASTCALL StubTypeHelper(VMFrame &f, int32 which);
|
||||
|
||||
void JS_FASTCALL CheckArgumentTypes(VMFrame &f);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
Загрузка…
Ссылка в новой задаче