Bug 1028910: Improve types at branches with MIsObject. r=h4writer.

This commit is contained in:
Sushant Dinesh 2014-07-04 15:40:33 +02:00
parent 416979553c
commit dab4089818
4 changed files with 57 additions and 9 deletions

View File

@ -0,0 +1,14 @@
setJitCompilerOption("ion.usecount.trigger", 4);
var IsObject = getSelfHostedValue("IsObject")
function test(foo) {
if (IsObject(foo)) {
print(foo.test)
}
}
for (var i=0; i<10; i++) {
test(1)
test({})
}

View File

@ -3070,10 +3070,24 @@ IonBuilder::filterTypesAtTest(MTest *test)
bool trueBranch = test->ifTrue() == current;
MDefinition *subject = nullptr;
bool removeUndefined;
bool removeNull;
bool removeUndefined = false;
bool removeNull = false;
bool setTypeToObject = false;
test->filtersUndefinedOrNull(trueBranch, &subject, &removeUndefined, &removeNull);
// setTypeToObject is set to true only when we're sure that the type is object.
// If IsObject results to true, and we're in the true branch,
// then setTypeToObject is true. Similarly, if the instruction is !IsObject and
// we're not in true branch.
MDefinition *ins = test->getOperand(0);
if (ins->isIsObject() && trueBranch) {
setTypeToObject = true;
subject = ins->getOperand(0);
} else if (!trueBranch && ins->isNot() && ins->toNot()->getOperand(0)->isIsObject()) {
setTypeToObject = true;
subject = ins->getOperand(0)->getOperand(0);
} else {
test->filtersUndefinedOrNull(trueBranch, &subject, &removeUndefined, &removeNull);
}
// The test filters no undefined or null.
if (!subject)
@ -3083,9 +3097,11 @@ IonBuilder::filterTypesAtTest(MTest *test)
if (!subject->resultTypeSet() || subject->resultTypeSet()->unknown())
return true;
// Only do this optimization if the typeset does contains null or undefined.
if ((!(removeUndefined && subject->resultTypeSet()->hasType(types::Type::UndefinedType())) &&
!(removeNull && subject->resultTypeSet()->hasType(types::Type::NullType()))))
// Only do this optimization if the typeset does contains null or undefined
// or if type isn't already object only.
if (!(removeUndefined && subject->resultTypeSet()->hasType(types::Type::UndefinedType())) &&
!(removeNull && subject->resultTypeSet()->hasType(types::Type::NullType())) &&
!(setTypeToObject && subject->type() != MIRType_Object))
{
return true;
}
@ -3100,9 +3116,12 @@ IonBuilder::filterTypesAtTest(MTest *test)
// Create replacement MIR with filtered TypesSet.
if (!replace) {
types::TemporaryTypeSet *type =
subject->resultTypeSet()->filter(alloc_->lifoAlloc(), removeUndefined,
removeNull);
types::TemporaryTypeSet *type;
if (setTypeToObject)
type = subject->resultTypeSet()->cloneObjectsOnly(alloc_->lifoAlloc());
else
type = subject->resultTypeSet()->filter(alloc_->lifoAlloc(), removeUndefined,
removeNull);
if (!type)
return false;

View File

@ -679,6 +679,18 @@ TypeSet::filter(LifoAlloc *alloc, bool filterUndefined, bool filterNull) const
return res;
}
TemporaryTypeSet *
TypeSet::cloneObjectsOnly(LifoAlloc *alloc)
{
TemporaryTypeSet *res = clone(alloc);
if (!res)
return nullptr;
res->flags &= TYPE_FLAG_ANYOBJECT;
return res;
}
/* static */ TemporaryTypeSet *
TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
{

View File

@ -624,6 +624,9 @@ class TypeSet
// Create a new TemporaryTypeSet where undefined and/or null has been filtered out.
TemporaryTypeSet *filter(LifoAlloc *alloc, bool filterUndefined, bool filterNull) const;
// Create a new TemporaryTypeSet where the type has been set to object.
TemporaryTypeSet *cloneObjectsOnly(LifoAlloc *alloc);
// Trigger a read barrier on all the contents of a type set.
static void readBarrier(const TypeSet *types);