From dab40898184c8a12d09f8a1a26b55dbc43354255 Mon Sep 17 00:00:00 2001 From: Sushant Dinesh Date: Fri, 4 Jul 2014 15:40:33 +0200 Subject: [PATCH] Bug 1028910: Improve types at branches with MIsObject. r=h4writer. --- js/src/jit-test/tests/ion/bug1028910.js | 14 ++++++++++ js/src/jit/IonBuilder.cpp | 37 +++++++++++++++++++------ js/src/jsinfer.cpp | 12 ++++++++ js/src/jsinfer.h | 3 ++ 4 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 js/src/jit-test/tests/ion/bug1028910.js diff --git a/js/src/jit-test/tests/ion/bug1028910.js b/js/src/jit-test/tests/ion/bug1028910.js new file mode 100644 index 000000000000..9626447918f2 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1028910.js @@ -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({}) +} diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 563eb767cb14..65f0671f3d30 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -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; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 6b30e9d6f8a3..2eff1e1138f2 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -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) { diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index f989d6796bb9..923320e33eb8 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -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);