Bug 771130 part 3 - Invalidate the script if GuardShape fails. r=pierron

This commit is contained in:
Jan de Mooij 2012-07-19 11:36:56 +02:00
parent b9a67416a1
commit e4ad550d89
13 changed files with 82 additions and 25 deletions

View File

@ -335,6 +335,8 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it)
return BAILOUT_RETURN_RECOMPILE_CHECK;
case Bailout_BoundsCheck:
return BAILOUT_RETURN_BOUNDS_CHECK;
case Bailout_Invalidate:
return BAILOUT_RETURN_INVALIDATE;
}
JS_NOT_REACHED("bad bailout kind");
@ -549,19 +551,28 @@ ion::BoundsCheckFailure()
script->failedBoundsCheck = true;
// Invalidate the script to force a recompile.
Vector<types::CompilerOutput> scripts(cx);
types::CompilerOutput co(script);
if (!scripts.append(co))
return BAILOUT_RETURN_FATAL_ERROR;
IonSpew(IonSpew_Invalidate, "Invalidating due to bounds check failure");
Invalidate(cx->runtime->defaultFreeOp(), scripts);
return Invalidate(cx, script);
}
return true;
}
uint32
ion::ForceInvalidation()
{
JSContext *cx = GetIonContext()->cx;
JSScript *script = GetBailedJSScript(cx);
JS_ASSERT(script->hasIonScript());
JS_ASSERT(!script->ion->invalidated());
IonSpew(IonSpew_Invalidate, "Forced invalidation bailout");
return Invalidate(cx, script);
}
uint32
ion::ThunkToInterpreter(Value *vp)
{

View File

@ -140,6 +140,7 @@ static const uint32 BAILOUT_RETURN_TYPE_BARRIER = 3;
static const uint32 BAILOUT_RETURN_MONITOR = 4;
static const uint32 BAILOUT_RETURN_RECOMPILE_CHECK = 5;
static const uint32 BAILOUT_RETURN_BOUNDS_CHECK = 6;
static const uint32 BAILOUT_RETURN_INVALIDATE = 7;
// Attached to the compartment for easy passing through from ::Bailout to
// ::ThunkToInterpreter.
@ -253,6 +254,8 @@ uint32 RecompileForInlining();
uint32 BoundsCheckFailure();
uint32 ForceInvalidation();
} // namespace ion
} // namespace js

View File

@ -84,7 +84,10 @@ enum BailoutKind
Bailout_RecompileCheck,
// A bailout triggered by a bounds-check failure.
Bailout_BoundsCheck
Bailout_BoundsCheck,
// Like Bailout_Normal, but invalidate the current IonScript.
Bailout_Invalidate
};
#ifdef DEBUG

View File

@ -347,7 +347,7 @@ LIRGeneratorARM::visitGuardShape(MGuardShape *ins)
{
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()), tempObj);
return assignSnapshot(guard) && add(guard, ins);
return assignSnapshot(guard, Bailout_Invalidate) && add(guard, ins);
}
bool

View File

@ -252,6 +252,7 @@ GenerateBailoutTail(MacroAssembler &masm)
Label exception;
Label osr;
Label recompile;
Label boundsCheck;
// The return value from Bailout is tagged as:
// - 0x0: done (thunk to interpreter)
@ -261,17 +262,32 @@ GenerateBailoutTail(MacroAssembler &masm)
// - 0x4: monitor types
// - 0x5: recompile to inline calls
// - 0x6: bounds check failure
// - 0x7: force invalidation
masm.ma_cmp(r0, Imm32(BAILOUT_RETURN_FATAL_ERROR));
masm.ma_b(&interpret, Assembler::LessThan);
masm.ma_b(&exception, Assembler::Equal);
masm.ma_cmp(r0, Imm32(BAILOUT_RETURN_RECOMPILE_CHECK));
masm.ma_b(&reflow, Assembler::LessThan);
masm.ma_b(&recompile, Assembler::Equal);
masm.ma_cmp(r0, Imm32(BAILOUT_RETURN_INVALIDATE));
masm.ma_b(&boundsCheck, Assembler::LessThan);
// Force invalidation.
{
masm.setupAlignedABICall(0);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForceInvalidation));
masm.ma_cmp(r0, Imm32(0));
masm.ma_b(&exception, Assembler::Equal);
masm.ma_b(&interpret);
}
// Bounds check failure.
masm.bind(&boundscheck);
{
masm.setupAlignedABICall(0);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BoundsCheckFailure));

View File

