Backed out changeset e2d3d7bb9d1f (bug 1457728) for build bustages at build\build\src\xpcom\ds\nsTArray.h(807) on a CLOSED TREE

This commit is contained in:
Andreea Pavel 2018-07-07 22:55:25 +03:00
Родитель 8751f930ce
Коммит be1d77cb98
3 изменённых файлов: 60 добавлений и 155 удалений

Просмотреть файл

@ -28,6 +28,21 @@ CompareIIDs(const nsIID& aA, const nsIID &aB)
return memcmp((void*)&aA.m0, (void*)&aB.m0, IID_SIZE);
}
struct IIDComparator
{
bool
LessThan(const nsIID& aA, const nsIID &aB) const
{
return CompareIIDs(aA, aB) < 0;
}
bool
Equals(const nsIID& aA, const nsIID &aB) const
{
return aA.Equals(aB);
}
};
/* static */
MozQueryInterface*
ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningStringOrIID>& aInterfaces, ErrorResult& aRv)
@ -83,10 +98,10 @@ ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningString
ifaces.AppendElement(*iid->GetID());
}
MOZ_ASSERT(!ifaces.Contains(NS_GET_IID(nsISupports), CompareIIDs));
MOZ_ASSERT(!ifaces.Contains(NS_GET_IID(nsISupports), IIDComparator()));
ifaces.AppendElement(NS_GET_IID(nsISupports));
ifaces.Sort(CompareIIDs);
ifaces.Sort(IIDComparator());
return new MozQueryInterface(std::move(ifaces));
}
@ -94,7 +109,12 @@ ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningString
bool
MozQueryInterface::QueriesTo(const nsIID& aIID) const
{
return mInterfaces.ContainsSorted(aIID, CompareIIDs);
// We use BinarySearchIf here because nsTArray::ContainsSorted requires
// twice as many comparisons.
size_t result;
return BinarySearchIf(mInterfaces, 0, mInterfaces.Length(),
[&] (const nsIID& aOther) { return CompareIIDs(aIID, aOther); },
&result);
}
void

Просмотреть файл

