зеркало из https://github.com/mozilla/gecko-dev.git
Bug 847045 - Avoid frequent ExcludeType bailouts. r=nbp
This commit is contained in:
Родитель
fb908073ee
Коммит
7c0147addc
|
@ -957,20 +957,6 @@ CodeGenerator::visitMonitorTypes(LMonitorTypes *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitExcludeType(LExcludeType *lir)
|
||||
{
|
||||
ValueOperand operand = ToValue(lir, LExcludeType::Input);
|
||||
Register scratch = ToRegister(lir->temp());
|
||||
|
||||
Label matched, miss;
|
||||
masm.guardType(operand, lir->mir()->type(), scratch, &matched, &miss);
|
||||
if (matched.used() && !bailoutFrom(&matched, lir->snapshot()))
|
||||
return false;
|
||||
masm.bind(&miss);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitCallNative(LCallNative *call)
|
||||
{
|
||||
|
|
|
@ -84,7 +84,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
|
||||
bool visitTypeBarrier(LTypeBarrier *lir);
|
||||
bool visitMonitorTypes(LMonitorTypes *lir);
|
||||
bool visitExcludeType(LExcludeType *lir);
|
||||
bool visitCallNative(LCallNative *call);
|
||||
bool emitCallInvokeFunction(LInstruction *call, Register callereg,
|
||||
uint32_t argc, uint32_t unusedStack);
|
||||
|
|
|
@ -3027,10 +3027,13 @@ IonBuilder::addTypeBarrier(uint32_t i, CallInfo &callinfo, types::StackTypeSet *
|
|||
callerObs = callinfo.getArgType(i - 1);
|
||||
}
|
||||
|
||||
bool needsBarrier = false;
|
||||
|
||||
while (excluded) {
|
||||
if (excluded->target == calleeObs && callerObs->hasType(excluded->type)) {
|
||||
if (excluded->type == types::Type::DoubleType() &&
|
||||
calleeObs->hasType(types::Type::Int32Type())) {
|
||||
calleeObs->hasType(types::Type::Int32Type()))
|
||||
{
|
||||
// The double type also implies int32, so this implies that
|
||||
// double should be coerced into int if possible, and other
|
||||
// types should remain.
|
||||
|
@ -3040,7 +3043,6 @@ IonBuilder::addTypeBarrier(uint32_t i, CallInfo &callinfo, types::StackTypeSet *
|
|||
MInstruction *bailType = MToInt32::New(ins);
|
||||
current->add(bailType);
|
||||
ins = bailType;
|
||||
break;
|
||||
} else {
|
||||
// We expect either an Int or a Value, this variant is not
|
||||
// optimized and favor the int variant by filtering out all
|
||||
|
@ -3054,18 +3056,21 @@ IonBuilder::addTypeBarrier(uint32_t i, CallInfo &callinfo, types::StackTypeSet *
|
|||
current->add(toInt);
|
||||
ins = toInt;
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(!calleeObs->hasType(excluded->type));
|
||||
|
||||
// Filter out unexpected type which are not yet added to the set
|
||||
// observed type but which are infered by type inference.
|
||||
MInstruction *bailType = MExcludeType::New(ins, excluded->type);
|
||||
current->add(bailType);
|
||||
needsBarrier = false;
|
||||
break;
|
||||
}
|
||||
|
||||
needsBarrier = true;
|
||||
}
|
||||
excluded = excluded->next;
|
||||
}
|
||||
|
||||
if (needsBarrier) {
|
||||
MTypeBarrier *barrier = MTypeBarrier::New(ins, cloneTypeSet(calleeObs), Bailout_Normal);
|
||||
current->add(barrier);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
callinfo.setThis(ins);
|
||||
else
|
||||
|
|
|
@ -3735,11 +3735,10 @@ class LParDump : public LCallInstructionHelper<0, BOX_PIECES, 0>
|
|||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LTypeBarrier : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
|
||||
class LTypeBarrier : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypeBarrier)
|
||||
BOX_OUTPUT_ACCESSORS()
|
||||
|
||||
LTypeBarrier(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
|
@ -3775,27 +3774,6 @@ class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 1>
|
|||
}
|
||||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LExcludeType : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(ExcludeType);
|
||||
BOX_OUTPUT_ACCESSORS();
|
||||
|
||||
LExcludeType(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MExcludeType *mir() const {
|
||||
return mir_->toExcludeType();
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Guard against an object's class.
|
||||
class LGuardClass : public LInstructionHelper<0, 1, 1>
|
||||
{
|
||||
|
|
|
@ -134,7 +134,6 @@
|
|||
_(ParDump) \
|
||||
_(TypeBarrier) \
|
||||
_(MonitorTypes) \
|
||||
_(ExcludeType) \
|
||||
_(InitializedLength) \
|
||||
_(SetInitializedLength) \
|
||||
_(BoundsCheck) \
|
||||
|
|
|
@ -1650,7 +1650,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
return false;
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
return false;
|
||||
return defineAs(barrier, ins, ins->input()) && add(barrier);
|
||||
return redefine(ins, ins->input()) && add(barrier, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1664,18 +1664,6 @@ LIRGenerator::visitMonitorTypes(MMonitorTypes *ins)
|
|||
return assignSnapshot(lir, Bailout_Monitor) && add(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitExcludeType(MExcludeType *ins)
|
||||
{
|
||||
LExcludeType *filter = new LExcludeType(temp());
|
||||
if (!useBox(filter, LExcludeType::Input, ins->input()))
|
||||
return false;
|
||||
if (!assignSnapshot(filter, ins->bailoutKind()))
|
||||
return false;
|
||||
filter->setMir(ins);
|
||||
return add(filter);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitArrayLength(MArrayLength *ins)
|
||||
{
|
||||
|
|
|
@ -160,7 +160,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitStoreSlot(MStoreSlot *ins);
|
||||
bool visitTypeBarrier(MTypeBarrier *ins);
|
||||
bool visitMonitorTypes(MMonitorTypes *ins);
|
||||
bool visitExcludeType(MExcludeType *ins);
|
||||
bool visitArrayLength(MArrayLength *ins);
|
||||
bool visitTypedArrayLength(MTypedArrayLength *ins);
|
||||
bool visitTypedArrayElements(MTypedArrayElements *ins);
|
||||
|
|
|
@ -6162,28 +6162,39 @@ class MParDump
|
|||
|
||||
// Given a value, guard that the value is in a particular TypeSet, then returns
|
||||
// that value.
|
||||
class MTypeBarrier : public MUnaryInstruction
|
||||
class MTypeBarrier
|
||||
: public MUnaryInstruction,
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
BailoutKind bailoutKind_;
|
||||
const types::StackTypeSet *typeSet_;
|
||||
|
||||
MTypeBarrier(MDefinition *def, const types::StackTypeSet *types)
|
||||
MTypeBarrier(MDefinition *def, const types::StackTypeSet *types, BailoutKind bailoutKind)
|
||||
: MUnaryInstruction(def),
|
||||
typeSet_(types)
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
setGuard();
|
||||
setMovable();
|
||||
bailoutKind_ = def->isEffectful()
|
||||
? Bailout_TypeBarrier
|
||||
: Bailout_Normal;
|
||||
bailoutKind_ = bailoutKind;
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypeBarrier)
|
||||
|
||||
static MTypeBarrier *New(MDefinition *def, const types::StackTypeSet *types) {
|
||||
return new MTypeBarrier(def, types);
|
||||
BailoutKind bailoutKind = def->isEffectful()
|
||||
? Bailout_TypeBarrier
|
||||
: Bailout_Normal;
|
||||
return new MTypeBarrier(def, types, bailoutKind);
|
||||
}
|
||||
static MTypeBarrier *New(MDefinition *def, const types::StackTypeSet *types,
|
||||
BailoutKind bailoutKind) {
|
||||
return new MTypeBarrier(def, types, bailoutKind);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
bool congruentTo(MDefinition * const &def) const {
|
||||
|
@ -6204,7 +6215,6 @@ class MTypeBarrier : public MUnaryInstruction
|
|||
virtual bool neverHoist() const {
|
||||
return typeSet()->empty();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Like MTypeBarrier, guard that the value is in the given type set. This is
|
||||
|
@ -6240,46 +6250,6 @@ class MMonitorTypes : public MUnaryInstruction
|
|||
}
|
||||
};
|
||||
|
||||
// Guards that the incoming value does not have the specified Type.
|
||||
class MExcludeType
|
||||
: public MUnaryInstruction,
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
types::Type type_;
|
||||
|
||||
MExcludeType(MDefinition *def, types::Type type)
|
||||
: MUnaryInstruction(def),
|
||||
type_(type)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ExcludeType);
|
||||
|
||||
static MExcludeType *New(MDefinition *def, types::Type type) {
|
||||
return new MExcludeType(def, type);
|
||||
}
|
||||
|
||||
MDefinition *input() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
BailoutKind bailoutKind() const {
|
||||
return Bailout_Normal;
|
||||
}
|
||||
types::Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MNewSlots : public MNullaryInstruction
|
||||
{
|
||||
unsigned nslots_;
|
||||
|
|
|
@ -98,7 +98,6 @@ namespace ion {
|
|||
_(FunctionEnvironment) \
|
||||
_(TypeBarrier) \
|
||||
_(MonitorTypes) \
|
||||
_(ExcludeType) \
|
||||
_(GetPropertyCache) \
|
||||
_(GetElementCache) \
|
||||
_(BindNameCache) \
|
||||
|
|
|
@ -194,7 +194,6 @@ class ParallelArrayVisitor : public MInstructionVisitor
|
|||
SAFE_OP(FunctionEnvironment) // just a load of func env ptr
|
||||
SAFE_OP(TypeBarrier) // causes a bailout if the type is not found: a-ok with us
|
||||
SAFE_OP(MonitorTypes) // causes a bailout if the type is not found: a-ok with us
|
||||
SAFE_OP(ExcludeType) // causes a bailout if the type is not found: a-ok with us
|
||||
UNSAFE_OP(GetPropertyCache)
|
||||
UNSAFE_OP(GetElementCache)
|
||||
UNSAFE_OP(BindNameCache)
|
||||
|
|
Загрузка…
Ссылка в новой задаче