зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1004388 part 1. When we're testing an MPhi that doesn't represent the and-or pattern, just fall back to optimizing the typeset for the true/false branches based on the truthiness directly, like we would for the non-MPhi case. r=jandem
This commit is contained in:
Родитель
9284760710
Коммит
ca52532afc
|
@ -3367,6 +3367,11 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test)
|
||||||
if (!ins)
|
if (!ins)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// All branches of this switch that don't want to fall through to the
|
||||||
|
// default behavior must return. The default behavior assumes that a true
|
||||||
|
// test means the incoming ins is not null or undefined and that a false
|
||||||
|
// tests means it's one of null, undefined, false, 0, "", and objects
|
||||||
|
// emulating undefined
|
||||||
switch (ins->op()) {
|
switch (ins->op()) {
|
||||||
case MDefinition::Op_Not:
|
case MDefinition::Op_Not:
|
||||||
return improveTypesAtTest(ins->toNot()->getOperand(0), !trueBranch, test);
|
return improveTypesAtTest(ins->toNot()->getOperand(0), !trueBranch, test);
|
||||||
|
@ -3390,8 +3395,10 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test)
|
||||||
}
|
}
|
||||||
case MDefinition::Op_Phi: {
|
case MDefinition::Op_Phi: {
|
||||||
bool branchIsAnd = true;
|
bool branchIsAnd = true;
|
||||||
if (!detectAndOrStructure(ins->toPhi(), &branchIsAnd))
|
if (!detectAndOrStructure(ins->toPhi(), &branchIsAnd)) {
|
||||||
return true;
|
// Just fall through to the default behavior.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Now we have detected the triangular structure and determined if it was an AND or an OR.
|
// Now we have detected the triangular structure and determined if it was an AND or an OR.
|
||||||
if (branchIsAnd) {
|
if (branchIsAnd) {
|
||||||
|
@ -3430,53 +3437,54 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test)
|
||||||
case MDefinition::Op_Compare:
|
case MDefinition::Op_Compare:
|
||||||
return improveTypesAtCompare(ins->toCompare(), trueBranch, test);
|
return improveTypesAtCompare(ins->toCompare(), trueBranch, test);
|
||||||
|
|
||||||
// By default MTest tests ToBoolean(input). As a result in the true branch we can filter
|
default:
|
||||||
// undefined and null. In false branch we can only encounter undefined, null, false, 0, ""
|
break;
|
||||||
// and objects that emulate undefined.
|
|
||||||
default: {
|
|
||||||
// If ins does not have a typeset we return as we cannot optimize.
|
|
||||||
if (!ins->resultTypeSet() || ins->resultTypeSet()->unknown())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
types::TemporaryTypeSet *oldType = ins->resultTypeSet();
|
|
||||||
types::TemporaryTypeSet *type;
|
|
||||||
|
|
||||||
// Decide either to set or filter.
|
|
||||||
if (trueBranch) {
|
|
||||||
// Filter undefined/null.
|
|
||||||
if (!ins->mightBeType(MIRType_Undefined) &&
|
|
||||||
!ins->mightBeType(MIRType_Null))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
type = oldType->filter(alloc_->lifoAlloc(), true, true);
|
|
||||||
} else {
|
|
||||||
// According to the standards, we cannot filter out: Strings,
|
|
||||||
// Int32, Double, Booleans, Objects (if they emulate undefined)
|
|
||||||
uint32_t flags = types::TYPE_FLAG_PRIMITIVE;
|
|
||||||
|
|
||||||
// If the typeset does emulate undefined, then we cannot filter out
|
|
||||||
// objects.
|
|
||||||
if (oldType->maybeEmulatesUndefined())
|
|
||||||
flags |= types::TYPE_FLAG_ANYOBJECT;
|
|
||||||
|
|
||||||
// Only intersect the typesets if it will generate a more narrow
|
|
||||||
// typeset. The first part takes care of primitives and AnyObject,
|
|
||||||
// while the second line specific (type)objects.
|
|
||||||
if (!oldType->hasAnyFlag(~flags & types::TYPE_FLAG_BASE_MASK) &&
|
|
||||||
(oldType->maybeEmulatesUndefined() || !oldType->maybeObject()))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
types::TemporaryTypeSet base(flags, static_cast<types::TypeObjectKey**>(nullptr));
|
|
||||||
type = types::TypeSet::intersectSets(&base, oldType, alloc_->lifoAlloc());
|
|
||||||
}
|
|
||||||
replaceTypeSet(ins, type, test);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
// By default MTest tests ToBoolean(input). As a result in the true branch we can filter
|
||||||
|
// undefined and null. In false branch we can only encounter undefined, null, false, 0, ""
|
||||||
|
// and objects that emulate undefined.
|
||||||
|
|
||||||
|
// If ins does not have a typeset we return as we cannot optimize.
|
||||||
|
if (!ins->resultTypeSet() || ins->resultTypeSet()->unknown())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
types::TemporaryTypeSet *oldType = ins->resultTypeSet();
|
||||||
|
types::TemporaryTypeSet *type;
|
||||||
|
|
||||||
|
// Decide either to set or filter.
|
||||||
|
if (trueBranch) {
|
||||||
|
// Filter undefined/null.
|
||||||
|
if (!ins->mightBeType(MIRType_Undefined) &&
|
||||||
|
!ins->mightBeType(MIRType_Null))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
type = oldType->filter(alloc_->lifoAlloc(), true, true);
|
||||||
|
} else {
|
||||||
|
// According to the standards, we cannot filter out: Strings,
|
||||||
|
// Int32, Double, Booleans, Objects (if they emulate undefined)
|
||||||
|
uint32_t flags = types::TYPE_FLAG_PRIMITIVE;
|
||||||
|
|
||||||
|
// If the typeset does emulate undefined, then we cannot filter out
|
||||||
|
// objects.
|
||||||
|
if (oldType->maybeEmulatesUndefined())
|
||||||
|
flags |= types::TYPE_FLAG_ANYOBJECT;
|
||||||
|
|
||||||
|
// Only intersect the typesets if it will generate a more narrow
|
||||||
|
// typeset. The first part takes care of primitives and AnyObject,
|
||||||
|
// while the second line specific (type)objects.
|
||||||
|
if (!oldType->hasAnyFlag(~flags & types::TYPE_FLAG_BASE_MASK) &&
|
||||||
|
(oldType->maybeEmulatesUndefined() || !oldType->maybeObject()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
types::TemporaryTypeSet base(flags, static_cast<types::TypeObjectKey**>(nullptr));
|
||||||
|
type = types::TypeSet::intersectSets(&base, oldType, alloc_->lifoAlloc());
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaceTypeSet(ins, type, test);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
Загрузка…
Ссылка в новой задаче