mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1034184 - IonMonkey: Enable taking the union of a filter at tests. r=h4writer
This commit is contained in:
parent
b8d695fb8b
commit
4f4d73453f
@ -3077,25 +3077,55 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote *sn)
|
||||
return ControlStatus_Jumped;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
IonBuilder::replaceTypeSet(MDefinition *subject, types::TemporaryTypeSet *type, MTest *test)
|
||||
{
|
||||
MDefinition *replace = nullptr;
|
||||
if (type->unknown())
|
||||
return true;
|
||||
|
||||
MFilterTypeSet *replace = nullptr;
|
||||
MDefinition *ins;
|
||||
|
||||
for (uint32_t i = 0; i < current->stackDepth(); i++) {
|
||||
if (current->getSlot(i) != subject)
|
||||
ins = current->getSlot(i);
|
||||
|
||||
// Instead of creating a new MFilterTypeSet, try to update the old one.
|
||||
if (ins->isFilterTypeSet() && ins->getOperand(0) == subject &&
|
||||
ins->dependency() == test)
|
||||
{
|
||||
types::TemporaryTypeSet *intersect =
|
||||
types::TypeSet::intersectSets(ins->resultTypeSet(), type, alloc_->lifoAlloc());
|
||||
if (!intersect)
|
||||
return false;
|
||||
|
||||
ins->toFilterTypeSet()->setResultType(intersect->getKnownMIRType());
|
||||
ins->toFilterTypeSet()->setResultTypeSet(intersect);
|
||||
continue;
|
||||
if (!replace) {
|
||||
replace = ensureDefiniteTypeSet(subject, type);
|
||||
if (replace != subject) {
|
||||
// Make sure we don't hoist it above the MTest, we can use the
|
||||
// 'dependency' of an MInstruction. This is normally used by
|
||||
// Alias Analysis, but won't get overwritten, since this
|
||||
// instruction doesn't have an AliasSet.
|
||||
replace->setDependency(test);
|
||||
}
|
||||
}
|
||||
current->setSlot(i, replace);
|
||||
|
||||
if (ins == subject) {
|
||||
if (!replace) {
|
||||
replace = MFilterTypeSet::New(alloc(), subject, type);
|
||||
|
||||
if (!replace)
|
||||
return false;
|
||||
if (replace == subject)
|
||||
break;
|
||||
|
||||
current->add(replace);
|
||||
|
||||
if (replace != subject) {
|
||||
// Make sure we don't hoist it above the MTest, we can use the
|
||||
// 'dependency' of an MInstruction. This is normally used by
|
||||
// Alias Analysis, but won't get overwritten, since this
|
||||
// instruction doesn't have an AliasSet.
|
||||
replace->setDependency(test);
|
||||
}
|
||||
}
|
||||
current->setSlot(i, replace);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3200,9 +3230,7 @@ IonBuilder::improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test)
|
||||
if (!type)
|
||||
return false;
|
||||
|
||||
replaceTypeSet(subject, type, test);
|
||||
|
||||
return true;
|
||||
return replaceTypeSet(subject, type, test);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3232,8 +3260,7 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test)
|
||||
if (!type)
|
||||
return false;
|
||||
|
||||
replaceTypeSet(ins->getOperand(0), type, test);
|
||||
return true;
|
||||
return replaceTypeSet(ins->getOperand(0), type, test);
|
||||
}
|
||||
case MDefinition::Op_Phi: {
|
||||
bool branchIsAnd = true;
|
||||
|
@ -348,7 +348,7 @@ class IonBuilder : public MIRGenerator
|
||||
bool improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test);
|
||||
// Used to detect triangular structure at test.
|
||||
bool detectAndOrStructure(MPhi *ins, bool *branchIsTrue);
|
||||
void replaceTypeSet(MDefinition *subject, types::TemporaryTypeSet *type, MTest *test);
|
||||
bool replaceTypeSet(MDefinition *subject, types::TemporaryTypeSet *type, MTest *test);
|
||||
|
||||
// Add a guard which ensure that the set of type which goes through this
|
||||
// generated code correspond to the observed types for the bytecode.
|
||||
|
@ -10623,7 +10623,6 @@ class MFilterTypeSet
|
||||
: MUnaryInstruction(def)
|
||||
{
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
MOZ_ASSERT(def->type() == types->getKnownMIRType());
|
||||
setResultType(types->getKnownMIRType());
|
||||
setResultTypeSet(types);
|
||||
}
|
||||
|
@ -698,7 +698,7 @@ TypeSet::cloneObjectsOnly(LifoAlloc *alloc)
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
res->flags &= TYPE_FLAG_ANYOBJECT;
|
||||
res->flags &= ~TYPE_FLAG_BASE_MASK | TYPE_FLAG_ANYOBJECT;
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -737,6 +737,53 @@ TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* static */ TemporaryTypeSet *
|
||||
TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *alloc)
|
||||
{
|
||||
TemporaryTypeSet *res;
|
||||
res = alloc->new_<TemporaryTypeSet>(a->baseFlags() & b->baseFlags(),
|
||||
static_cast<TypeObjectKey**>(nullptr));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
res->setBaseObjectCount(0);
|
||||
if (res->unknownObject())
|
||||
return res;
|
||||
|
||||
MOZ_ASSERT(!a->unknownObject() || !b->unknownObject());
|
||||
|
||||
if (a->unknownObject()) {
|
||||
for (size_t i = 0; i < b->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(b->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (b->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(a->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!a->unknownObject() && !b->unknownObject());
|
||||
|
||||
for (size_t i = 0; i < a->getObjectCount(); i++) {
|
||||
for (size_t j = 0; j < b->getObjectCount(); j++) {
|
||||
if (b->getObject(j) != a->getObject(i))
|
||||
continue;
|
||||
if (!b->getObject(j))
|
||||
continue;
|
||||
res->addType(Type::ObjectType(b->getObject(j)), alloc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Compiler constraints
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -572,6 +572,8 @@ class TypeSet
|
||||
|
||||
/* Join two type sets into a new set. The result should not be modified further. */
|
||||
static TemporaryTypeSet *unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc);
|
||||
/* Return the intersection of the 2 TypeSets. The result should not be modified further */
|
||||
static TemporaryTypeSet *intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *alloc);
|
||||
|
||||
/* Add a type to this set using the specified allocator. */
|
||||
void addType(Type type, LifoAlloc *alloc);
|
||||
|
Loading…
Reference in New Issue
Block a user