Extend hash seed to 64 bits

R=bmeurer@chromium.org, ulan@chromium.org

Bug: chromium:680662
Change-Id: I5e1486ad2a42db2998d5485a0c4e711378678e6c
Reviewed-on: https://chromium-review.googlesource.com/1136034
Reviewed-by: Marja Hölttä <marja@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54460}
This commit is contained in:
Yang Guo 2018-07-16 11:52:50 +02:00 committed by Commit Bot
parent 88338c2d99
commit d5686a74d5
27 changed files with 154 additions and 84 deletions

View File

@ -182,7 +182,7 @@ std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
return result;
}
AstStringConstants::AstStringConstants(Isolate* isolate, uint32_t hash_seed)
AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
: zone_(isolate->allocator(), ZONE_NAME),
string_table_(AstRawString::Compare),
hash_seed_(hash_seed) {

View File

@ -240,14 +240,14 @@ class AstBigInt {
class AstStringConstants final {
public:
AstStringConstants(Isolate* isolate, uint32_t hash_seed);
AstStringConstants(Isolate* isolate, uint64_t hash_seed);
#define F(name, str) \
const AstRawString* name##_string() const { return name##_string_; }
AST_STRING_CONSTANTS(F)
#undef F
uint32_t hash_seed() const { return hash_seed_; }
uint64_t hash_seed() const { return hash_seed_; }
const base::CustomMatcherHashMap* string_table() const {
return &string_table_;
}
@ -255,7 +255,7 @@ class AstStringConstants final {
private:
Zone zone_;
base::CustomMatcherHashMap string_table_;
uint32_t hash_seed_;
uint64_t hash_seed_;
#define F(name, str) AstRawString* name##_string_;
AST_STRING_CONSTANTS(F)
@ -267,7 +267,7 @@ class AstStringConstants final {
class AstValueFactory {
public:
AstValueFactory(Zone* zone, const AstStringConstants* string_constants,
uint32_t hash_seed)
uint64_t hash_seed)
: string_table_(string_constants->string_table()),
strings_(nullptr),
strings_end_(&strings_),
@ -354,7 +354,7 @@ class AstValueFactory {
Zone* zone_;
uint32_t hash_seed_;
uint64_t hash_seed_;
};
} // namespace internal
} // namespace v8

View File

@ -244,8 +244,38 @@ HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR);
HEAP_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_TEST);
#undef HEAP_CONSTANT_TEST
TNode<Int32T> CodeStubAssembler::HashSeed() {
return LoadAndUntagToWord32Root(Heap::kHashSeedRootIndex);
TNode<Int64T> CodeStubAssembler::HashSeed() {
DCHECK(Is64());
TNode<HeapObject> hash_seed_root =
TNode<HeapObject>::UncheckedCast(LoadRoot(Heap::kHashSeedRootIndex));
return TNode<Int64T>::UncheckedCast(LoadObjectField(
hash_seed_root, ByteArray::kHeaderSize, MachineType::Int64()));
}
TNode<Int32T> CodeStubAssembler::HashSeedHigh() {
DCHECK(!Is64());
#ifdef V8_TARGET_BIG_ENDIAN
static int kOffset = 0;
#else
static int kOffset = kInt32Size;
#endif
TNode<HeapObject> hash_seed_root =
TNode<HeapObject>::UncheckedCast(LoadRoot(Heap::kHashSeedRootIndex));
return TNode<Int32T>::UncheckedCast(LoadObjectField(
hash_seed_root, ByteArray::kHeaderSize + kOffset, MachineType::Int32()));
}
TNode<Int32T> CodeStubAssembler::HashSeedLow() {
DCHECK(!Is64());
#ifdef V8_TARGET_BIG_ENDIAN
static int kOffset = kInt32Size;
#else
static int kOffset = 0;
#endif
TNode<HeapObject> hash_seed_root =
TNode<HeapObject>::UncheckedCast(LoadRoot(Heap::kHashSeedRootIndex));
return TNode<Int32T>::UncheckedCast(LoadObjectField(
hash_seed_root, ByteArray::kHeaderSize + kOffset, MachineType::Int32()));
}
Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
@ -7433,7 +7463,14 @@ void CodeStubAssembler::NumberDictionaryLookup(
TNode<IntPtrT> capacity = SmiUntag(GetCapacity<NumberDictionary>(dictionary));
TNode<WordT> mask = IntPtrSub(capacity, IntPtrConstant(1));
TNode<Int32T> int32_seed = HashSeed();
TNode<Int32T> int32_seed;
if (Is64()) {
int32_seed = TruncateInt64ToInt32(HashSeed());
} else {
int32_seed = HashSeedLow();
}
TNode<WordT> hash =
ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed));
Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index);

