From f5e28900f7347826c882a8d43d4e44c9eb797713 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Sat, 28 Feb 2015 01:30:42 +0100 Subject: [PATCH] Bug 994016: IonMonkey: Use high level TI API for improving types at branches, r=bhackett --- js/src/jit/IonBuilder.cpp | 69 +++++++++++++++---------------------- js/src/vm/TypeInference.cpp | 4 +-- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 68d620b214a2..3c3e8509b53f 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -3308,6 +3308,9 @@ IonBuilder::replaceTypeSet(MDefinition *subject, TemporaryTypeSet *type, MTest * if (type->unknown()) return true; + if (type->equals(subject->resultTypeSet())) + return true; + MInstruction *replace = nullptr; MDefinition *ins; @@ -3456,12 +3459,6 @@ IonBuilder::improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test) if (!subject->resultTypeSet() || subject->resultTypeSet()->unknown()) return true; - if (!subject->mightBeType(MIRType_Undefined) && - !subject->mightBeType(MIRType_Null)) - { - return true; - } - if (!altersUndefined && !altersNull) return true; @@ -3469,29 +3466,27 @@ IonBuilder::improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test) // Decide if we need to filter the type or set it. if ((op == JSOP_STRICTEQ || op == JSOP_EQ) ^ trueBranch) { - // Filter undefined/null - uint32_t flags = 0; + // Remove undefined/null + TemporaryTypeSet remove; if (altersUndefined) - flags |= types::TYPE_FLAG_UNDEFINED; + remove.addType(TypeSet::UndefinedType(), alloc_->lifoAlloc()); if (altersNull) - flags |= types::TYPE_FLAG_NULL; + remove.addType(TypeSet::NullType(), alloc_->lifoAlloc()); - types::TemporaryTypeSet remove(flags, static_cast(nullptr)); - type = types::TypeSet::removeSet(subject->resultTypeSet(), &remove, alloc_->lifoAlloc()); + type = TypeSet::removeSet(subject->resultTypeSet(), &remove, alloc_->lifoAlloc()); } else { // Set undefined/null. - uint32_t flags = 0; + TemporaryTypeSet base; if (altersUndefined) { - flags |= TYPE_FLAG_UNDEFINED; + base.addType(TypeSet::UndefinedType(), alloc_->lifoAlloc()); // If TypeSet emulates undefined, then we cannot filter the objects. if (subject->resultTypeSet()->maybeEmulatesUndefined(constraints())) - flags |= TYPE_FLAG_ANYOBJECT; + base.addType(TypeSet::AnyObjectType(), alloc_->lifoAlloc()); } if (altersNull) - flags |= TYPE_FLAG_NULL; + base.addType(TypeSet::NullType(), alloc_->lifoAlloc()); - TemporaryTypeSet base(flags, static_cast(nullptr)); type = TypeSet::intersectSets(&base, subject->resultTypeSet(), alloc_->lifoAlloc()); } @@ -3540,7 +3535,8 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test) break; } - // Now we have detected the triangular structure and determined if it was an AND or an OR. + // Now we have detected the triangular structure and determined if it + // was an AND or an OR. if (branchIsAnd) { if (trueBranch) { if (!improveTypesAtTest(ins->toPhi()->getOperand(0), true, test)) @@ -3592,37 +3588,26 @@ IonBuilder::improveTypesAtTest(MDefinition *ins, bool trueBranch, MTest *test) TemporaryTypeSet *oldType = ins->resultTypeSet(); TemporaryTypeSet *type; - // Decide either to set or filter. + // Decide either to set or remove. if (trueBranch) { - // Filter undefined/null. - if (!ins->mightBeType(MIRType_Undefined) && - !ins->mightBeType(MIRType_Null)) - { - return true; - } - uint32_t flags = types::TYPE_FLAG_UNDEFINED | types::TYPE_FLAG_NULL; - types::TemporaryTypeSet remove(flags, static_cast(nullptr)); - type = types::TypeSet::removeSet(oldType, &remove, alloc_->lifoAlloc()); + TemporaryTypeSet remove; + remove.addType(TypeSet::UndefinedType(), alloc_->lifoAlloc()); + remove.addType(TypeSet::NullType(), alloc_->lifoAlloc()); + type = TypeSet::removeSet(oldType, &remove, alloc_->lifoAlloc()); } else { - // According to the standards, we cannot filter out: Strings, - // Int32, Double, Booleans, Objects (if they emulate undefined) - uint32_t flags = TYPE_FLAG_PRIMITIVE; + TemporaryTypeSet base; + base.addType(TypeSet::UndefinedType(), alloc_->lifoAlloc()); // ToBoolean(undefined) == false + base.addType(TypeSet::NullType(), alloc_->lifoAlloc()); // ToBoolean(null) == false + base.addType(TypeSet::BooleanType(), alloc_->lifoAlloc()); // ToBoolean(false) == false + base.addType(TypeSet::Int32Type(), alloc_->lifoAlloc()); // ToBoolean(0) == false + base.addType(TypeSet::DoubleType(), alloc_->lifoAlloc()); // ToBoolean(0.0) == false + base.addType(TypeSet::StringType(), alloc_->lifoAlloc()); // ToBoolean("") == false // If the typeset does emulate undefined, then we cannot filter out // objects. if (oldType->maybeEmulatesUndefined(constraints())) - flags |= TYPE_FLAG_ANYOBJECT; + base.addType(TypeSet::AnyObjectType(), alloc_->lifoAlloc()); - // Only intersect the typesets if it will generate a more narrow - // typeset. The first part takes care of primitives and AnyObject, - // while the second line specific (type)objects. - if (!oldType->hasAnyFlag(~flags & TYPE_FLAG_BASE_MASK) && - (oldType->maybeEmulatesUndefined(constraints()) || !oldType->maybeObject())) - { - return true; - } - - TemporaryTypeSet base(flags, static_cast(nullptr)); type = TypeSet::intersectSets(&base, oldType, alloc_->lifoAlloc()); } diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index e6f62f520e5b..c463d5c4036d 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -771,7 +771,7 @@ TypeSet::removeSet(TemporaryTypeSet *input, TemporaryTypeSet *removal, LifoAlloc uint32_t flags = input->baseFlags() & ~removal->baseFlags(); TemporaryTypeSet *res = - alloc->new_(flags, static_cast(nullptr)); + alloc->new_(flags, static_cast(nullptr)); if (!res) return nullptr; @@ -783,7 +783,7 @@ TypeSet::removeSet(TemporaryTypeSet *input, TemporaryTypeSet *removal, LifoAlloc if (!input->getObject(i)) continue; - res->addType(Type::ObjectType(input->getObject(i)), alloc); + res->addType(TypeSet::ObjectType(input->getObject(i)), alloc); } return res;