Bug 1034184 - IonMonkey: Enable taking the union of a filter at tests. r=h4writer

This commit is contained in:
Sushant Dinesh 2014-09-10 12:10:52 +02:00
parent b8d695fb8b
commit 4f4d73453f
5 changed files with 96 additions and 21 deletions

View File

@ -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;

View File

@ -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.

View File

@ -10623,7 +10623,6 @@ class MFilterTypeSet
: MUnaryInstruction(def)
{
MOZ_ASSERT(!types->unknown());
MOZ_ASSERT(def->type() == types->getKnownMIRType());
setResultType(types->getKnownMIRType());
setResultTypeSet(types);
}

View File

@ -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
/////////////////////////////////////////////////////////////////////

View File

@ -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);