View File

@ -444,7 +444,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
HEAP_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_TEST)
#undef HEAP_CONSTANT_TEST
TNode<Int32T> HashSeed();
TNode<Int64T> HashSeed();
TNode<Int32T> HashSeedHigh();
TNode<Int32T> HashSeedLow();
Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
TNode<Smi> LanguageModeConstant(LanguageMode mode) {

View File

@ -162,6 +162,7 @@ struct MaybeBoolFlag {
FLAG(MAYBE_BOOL, MaybeBoolFlag, nam, {false COMMA false}, cmt)
#define DEFINE_INT(nam, def, cmt) FLAG(INT, int, nam, def, cmt)
#define DEFINE_UINT(nam, def, cmt) FLAG(UINT, unsigned int, nam, def, cmt)
#define DEFINE_UINT64(nam, def, cmt) FLAG(UINT64, uint64_t, nam, def, cmt)
#define DEFINE_FLOAT(nam, def, cmt) FLAG(FLOAT, double, nam, def, cmt)
#define DEFINE_SIZE_T(nam, def, cmt) FLAG(SIZE_T, size_t, nam, def, cmt)
#define DEFINE_STRING(nam, def, cmt) FLAG(STRING, const char*, nam, def, cmt)
@ -1041,9 +1042,9 @@ DEFINE_BOOL(randomize_hashes, true,
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_BOOL(rehash_snapshot, true,
"rehash strings from the snapshot to override the baked-in seed")
DEFINE_INT(hash_seed, 0,
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_UINT64(hash_seed, 0,
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_INT(random_seed, 0,
"Default seed for initializing random generator "
"(0, the default, means to use system random).")

View File

@ -39,6 +39,7 @@ struct Flag {
TYPE_MAYBE_BOOL,
TYPE_INT,
TYPE_UINT,
TYPE_UINT64,
TYPE_FLOAT,
TYPE_SIZE_T,
TYPE_STRING,
@ -78,6 +79,11 @@ struct Flag {
return reinterpret_cast<unsigned int*>(valptr_);
}
uint64_t* uint64_variable() const {
DCHECK(type_ == TYPE_UINT64);
return reinterpret_cast<uint64_t*>(valptr_);
}
double* float_variable() const {
DCHECK(type_ == TYPE_FLOAT);
return reinterpret_cast<double*>(valptr_);
@ -121,6 +127,11 @@ struct Flag {
return *reinterpret_cast<const unsigned int*>(defptr_);
}
uint64_t uint64_default() const {
DCHECK(type_ == TYPE_UINT64);
return *reinterpret_cast<const uint64_t*>(defptr_);
}
double float_default() const {
DCHECK(type_ == TYPE_FLOAT);
return *reinterpret_cast<const double*>(defptr_);
@ -152,6 +163,8 @@ struct Flag {
return *int_variable() == int_default();
case TYPE_UINT:
return *uint_variable() == uint_default();
case TYPE_UINT64:
return *uint64_variable() == uint64_default();
case TYPE_FLOAT:
return *float_variable() == float_default();
case TYPE_SIZE_T:
@ -184,6 +197,9 @@ struct Flag {
case TYPE_UINT:
*uint_variable() = uint_default();
break;
case TYPE_UINT64:
*uint64_variable() = uint64_default();
break;
case TYPE_FLOAT:
*float_variable() = float_default();
break;
@ -217,6 +233,8 @@ static const char* Type2String(Flag::FlagType type) {
case Flag::TYPE_INT: return "int";
case Flag::TYPE_UINT:
return "uint";
case Flag::TYPE_UINT64:
return "uint64";
case Flag::TYPE_FLOAT: return "float";
case Flag::TYPE_SIZE_T:
return "size_t";
@ -243,6 +261,9 @@ std::ostream& operator<<(std::ostream& os, const Flag& flag) { // NOLINT
case Flag::TYPE_UINT:
os << *flag.uint_variable();
break;
case Flag::TYPE_UINT64:
os << *flag.uint64_variable();
break;
case Flag::TYPE_FLOAT:
os << *flag.float_variable();
break;
@ -464,6 +485,12 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
return_code = j;
}
break;
case Flag::TYPE_UINT64:
if (!TryParseUnsigned(flag, arg, value, &endp,
flag->uint64_variable())) {
return_code = j;
}
break;
case Flag::TYPE_FLOAT:
*flag->float_variable() = strtod(value, &endp);
break;

View File

@ -542,13 +542,13 @@ Oddball* Heap::ToBoolean(bool condition) {
return condition ? roots.true_value() : roots.false_value();
}
uint32_t Heap::HashSeed() {
uint32_t seed = static_cast<uint32_t>(hash_seed()->value());
uint64_t Heap::HashSeed() {
uint64_t seed;
hash_seed()->copy_out(0, reinterpret_cast<byte*>(&seed), kInt64Size);
DCHECK(FLAG_randomize_hashes || seed == 0);
return seed;
}
int Heap::NextScriptId() {
int last_id = last_script_id()->value();
if (last_id == Smi::kMaxValue) last_id = v8::UnboundScript::kNoScriptId;

View File

@ -4656,10 +4656,6 @@ void Heap::SetUp() {
space_[LO_SPACE] = lo_space_ = new LargeObjectSpace(this);
space_[NEW_LO_SPACE] = new_lo_space_ = new NewLargeObjectSpace(this);
// Set up the seed that is used to randomize the string hash function.
DCHECK_EQ(Smi::kZero, hash_seed());
if (FLAG_randomize_hashes) InitializeHashSeed();
for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
i++) {
deferred_counters_[i] = 0;
@ -4717,12 +4713,14 @@ void Heap::SetUp() {
}
void Heap::InitializeHashSeed() {
uint64_t new_hash_seed;
if (FLAG_hash_seed == 0) {
int rnd = isolate()->random_number_generator()->NextInt();
set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
int64_t rnd = isolate()->random_number_generator()->NextInt64();
new_hash_seed = static_cast<uint64_t>(rnd);
} else {
set_hash_seed(Smi::FromInt(FLAG_hash_seed));
new_hash_seed = static_cast<uint64_t>(FLAG_hash_seed);
}
hash_seed()->copy_in(0, reinterpret_cast<byte*>(&new_hash_seed), kInt64Size);
}
void Heap::SetStackLimits() {

View File

@ -652,7 +652,7 @@ class Heap {
void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature);
inline uint32_t HashSeed();
inline uint64_t HashSeed();
inline int NextScriptId();
inline int NextDebuggingId();

View File

@ -621,6 +621,9 @@ void Heap::CreateInitialObjects() {
set_minus_infinity_value(
*factory->NewHeapNumber(-V8_INFINITY, TENURED_READ_ONLY));
set_hash_seed(*factory->NewByteArray(kInt64Size, TENURED));
InitializeHashSeed();
// Allocate cache for single character one byte strings.
set_single_character_string_cache(
*factory->NewFixedArray(String::kMaxOneByteCharCode + 1, TENURED));

View File

@ -833,7 +833,8 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
int position = position_;
uc32 c0 = c0_;
uint32_t running_hash = isolate()->heap()->HashSeed();
uint32_t running_hash =
static_cast<uint32_t>(isolate()->heap()->HashSeed());
uint32_t index = 0;
bool is_array_index = true;

View File

@ -12295,9 +12295,7 @@ uint32_t StringHasher::GetHashField() {
}
}
uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
uint32_t seed,
uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
int* utf16_length_out) {
int vector_length = chars.length();
// Handle some edge cases
@ -17020,7 +17018,7 @@ Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
// algorithm.
class TwoCharHashTableKey : public StringTableKey {
public:
TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint64_t seed)
: StringTableKey(ComputeHashField(c1, c2, seed)), c1_(c1), c2_(c2) {}
bool IsMatch(Object* o) override {
@ -17037,9 +17035,9 @@ class TwoCharHashTableKey : public StringTableKey {
}
private:
uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint32_t seed) {
uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint64_t seed) {
// Char 1.
uint32_t hash = seed;
uint32_t hash = static_cast<uint32_t>(seed);
hash += c1;
hash += hash << 10;
hash ^= hash >> 6;
@ -17238,7 +17236,7 @@ namespace {
class StringTableNoAllocateKey : public StringTableKey {
public:
StringTableNoAllocateKey(String* string, uint32_t seed)
StringTableNoAllocateKey(String* string, uint64_t seed)
: StringTableKey(0), string_(string) {
StringShape shape(string);
one_byte_ = shape.HasOnlyOneByteChars();

View File

@ -195,7 +195,7 @@ Char FlatStringReader::Get(int index) {
template <typename Char>
class SequentialStringKey : public StringTableKey {
public:
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
explicit SequentialStringKey(Vector<const Char> string, uint64_t seed)
: StringTableKey(StringHasher::HashSequentialString<Char>(
string.start(), string.length(), seed)),
string_(string) {}
@ -205,7 +205,7 @@ class SequentialStringKey : public StringTableKey {
class OneByteStringKey : public SequentialStringKey<uint8_t> {
public:
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
OneByteStringKey(Vector<const uint8_t> str, uint64_t seed)
: SequentialStringKey<uint8_t>(str, seed) {}
bool IsMatch(Object* string) override {
@ -251,7 +251,7 @@ class SeqOneByteSubStringKey : public StringTableKey {
class TwoByteStringKey : public SequentialStringKey<uc16> {
public:
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
explicit TwoByteStringKey(Vector<const uc16> str, uint64_t seed)
: SequentialStringKey<uc16>(str, seed) {}
bool IsMatch(Object* string) override {
@ -264,7 +264,7 @@ class TwoByteStringKey : public SequentialStringKey<uc16> {
// Utf8StringKey carries a vector of chars as key.
class Utf8StringKey : public StringTableKey {
public:
explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
explicit Utf8StringKey(Vector<const char> string, uint64_t seed)
: StringTableKey(StringHasher::ComputeUtf8Hash(string, seed, &chars_)),
string_(string) {}

View File

@ -140,8 +140,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
uintptr_t stack_limit() const { return stack_limit_; }
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
uint32_t hash_seed() const { return hash_seed_; }
void set_hash_seed(uint32_t hash_seed) { hash_seed_ = hash_seed; }
uint64_t hash_seed() const { return hash_seed_; }
void set_hash_seed(uint64_t hash_seed) { hash_seed_ = hash_seed; }
int function_flags() const { return function_flags_; }
void set_function_flags(int function_flags) {
@ -258,7 +258,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
DeclarationScope* script_scope_;
UnicodeCache* unicode_cache_;
uintptr_t stack_limit_;
uint32_t hash_seed_;
uint64_t hash_seed_;
// TODO(leszeks): Move any remaining flags used here either to the flags_
// field or to other fields.
int function_flags_;

View File

@ -16,14 +16,14 @@ namespace internal {
HeapProfiler::HeapProfiler(Heap* heap)
: ids_(new HeapObjectsMap(heap)),
names_(new StringsStorage(heap->HashSeed())),
names_(new StringsStorage()),
is_tracking_object_moves_(false) {}
HeapProfiler::~HeapProfiler() = default;
void HeapProfiler::DeleteAllSnapshots() {
snapshots_.clear();
names_.reset(new StringsStorage(heap()->HashSeed()));
names_.reset(new StringsStorage());
}

View File

@ -590,9 +590,7 @@ void CodeMap::Print() {
}
CpuProfilesCollection::CpuProfilesCollection(Isolate* isolate)
: resource_names_(isolate->heap()->HashSeed()),
profiler_(nullptr),
current_profiles_semaphore_(1) {}
: profiler_(nullptr), current_profiles_semaphore_(1) {}
bool CpuProfilesCollection::StartProfiling(const char* title,
bool record_samples,

View File

@ -17,9 +17,7 @@ namespace internal {
ProfilerListener::ProfilerListener(Isolate* isolate,
CodeEventObserver* observer)
: isolate_(isolate),
observer_(observer),
function_and_resource_names_(isolate->heap()->HashSeed()) {}
: isolate_(isolate), observer_(observer) {}
ProfilerListener::~ProfilerListener() = default;

View File

@ -17,8 +17,7 @@ bool StringsStorage::StringsMatch(void* key1, void* key2) {
0;
}
StringsStorage::StringsStorage(uint32_t hash_seed)
: hash_seed_(hash_seed), names_(StringsMatch) {}
StringsStorage::StringsStorage() : names_(StringsMatch) {}
StringsStorage::~StringsStorage() {
for (base::HashMap::Entry* p = names_.Start(); p != nullptr;
@ -108,7 +107,7 @@ const char* StringsStorage::GetConsName(const char* prefix, Name* name) {
}
base::HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
uint32_t hash = StringHasher::HashSequentialString(str, len, hash_seed_);
uint32_t hash = StringHasher::HashSequentialString(str, len, kZeroHashSeed);
return names_.LookupOrInsert(const_cast<char*>(str), hash);
}

View File

@ -20,7 +20,7 @@ class Name;
// forever, even if they disappear from JS heap or external storage.
class V8_EXPORT_PRIVATE StringsStorage {
public:
explicit StringsStorage(uint32_t hash_seed);
StringsStorage();
~StringsStorage();
// Copies the given c-string and stores it, returning the stored copy, or just
@ -45,7 +45,6 @@ class V8_EXPORT_PRIVATE StringsStorage {
PRINTF_FORMAT(2, 0)
const char* GetVFormatted(const char* format, va_list args);
uint32_t hash_seed_;
base::CustomMatcherHashMap names_;
DISALLOW_COPY_AND_ASSIGN(StringsStorage);

View File

@ -254,6 +254,8 @@ namespace internal {
V(Object, deserialize_lazy_handler_wide, DeserializeLazyHandlerWide) \
V(Object, deserialize_lazy_handler_extra_wide, \
DeserializeLazyHandlerExtraWide) \
/* Hash seed */ \
V(ByteArray, hash_seed, HashSeed) \
/* JS Entries */ \
V(Code, js_entry_code, JsEntryCode) \
V(Code, js_construct_entry_code, JsConstructEntryCode) \
@ -269,7 +271,6 @@ namespace internal {
V(Smi, real_stack_limit, RealStackLimit) \
V(Smi, last_script_id, LastScriptId) \
V(Smi, last_debugging_id, LastDebuggingId) \
V(Smi, hash_seed, HashSeed) \
/* To distinguish the function templates, so that we can find them in the */ \
/* function cache of the native context. */ \
V(Smi, next_template_serial_number, NextTemplateSerialNumber) \

View File

@ -12,9 +12,9 @@
namespace v8 {
namespace internal {
StringHasher::StringHasher(int length, uint32_t seed)
StringHasher::StringHasher(int length, uint64_t seed)
: length_(length),
raw_running_hash_(seed),
raw_running_hash_(static_cast<uint32_t>(seed)),
array_index_(0),
is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
is_first_char_(true) {
@ -113,16 +113,16 @@ inline void StringHasher::AddCharacters(const Char* chars, int length) {
template <typename schar>
uint32_t StringHasher::HashSequentialString(const schar* chars, int length,
uint32_t seed) {
uint64_t seed) {
StringHasher hasher(length, seed);
if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
return hasher.GetHashField();
}
IteratingStringHasher::IteratingStringHasher(int len, uint32_t seed)
IteratingStringHasher::IteratingStringHasher(int len, uint64_t seed)
: StringHasher(len, seed) {}
uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) {
uint32_t IteratingStringHasher::Hash(String* string, uint64_t seed) {
IteratingStringHasher hasher(string->length(), seed);
// Nothing to do.
if (hasher.has_trivial_hash()) return hasher.GetHashField();

View File

@ -18,14 +18,14 @@ class Vector;
class V8_EXPORT_PRIVATE StringHasher {
public:
explicit inline StringHasher(int length, uint32_t seed);
explicit inline StringHasher(int length, uint64_t seed);
template <typename schar>
static inline uint32_t HashSequentialString(const schar* chars, int length,
uint32_t seed);
uint64_t seed);
// Reads all the data, even for long strings and computes the utf16 length.
static uint32_t ComputeUtf8Hash(Vector<const char> chars, uint32_t seed,
static uint32_t ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
int* utf16_length_out);
// Calculated hash value for a string consisting of 1 to
@ -74,22 +74,22 @@ class V8_EXPORT_PRIVATE StringHasher {
class IteratingStringHasher : public StringHasher {
public:
static inline uint32_t Hash(String* string, uint32_t seed);
static inline uint32_t Hash(String* string, uint64_t seed);
inline void VisitOneByteString(const uint8_t* chars, int length);
inline void VisitTwoByteString(const uint16_t* chars, int length);
private:
inline IteratingStringHasher(int len, uint32_t seed);
inline IteratingStringHasher(int len, uint64_t seed);
void VisitConsString(ConsString* cons_string);
DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
};
// Useful for std containers that require something ()'able.
struct SeededStringHasher {
explicit SeededStringHasher(uint32_t hashseed) : hashseed_(hashseed) {}
explicit SeededStringHasher(uint64_t hashseed) : hashseed_(hashseed) {}
inline std::size_t operator()(const char* name) const;
uint32_t hashseed_;
uint64_t hashseed_;
};
// Useful for std containers that require something ()'able.

View File

@ -472,13 +472,13 @@ class BitSetComputer {
// ----------------------------------------------------------------------------
// Hash function.
static const uint32_t kZeroHashSeed = 0;
static const uint64_t kZeroHashSeed = 0;
// Thomas Wang, Integer Hash Functions.
// http://www.concentric.net/~Ttwang/tech/inthash.htm
inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
inline uint32_t ComputeIntegerHash(uint32_t key, uint64_t seed) {
uint32_t hash = key;
hash = hash ^ seed;
hash = hash ^ static_cast<uint32_t>(seed);
hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
hash = hash ^ (hash >> 12);
hash = hash + (hash << 2);

View File

@ -5957,7 +5957,7 @@ UNINITIALIZED_TEST(ReinitializeStringHashSeed) {
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
CHECK_EQ(1337 * i,
CHECK_EQ(static_cast<uint64_t>(1337 * i),
reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);

View File

@ -325,25 +325,31 @@ TEST(JSFunction) {
TEST(ComputeIntegerHash) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.Return(m.SmiFromInt32(m.ComputeIntegerHash(m.SmiUntag(m.Parameter(0)),
m.SmiToInt32(m.Parameter(1)))));
TNode<Int32T> int32_seed;
if (m.Is64()) {
int32_seed = m.TruncateInt64ToInt32(m.HashSeed());
} else {
int32_seed = m.HashSeedLow();
}
m.Return(m.SmiFromInt32(
m.ComputeIntegerHash(m.SmiUntag(m.Parameter(0)), int32_seed)));
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
Handle<Smi> hash_seed = isolate->factory()->hash_seed();
base::RandomNumberGenerator rand_gen(FLAG_random_seed);
for (int i = 0; i < 1024; i++) {
int k = rand_gen.NextInt(Smi::kMaxValue);
Handle<Smi> key(Smi::FromInt(k), isolate);
Handle<Object> result = ft.Call(key, hash_seed).ToHandleChecked();
Handle<Object> result = ft.Call(key).ToHandleChecked();
uint32_t hash = ComputeIntegerHash(k, hash_seed->value());
uint32_t hash = ComputeIntegerHash(k, isolate->heap()->HashSeed());
Smi* expected = Smi::FromInt(hash & Smi::kMaxValue);
CHECK_EQ(expected, Smi::cast(*result));
}

View File

@ -3467,7 +3467,8 @@ UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
// Check that no rehashing has been performed.
CHECK_EQ(42, reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
CHECK_EQ(static_cast<uint64_t>(42),
reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
@ -3529,7 +3530,8 @@ UNINITIALIZED_TEST(ReinitializeHashSeedRehashable) {
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
// Check that rehashing has been performed.
CHECK_EQ(1337, reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
CHECK_EQ(static_cast<uint64_t>(1337),
reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);

View File

@ -19,7 +19,7 @@ bool StringEq(const char* left, const char* right) {
}
TEST_F(StringsStorageWithIsolate, GetNameFromString) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
// One char strings are canonical on the v8 heap so use a 2 char string here.
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
@ -40,7 +40,7 @@ TEST_F(StringsStorageWithIsolate, GetNameFromString) {
}
TEST_F(StringsStorageWithIsolate, GetNameFromSymbol) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
Handle<Symbol> symbol = isolate()->factory()->NewSymbol();
const char* stored_symbol = storage.GetName(*symbol);
@ -53,7 +53,7 @@ TEST_F(StringsStorageWithIsolate, GetNameFromSymbol) {
}
TEST_F(StringsStorageWithIsolate, GetConsName) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
@ -65,7 +65,7 @@ TEST_F(StringsStorageWithIsolate, GetConsName) {
}
TEST_F(StringsStorageWithIsolate, GetNameFromInt) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
const char* stored_str = storage.GetName(0);
CHECK(StringEq("0", stored_str));
@ -81,7 +81,7 @@ TEST_F(StringsStorageWithIsolate, GetNameFromInt) {
}
TEST_F(StringsStorageWithIsolate, Format) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
const char* xy = "xy";
const char* stored_str = storage.GetFormatted("%s", xy);
@ -99,7 +99,7 @@ TEST_F(StringsStorageWithIsolate, Format) {
}
TEST_F(StringsStorageWithIsolate, FormatAndGetShareStorage) {
StringsStorage storage(isolate()->heap()->HashSeed());
StringsStorage storage;
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
const char* stored_str = storage.GetName(*str);