[INFER] Reapply f1c585415dd4 7c89b0ff453d 19794de530f1 (bug 686000).

This commit is contained in:
Brian Hackett 2011-09-17 19:31:33 -07:00
Родитель bdae2afd0e
Коммит e7ad41c28f
11 изменённых файлов: 132 добавлений и 89 удалений

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

@ -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