Bug 1546853: Implement mozilla::Variant::addTagToHash. r=froydnj

Define the Variant::addTagToHash method, which perturbs a hash value according
to the variant's current alternative's tag. This makes it easier to avoid
collisions in variants in which different alternatives might hash similarly.

Tests included.

Differential Revision: https://phabricator.services.mozilla.com/D28768

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jim Blandy 2019-04-25 14:03:40 +00:00
Родитель dc4531ece2
Коммит 52031426cb
2 изменённых файлов: 42 добавлений и 0 удалений

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

@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/FunctionTypeTraits.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
@ -759,6 +760,15 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
return Impl::matchN(*this, std::forward<M0>(aM0), std::forward<M1>(aM1),
std::forward<Ms>(aMs)...);
}
/**
* Incorporate the current variant's tag into hashValue.
* Note that this does not hash the actual contents; you must take
* care of that yourself, perhaps by using a match.
*/
mozilla::HashNumber addTagToHash(mozilla::HashNumber hashValue) {
return mozilla::AddToHash(hashValue, tag);
}
};
/*

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

@ -473,6 +473,37 @@ static void testRvalueMatcher() {
MOZ_RELEASE_ASSERT(v.match(Describer()) == Describer::little);
}
static void testAddTagToHash() {
printf("testAddToHash\n");
using V = Variant<uint8_t, uint16_t, uint32_t, uint64_t>;
// We don't know what our hash function is, and these are certainly not all
// true under all hash functions. But they are probably true under almost any
// decent hash function, and our aim is simply to establish that the tag
// *does* influence the hash value.
{
mozilla::HashNumber h8 = V(uint8_t(1)).addTagToHash(0);
mozilla::HashNumber h16 = V(uint16_t(1)).addTagToHash(0);
mozilla::HashNumber h32 = V(uint32_t(1)).addTagToHash(0);
mozilla::HashNumber h64 = V(uint64_t(1)).addTagToHash(0);
MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64);
MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64);
MOZ_RELEASE_ASSERT(h32 != h64);
}
{
mozilla::HashNumber h8 = V(uint8_t(1)).addTagToHash(0x124356);
mozilla::HashNumber h16 = V(uint16_t(1)).addTagToHash(0x124356);
mozilla::HashNumber h32 = V(uint32_t(1)).addTagToHash(0x124356);
mozilla::HashNumber h64 = V(uint64_t(1)).addTagToHash(0x124356);
MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64);
MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64);
MOZ_RELEASE_ASSERT(h32 != h64);
}
}
int main() {
testDetails();
testSimple();
@ -487,6 +518,7 @@ int main() {
testMatchingLambda();
testMatchingLambdas();
testRvalueMatcher();
testAddTagToHash();
printf("TestVariant OK!\n");
return 0;