mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Bug 1054512: IonMonkey: Run the type policy of added instructions during type analysis, r=jandem
This commit is contained in:
parent
e0c5cdb4c3
commit
d05c879c31
11
js/src/jit-test/tests/ion/bug1054512.js
Normal file
11
js/src/jit-test/tests/ion/bug1054512.js
Normal file
@ -0,0 +1,11 @@
|
||||
function f(x) {
|
||||
x((x | 0) + x);
|
||||
};
|
||||
try {
|
||||
f(1);
|
||||
} catch (e) {}
|
||||
for (var k = 0; k < 1; ++k) {
|
||||
try {
|
||||
f(Symbol());
|
||||
} catch (e) {}
|
||||
}
|
@ -3112,7 +3112,11 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
||||
: MUnaryInstruction(ins),
|
||||
mode_(mode)
|
||||
{
|
||||
JS_ASSERT(ins->type() == MIRType_Value);
|
||||
// Only allow unboxing a non MIRType_Value when input and output types
|
||||
// don't match. This is often used to force a bailout. Boxing happens
|
||||
// during type analysis.
|
||||
JS_ASSERT_IF(ins->type() != MIRType_Value, type != ins->type());
|
||||
|
||||
JS_ASSERT(type == MIRType_Boolean ||
|
||||
type == MIRType_Int32 ||
|
||||
type == MIRType_Double ||
|
||||
@ -3839,7 +3843,9 @@ class MToInt32
|
||||
|
||||
// Converts a value or typed input to a truncated int32, for use with bitwise
|
||||
// operations. This is an infallible ValueToECMAInt32.
|
||||
class MTruncateToInt32 : public MUnaryInstruction
|
||||
class MTruncateToInt32
|
||||
: public MUnaryInstruction,
|
||||
public ToInt32Policy
|
||||
{
|
||||
explicit MTruncateToInt32(MDefinition *def)
|
||||
: MUnaryInstruction(def)
|
||||
@ -3850,7 +3856,6 @@ class MTruncateToInt32 : public MUnaryInstruction
|
||||
// An object might have "valueOf", which means it is effectful.
|
||||
// ToInt32(symbol) throws.
|
||||
MOZ_ASSERT(def->type() != MIRType_Object);
|
||||
MOZ_ASSERT(def->type() != MIRType_Symbol);
|
||||
if (def->mightBeType(MIRType_Object) || def->mightBeType(MIRType_Symbol))
|
||||
setGuard();
|
||||
}
|
||||
@ -3881,6 +3886,10 @@ class MTruncateToInt32 : public MUnaryInstruction
|
||||
}
|
||||
#endif
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
ALLOW_CLONE(MTruncateToInt32)
|
||||
};
|
||||
|
||||
@ -6100,6 +6109,7 @@ class MStringReplace
|
||||
bool congruentTo(const MDefinition *ins) const {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
@ -76,15 +76,6 @@ ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
|
||||
MInstruction *replace;
|
||||
|
||||
// If the input is a string or object, the conversion is not
|
||||
// possible--at least, we can't specialize. So box the input.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
(in->type() == MIRType_Undefined && specialization_ == MIRType_Int32))
|
||||
{
|
||||
in = boxAt(alloc, ins, in);
|
||||
}
|
||||
|
||||
if (ins->type() == MIRType_Double)
|
||||
replace = MToDouble::New(alloc, in);
|
||||
else if (ins->type() == MIRType_Float32)
|
||||
@ -94,6 +85,9 @@ ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(i, replace);
|
||||
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -194,13 +188,6 @@ ComparePolicy::adjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
|
||||
MInstruction *replace;
|
||||
|
||||
// See ArithPolicy::adjustInputs for an explanation of the following.
|
||||
if (in->type() == MIRType_Object || in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Undefined)
|
||||
{
|
||||
in = boxAt(alloc, def, in);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MIRType_Double: {
|
||||
MToDouble::ConversionKind convert = MToDouble::NumbersOnly;
|
||||
@ -265,6 +252,9 @@ ComparePolicy::adjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(i, replace);
|
||||
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -362,17 +352,12 @@ BitwisePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
if (in->type() == MIRType_Int32)
|
||||
continue;
|
||||
|
||||
// See ArithPolicy::adjustInputs for an explanation of the following.
|
||||
// MTruncateToInt32 in particular does not support MIRType_Symbol input.
|
||||
if (in->type() == MIRType_Object || in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol)
|
||||
{
|
||||
in = boxAt(alloc, ins, in);
|
||||
}
|
||||
|
||||
MInstruction *replace = MTruncateToInt32::New(alloc, in);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(i, replace);
|
||||
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -467,7 +452,8 @@ ConvertToInt32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction
|
||||
MToInt32 *replace = MToInt32::New(alloc, in);
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(Op, replace);
|
||||
return true;
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool ConvertToInt32Policy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
|
||||
@ -480,25 +466,11 @@ DoublePolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
if (in->type() == MIRType_Double)
|
||||
return true;
|
||||
|
||||
// Force a bailout. Objects may be effectful; strings and symbols are
|
||||
// currently unhandled.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol)
|
||||
{
|
||||
MBox *box = MBox::New(alloc, in);
|
||||
def->block()->insertBefore(def, box);
|
||||
|
||||
MUnbox *unbox = MUnbox::New(alloc, box, MIRType_Double, MUnbox::Fallible);
|
||||
def->block()->insertBefore(def, unbox);
|
||||
def->replaceOperand(Op, unbox);
|
||||
return true;
|
||||
}
|
||||
|
||||
MToDouble *replace = MToDouble::New(alloc, in);
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(Op, replace);
|
||||
return true;
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool DoublePolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
|
||||
@ -512,32 +484,11 @@ Float32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
if (in->type() == MIRType_Float32)
|
||||
return true;
|
||||
|
||||
// Force a bailout. Objects may be effectful; strings and symbols are
|
||||
// currently unhandled.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol)
|
||||
{
|
||||
MToDouble *toDouble = MToDouble::New(alloc, in);
|
||||
def->block()->insertBefore(def, toDouble);
|
||||
|
||||
MBox *box = MBox::New(alloc, toDouble);
|
||||
def->block()->insertBefore(def, box);
|
||||
|
||||
MUnbox *unbox = MUnbox::New(alloc, box, MIRType_Double, MUnbox::Fallible);
|
||||
def->block()->insertBefore(def, unbox);
|
||||
|
||||
MToFloat32 *toFloat32 = MToFloat32::New(alloc, unbox);
|
||||
def->block()->insertBefore(def, toFloat32);
|
||||
|
||||
def->replaceOperand(Op, unbox);
|
||||
return true;
|
||||
}
|
||||
|
||||
MToFloat32 *replace = MToFloat32::New(alloc, in);
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(Op, replace);
|
||||
return true;
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool Float32Policy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
|
||||
@ -609,18 +560,24 @@ ToDoublePolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
bool
|
||||
ToInt32Policy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
JS_ASSERT(ins->isToInt32());
|
||||
JS_ASSERT(ins->isToInt32() || ins->isTruncateToInt32());
|
||||
|
||||
MDefinition *in = ins->getOperand(0);
|
||||
switch (in->type()) {
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Undefined:
|
||||
// Objects might be effectful. Undefined and symbols coerce to NaN, not int32.
|
||||
// Objects might be effectful. Symbols give TypeError.
|
||||
in = boxAt(alloc, ins, in);
|
||||
ins->replaceOperand(0, in);
|
||||
break;
|
||||
case MIRType_Undefined:
|
||||
// Undefined coerce to NaN, not int32, when not truncated.
|
||||
if (ins->isToInt32()) {
|
||||
in = boxAt(alloc, ins, in);
|
||||
ins->replaceOperand(0, in);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -656,13 +613,11 @@ ObjectPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in->type() != MIRType_Value)
|
||||
in = boxAt(alloc, ins, in);
|
||||
|
||||
MUnbox *replace = MUnbox::New(alloc, in, MIRType_Object, MUnbox::Fallible);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(Op, replace);
|
||||
return true;
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool ObjectPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
|
||||
@ -677,14 +632,12 @@ CallPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
|
||||
MDefinition *func = call->getFunction();
|
||||
if (func->type() != MIRType_Object) {
|
||||
// If the function is impossible to call,
|
||||
// bail out by causing a subsequent unbox to fail.
|
||||
if (func->type() != MIRType_Value)
|
||||
func = boxAt(alloc, call, func);
|
||||
|
||||
MInstruction *unbox = MUnbox::New(alloc, func, MIRType_Object, MUnbox::Fallible);
|
||||
call->block()->insertBefore(call, unbox);
|
||||
call->replaceFunction(unbox);
|
||||
|
||||
if (!unbox->typePolicy()->adjustInputs(alloc, unbox))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < call->numStackArgs(); i++)
|
||||
|
@ -126,6 +126,7 @@ LIRGeneratorARM::visitUnbox(MUnbox *unbox)
|
||||
// a payload. Unlike most instructions conusming a box, we ask for the type
|
||||
// second, so that the result can re-use the first input.
|
||||
MDefinition *inner = unbox->getOperand(0);
|
||||
JS_ASSERT(inner->type() == MIRType_Value);
|
||||
|
||||
if (!ensureDefined(inner))
|
||||
return false;
|
||||
|
@ -128,6 +128,7 @@ LIRGeneratorMIPS::visitUnbox(MUnbox *unbox)
|
||||
// a payload. Unlike most instructions consuming a box, we ask for the type
|
||||
// second, so that the result can re-use the first input.
|
||||
MDefinition *inner = unbox->getOperand(0);
|
||||
JS_ASSERT(inner->type() == MIRType_Value);
|
||||
|
||||
if (!ensureDefined(inner))
|
||||
return false;
|
||||
|
@ -75,6 +75,8 @@ bool
|
||||
LIRGeneratorX64::visitUnbox(MUnbox *unbox)
|
||||
{
|
||||
MDefinition *box = unbox->getOperand(0);
|
||||
JS_ASSERT(box->type() == MIRType_Value);
|
||||
|
||||
LUnboxBase *lir;
|
||||
if (IsFloatingPointType(unbox->type()))
|
||||
lir = new(alloc()) LUnboxFloatingPoint(useRegisterAtStart(box), unbox->type());
|
||||
|
@ -119,6 +119,7 @@ LIRGeneratorX86::visitUnbox(MUnbox *unbox)
|
||||
// a payload. Unlike most instructions conusming a box, we ask for the type
|
||||
// second, so that the result can re-use the first input.
|
||||
MDefinition *inner = unbox->getOperand(0);
|
||||
JS_ASSERT(inner->type() == MIRType_Value);
|
||||
|
||||
if (!ensureDefined(inner))
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user