Skip to content

Commit

Permalink
Bug 1727422 - Support arbitrary integer keys in nsTHashMap, r=xpcom-r…
Browse files Browse the repository at this point in the history
…eviewers,mccr8

Differential Revision: https://phabricator.services.mozilla.com/D123547
  • Loading branch information
mystor committed Aug 25, 2021
1 parent ef07bb0 commit 6d8a726
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 82 deletions.
1 change: 0 additions & 1 deletion ipc/glue/ProtocolUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ enum {
class MessageLoop;
class PickleIterator;
class nsISerialEventTarget;
class nsUint32HashKey;

namespace mozilla {
class SchedulerGroup;
Expand Down
1 change: 0 additions & 1 deletion widget/nsIWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class nsIContent;
class ViewWrapper;
class nsIScreen;
class nsIRunnable;
class nsUint64HashKey;

namespace mozilla {
class NativeEventData;
Expand Down
78 changes: 24 additions & 54 deletions xpcom/ds/nsHashKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>

#include <type_traits>
#include <utility>

#include "mozilla/HashFunctions.h"
Expand Down Expand Up @@ -186,58 +187,48 @@ class nsCStringHashKey : public PLDHashEntryHdr {
};

/**
* hashkey wrapper using uint32_t KeyType
* hashkey wrapper using integral or enum KeyTypes
*
* @see nsTHashtable::EntryType for specification
*/
class nsUint32HashKey : public PLDHashEntryHdr {
template <typename T,
std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<T>, int> = 0>
class nsIntegralHashKey : public PLDHashEntryHdr {
public:
typedef const uint32_t& KeyType;
typedef const uint32_t* KeyTypePointer;
using KeyType = const T&;
using KeyTypePointer = const T*;

explicit nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsUint32HashKey(nsUint32HashKey&& aOther)
: PLDHashEntryHdr(std::move(aOther)), mValue(std::move(aOther.mValue)) {}
~nsUint32HashKey() = default;
explicit nsIntegralHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsIntegralHashKey(nsIntegralHashKey&& aOther) noexcept
: PLDHashEntryHdr(std::move(aOther)), mValue(aOther.mValue) {}
~nsIntegralHashKey() = default;

KeyType GetKey() const { return mValue; }
bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }

static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) {
return mozilla::HashGeneric(*aKey);
}
enum { ALLOW_MEMMOVE = true };

private:
const uint32_t mValue;
const T mValue;
};

/**
* hashkey wrapper using uint64_t KeyType
* hashkey wrapper using uint32_t KeyType
*
* @see nsTHashtable::EntryType for specification
*/
class nsUint64HashKey : public PLDHashEntryHdr {
public:
typedef const uint64_t& KeyType;
typedef const uint64_t* KeyTypePointer;

explicit nsUint64HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsUint64HashKey(nsUint64HashKey&& aOther)
: PLDHashEntryHdr(std::move(aOther)), mValue(std::move(aOther.mValue)) {}
~nsUint64HashKey() = default;
using nsUint32HashKey = nsIntegralHashKey<uint32_t>;

KeyType GetKey() const { return mValue; }
bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }

static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) {
return PLDHashNumber(*aKey);
}
enum { ALLOW_MEMMOVE = true };

private:
const uint64_t mValue;
};
/**
* hashkey wrapper using uint64_t KeyType
*
* @see nsTHashtable::EntryType for specification
*/
using nsUint64HashKey = nsIntegralHashKey<uint64_t>;

/**
* hashkey wrapper using float KeyType
Expand Down Expand Up @@ -272,28 +263,7 @@ class nsFloatHashKey : public PLDHashEntryHdr {
*
* @see nsTHashtable::EntryType for specification
*/
class IntPtrHashKey : public PLDHashEntryHdr {
public:
typedef const intptr_t& KeyType;
typedef const intptr_t* KeyTypePointer;

explicit IntPtrHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
IntPtrHashKey(IntPtrHashKey&& aOther)
: PLDHashEntryHdr(std::move(aOther)), mValue(aOther.mValue) {}
~IntPtrHashKey() = default;

KeyType GetKey() const { return mValue; }
bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }

static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) {
return mozilla::HashGeneric(*aKey);
}
enum { ALLOW_MEMMOVE = true };

private:
const intptr_t mValue;
};
using IntPtrHashKey = nsIntegralHashKey<intptr_t>;

/**
* hashkey wrapper using nsISupports* KeyType
Expand Down
2 changes: 1 addition & 1 deletion xpcom/ds/nsHashtablesFwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ template <class KeyClass, class ClassType>
using nsRefPtrHashtable = nsRefCountedHashtable<KeyClass, RefPtr<ClassType>>;

namespace mozilla::detail {
template <class KeyType>
template <class KeyType, class = void>
struct nsKeyClass;
} // namespace mozilla::detail

Expand Down
33 changes: 8 additions & 25 deletions xpcom/ds/nsTHashMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,10 @@

namespace mozilla::detail {
template <class KeyType>
struct nsKeyClass {
// Prevent instantiation with an incomplete KeyType, as std::is_base_of_v
// would have undefined behaviour then.
static_assert(sizeof(KeyType) > 0,
"KeyType must be a complete type (unless there's an explicit "
"specialization for nsKeyClass<KeyType>)");
static_assert(std::is_base_of_v<PLDHashEntryHdr, KeyType>,
"KeyType must inherit from PLDHashEntryHdr (unless there's an "
"explicit specialization for nsKeyClass<KeyType>)");

using type = std::conditional_t<std::is_base_of_v<PLDHashEntryHdr, KeyType>,
KeyType, void>;
struct nsKeyClass<
KeyType, std::enable_if_t<sizeof(KeyType) &&
std::is_base_of_v<PLDHashEntryHdr, KeyType>>> {
using type = KeyType;
};

template <typename KeyType>
Expand All @@ -49,19 +41,10 @@ struct nsKeyClass<nsString> {
using type = nsStringHashKey;
};

template <>
struct nsKeyClass<uint32_t> {
using type = nsUint32HashKey;
};

template <>
struct nsKeyClass<uint64_t> {
using type = nsUint64HashKey;
};

template <>
struct nsKeyClass<intptr_t> {
using type = IntPtrHashKey;
template <typename KeyType>
struct nsKeyClass<KeyType, std::enable_if_t<std::is_integral_v<KeyType> ||
std::is_enum_v<KeyType>>> {
using type = nsIntegralHashKey<KeyType>;
};

template <>
Expand Down

0 comments on commit 6d8a726

Please sign in to comment.