@ -772,93 +772,43 @@ struct nsTArray_TypedBase<JS::Heap<E>, Derived>
namespace detail {
// These helpers allow us to differentiate between tri-state comparator
// functions and classes with LessThan() and Equal() methods. If an object, when
// called as a function with two instances of our element type, returns an int,
// we treat it as a tri-state comparator.
//
// T is the type of the comparator object we want to check. U is the array
// element type that we'll be comparing.
//
// V is never passed, and is only used to allow us to specialize on the return
// value of the comparator function.
template <typename T, typename U, typename V = int>
struct IsCompareMethod : mozilla::FalseType {};
template <typename T, typename U>
struct IsCompareMethod<T, U, decltype(mozilla::DeclVal<T>()(mozilla::DeclVal<U>(), mozilla::DeclVal<U>()))>
: mozilla::TrueType {};
// These two wrappers allow us to use either a tri-state comparator, or an
// object with Equals() and LessThan() methods interchangeably. They provide a
// tri-state Compare() method, and Equals() method, and a LessThan() method.
//
// Depending on the type of the underlying comparator, they either pass these
// through directly, or synthesize them from the methods available on the
// comparator.
//
// Callers should always use the most-specific of these methods that match their
// purpose.
// Comparator wrapper for a tri-state comparator function
template <typename T, typename U, bool IsCompare = IsCompareMethod<T, U>::value>
struct CompareWrapper
template<class Item, class Comparator>
struct ItemComparatorEq
{
MOZ_IMPLICIT CompareWrapper(const T& aComparator)
: mComparator(aComparator)
const Item& mItem;
const Comparator& mComp;
ItemComparatorEq(const Item& aItem, const Comparator& aComp)
: mItem(aItem)
, mComp(aComp)
{}
template <typename A, typename B>
int Compare(A& aLeft, B& aRight) const
{
return mComparator(aLeft, aRight);
}
template <typename A, typename B>
bool Equals(A& aLeft, B& aRight) const
{
return Compare(aLeft, aRight) == 0;
}
template <typename A, typename B>
bool LessThan(A& aLeft, B& aRight) const
{
return Compare(aLeft, aRight) < 0;
}
const T& mComparator;
};
// Comparator wrapper for a class with Equals() and LessThan() methods.
template <typename T, typename U>
struct CompareWrapper<T, U, false>
{
MOZ_IMPLICIT CompareWrapper(const T& aComparator)
: mComparator(aComparator)
{}
template <typename A, typename B>
int Compare(A& aLeft, B& aRight) const
{
if (Equals(aLeft, aRight)) {
template<class T>
int operator()(const T& aElement) const {
if (mComp.Equals(aElement, mItem)) {
return 0;
}
return LessThan(aLeft, aRight) ? -1 : 1;
}
template <typename A, typename B>
bool Equals(A& aLeft, B& aRight) const
{
return mComparator.Equals(aLeft, aRight);
return mComp.LessThan(aElement, mItem) ? 1 : -1;
}
};
template <typename A, typename B>
bool LessThan(A& aLeft, B& aRight) const
{
return mComparator.LessThan(aLeft, aRight);
template<class Item, class Comparator>
struct ItemComparatorFirstElementGT
{
const Item& mItem;
const Comparator& mComp;
ItemComparatorFirstElementGT(const Item& aItem, const Comparator& aComp)
: mItem(aItem)
, mComp(aComp)
{}
template<class T>
int operator()(const T& aElement) const {
if (mComp.LessThan(aElement, mItem) ||
mComp.Equals(aElement, mItem)) {
return 1;
} else {
return -1;
}
}
const T& mComparator;
};
} // namespace detail
@ -1217,12 +1167,10 @@ public:
index_type IndexOf(const Item& aItem, index_type aStart,
const Comparator& aComp) const
{
::detail::CompareWrapper<Comparator, Item> comp(aComp);
const elem_type* iter = Elements() + aStart;
const elem_type* iend = Elements() + Length();
for (; iter != iend; ++iter) {
if (comp.Equals(*iter, aItem)) {
if (aComp.Equals(*iter, aItem)) {
return index_type(iter - Elements());
}
}
@ -1252,13 +1200,11 @@ public:
index_type LastIndexOf(const Item& aItem, index_type aStart,
const Comparator& aComp) const
{
::detail::CompareWrapper<Comparator, Item> comp(aComp);
size_type endOffset = aStart >= Length() ? Length() : aStart + 1;
const elem_type* iend = Elements() - 1;
const elem_type* iter = iend + endOffset;
for (; iter != iend; --iter) {
if (comp.Equals(*iter, aItem)) {
if (aComp.Equals(*iter, aItem)) {
return index_type(iter - Elements());
}
}
@ -1290,20 +1236,10 @@ public:
index_type BinaryIndexOf(const Item& aItem, const Comparator& aComp) const
{
using mozilla::BinarySearchIf;
::detail::CompareWrapper<Comparator, Item> comp(aComp);
typedef ::detail::ItemComparatorEq<Item, Comparator> Cmp;
size_t index;
bool found = BinarySearchIf(
*this, 0, Length(),
// Note: We pass the Compare() args here in reverse order and negate the
// results for compatibility reasons. Some existing callers use Equals()
// functions with first arguments which match aElement but not aItem, or
// second arguments that match aItem but not aElement. To accommodate
// those callers, we preserve the argument order of the older version of
// this API. These callers, however, should be fixed, and this special
// case removed.
[&] (const elem_type& aElement) { return -comp.Compare(aElement, aItem); },
&index);
bool found = BinarySearchIf(*this, 0, Length(), Cmp(aItem, aComp), &index);
return found ? index : NoIndex;
}
@ -1598,12 +1534,10 @@ public:
const Comparator& aComp) const
{
using mozilla::BinarySearchIf;
::detail::CompareWrapper<Comparator, Item> comp(aComp);
typedef ::detail::ItemComparatorFirstElementGT<Item, Comparator> Cmp;
size_t index;
BinarySearchIf(*this, 0, Length(),
[&] (const elem_type& aElement) { return comp.Compare(aElement, aItem) <= 0 ? 1 : -1; },
&index);
BinarySearchIf(*this, 0, Length(), Cmp(aItem, aComp), &index);
return index;
}
@ -2099,7 +2033,7 @@ public:
const Comparator* c = reinterpret_cast<const Comparator*>(aData);
const elem_type* a = static_cast<const elem_type*>(aE1);
const elem_type* b = static_cast<const elem_type*>(aE2);
return c->Compare(*a, *b);
return c->LessThan(*a, *b) ? -1 : (c->Equals(*a, *b) ? 0 : 1);
}
// This method sorts the elements of the array. It uses the LessThan
@ -2108,10 +2042,8 @@ public:
template<class Comparator>
void Sort(const Comparator& aComp)
{
::detail::CompareWrapper<Comparator, elem_type> comp(aComp);
NS_QuickSort(Elements(), Length(), sizeof(elem_type),
Compare<decltype(comp)>, &comp);
Compare<Comparator>, const_cast<Comparator*>(&aComp));
}
// A variation on the Sort method defined above that assumes that

Просмотреть файл

@ -1039,51 +1039,4 @@ TEST(TArray, test_SetLengthAndRetainStorage_no_ctor) {
#undef RPAREN
}
template <typename Comparator>
bool
TestCompareMethods(const Comparator& aComp)
{
nsTArray<int> ary({57, 4, 16, 17, 3, 5, 96, 12});
ary.Sort(aComp);
const int sorted[] = {3, 4, 5, 12, 16, 17, 57, 96 };
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sorted); i++) {
if (sorted[i] != ary[i]) {
return false;
}
}
if (!ary.ContainsSorted(5, aComp)) {
return false;
}
if (ary.ContainsSorted(42, aComp)) {
return false;
}
if (ary.BinaryIndexOf(16, aComp) != 4) {
return false;
}
return true;
}
struct IntComparator
{
bool Equals(int aLeft, int aRight) const
{
return aLeft == aRight;
}
bool LessThan(int aLeft, int aRight) const
{
return aLeft < aRight;
}
};
TEST(TArray, test_comparator_objects) {
ASSERT_TRUE(TestCompareMethods(IntComparator()));
ASSERT_TRUE(TestCompareMethods([] (int aLeft, int aRight) { return aLeft - aRight; }));
}
} // namespace TestTArray