@ -94,6 +94,13 @@ LIRGeneratorX86Shared::visitInterruptCheck(MInterruptCheck *ins)
return true;
}
bool
LIRGeneratorX86Shared::visitGuardShape(MGuardShape *ins)
{
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
return assignSnapshot(guard, Bailout_Invalidate) && add(guard, ins);
}
bool
LIRGeneratorX86Shared::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
{

View File

@ -54,6 +54,7 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared
bool visitTableSwitch(MTableSwitch *tableswitch);
bool visitRecompileCheck(MRecompileCheck *ins);
bool visitInterruptCheck(MInterruptCheck *ins);
bool visitGuardShape(MGuardShape *ins);
bool lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs);
bool lowerModI(MMod *mod);
};

View File

@ -177,13 +177,6 @@ LIRGeneratorX64::lowerDivI(MDiv *div)
return assignSnapshot(lir) && defineFixed(lir, div, LAllocation(AnyRegister(rax)));
}
bool
LIRGeneratorX64::visitGuardShape(MGuardShape *ins)
{
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
return assignSnapshot(guard) && add(guard, ins);
}
bool
LIRGeneratorX64::visitStoreTypedArrayElement(MStoreTypedArrayElement *ins)
{

View File

@ -72,7 +72,6 @@ class LIRGeneratorX64 : public LIRGeneratorX86Shared
bool lowerConstantDouble(double d, MInstruction *ins);
bool lowerDivI(MDiv *div);
bool visitGuardShape(MGuardShape *ins);
public:
bool visitConstant(MConstant *ins);

View File

@ -208,6 +208,7 @@ GenerateBailoutTail(MacroAssembler &masm)
Label exception;
Label osr;
Label recompile;
Label boundscheck;
// The return value from Bailout is tagged as:
// - 0x0: done (thunk to interpreter)
@ -217,6 +218,7 @@ GenerateBailoutTail(MacroAssembler &masm)
// - 0x4: monitor types
// - 0x5: recompile to inline calls
// - 0x6: bounds check failure
// - 0x7: force invalidation
masm.cmpl(rax, Imm32(BAILOUT_RETURN_FATAL_ERROR));
masm.j(Assembler::LessThan, &interpret);
@ -226,7 +228,21 @@ GenerateBailoutTail(MacroAssembler &masm)
masm.j(Assembler::LessThan, &reflow);
masm.j(Assembler::Equal, &recompile);
masm.cmpl(eax, Imm32(BAILOUT_RETURN_INVALIDATE));
masm.j(Assembler::LessThan, &boundscheck);
// Force invalidation.
{
masm.setupUnalignedABICall(0, rdx);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForceInvalidation));
masm.testl(rax, rax);
masm.j(Assembler::Zero, &exception);
masm.jmp(&interpret);
}
// Bounds check failure.
masm.bind(&boundscheck);
{
masm.setupUnalignedABICall(0, rdx);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BoundsCheckFailure));

View File

@ -253,13 +253,6 @@ LIRGeneratorX86::lowerDivI(MDiv *div)
}
bool
LIRGeneratorX86::visitGuardShape(MGuardShape *ins)
{
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
return assignSnapshot(guard) && add(guard, ins);
}
bool
LIRGeneratorX86::visitStoreTypedArrayElement(MStoreTypedArrayElement *ins)
{

View File

@ -74,7 +74,6 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
bool lowerConstantDouble(double d, MInstruction *ins);
bool lowerDivI(MDiv *div);
bool visitGuardShape(MGuardShape *ins);
public:
bool visitConstant(MConstant *ins);

View File

@ -202,6 +202,7 @@ GenerateBailoutTail(MacroAssembler &masm)
Label exception;
Label osr;
Label recompile;
Label boundscheck;
// The return value from Bailout is tagged as:
// - 0x0: done (thunk to interpreter)
@ -211,6 +212,7 @@ GenerateBailoutTail(MacroAssembler &masm)
// - 0x4: monitor types
// - 0x5: recompile to inline calls
// - 0x6: bounds check failure
// - 0x7: force invalidation
masm.cmpl(eax, Imm32(BAILOUT_RETURN_FATAL_ERROR));
masm.j(Assembler::LessThan, &interpret);
@ -220,7 +222,21 @@ GenerateBailoutTail(MacroAssembler &masm)
masm.j(Assembler::LessThan, &reflow);
masm.j(Assembler::Equal, &recompile);
masm.cmpl(eax, Imm32(BAILOUT_RETURN_INVALIDATE));
masm.j(Assembler::LessThan, &boundscheck);
// Force invalidation.
{
masm.setupUnalignedABICall(0, edx);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForceInvalidation));
masm.testl(eax, eax);
masm.j(Assembler::Zero, &exception);
masm.jmp(&interpret);
}
// Bounds check failure.
masm.bind(&boundscheck);
{
masm.setupUnalignedABICall(0, edx);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BoundsCheckFailure));