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:
parent
88338c2d99
commit
d5686a74d5
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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).")
|
||||
|
27
src/flags.cc
27
src/flags.cc
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user