mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1028910: Improve types at branches with MIsObject. r=h4writer.
This commit is contained in:
parent
416979553c
commit
dab4089818
14
js/src/jit-test/tests/ion/bug1028910.js
Normal file
14
js/src/jit-test/tests/ion/bug1028910.js
Normal 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({})
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user