5 #ifndef V8_STRING_HASHER_INL_H_ 6 #define V8_STRING_HASHER_INL_H_ 8 #include "src/string-hasher.h" 10 #include "src/char-predicates-inl.h" 11 #include "src/objects.h" 12 #include "src/objects/string-inl.h" 13 #include "src/utils-inl.h" 18 StringHasher::StringHasher(
int length, uint64_t seed)
20 raw_running_hash_(static_cast<
uint32_t>(seed)),
22 is_array_index_(IsInRange(length, 1, String::kMaxArrayIndexSize)) {
23 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0);
26 bool StringHasher::has_trivial_hash() {
27 return length_ > String::kMaxHashCalcLength;
32 running_hash += (running_hash << 10);
33 running_hash ^= (running_hash >> 6);
38 running_hash += (running_hash << 3);
39 running_hash ^= (running_hash >> 11);
40 running_hash += (running_hash << 15);
41 int32_t hash =
static_cast<int32_t
>(running_hash & String::kHashBitMask);
42 int32_t mask = (hash - 1) >> 31;
43 return running_hash | (kZeroHash & mask);
46 template <
typename Char>
48 const Char* chars,
int length) {
50 DCHECK_IMPLIES(0 < length, chars !=
nullptr);
51 const Char* end = &chars[length];
52 while (chars != end) {
53 running_hash = AddCharacterCore(running_hash, *chars++);
58 void StringHasher::AddCharacter(uint16_t c) {
61 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
64 bool StringHasher::UpdateIndex(uint16_t c) {
65 DCHECK(is_array_index_);
66 if (!TryAddIndexChar(&array_index_, c)) {
67 is_array_index_ =
false;
70 is_array_index_ = array_index_ != 0 || length_ == 1;
71 return is_array_index_;
74 template <
typename Char>
75 inline void StringHasher::AddCharacters(
const Char* chars,
int length) {
76 DCHECK(
sizeof(Char) == 1 ||
sizeof(Char) == 2);
78 if (is_array_index_) {
79 for (;
i < length;
i++) {
80 AddCharacter(chars[
i]);
81 if (!UpdateIndex(chars[
i])) {
88 ComputeRunningHash(raw_running_hash_, &chars[
i], length -
i);
91 template <
typename s
char>
92 uint32_t StringHasher::HashSequentialString(
const schar* chars,
int length,
95 StringHasher hasher(length, seed);
96 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
97 uint32_t expected = hasher.GetHashField();
103 if (IsInRange(length, 1, String::kMaxArrayIndexSize)) {
104 if (IsDecimalDigit(chars[0]) && (length == 1 || chars[0] !=
'0')) {
109 uint32_t result = MakeArrayIndexHash(index, length);
110 DCHECK_EQ(expected, result);
113 }
while (TryAddIndexChar(&index, chars[
i++]));
115 }
else if (length > String::kMaxHashCalcLength) {
118 (length << String::kHashShift) | String::kIsNotArrayIndexMask;
119 DCHECK_EQ(result, expected);
125 ComputeRunningHash(static_cast<uint32_t>(seed), chars, length);
128 (GetHashCore(hash) << String::kHashShift) | String::kIsNotArrayIndexMask;
129 DCHECK_EQ(result, expected);
133 IteratingStringHasher::IteratingStringHasher(
int len, uint64_t seed)
134 : StringHasher(len, seed) {}
136 uint32_t IteratingStringHasher::Hash(String
string, uint64_t seed) {
137 IteratingStringHasher hasher(string->length(), seed);
139 if (hasher.has_trivial_hash())
return hasher.GetHashField();
140 ConsString cons_string = String::VisitFlat(&hasher,
string);
141 if (cons_string.is_null())
return hasher.GetHashField();
142 hasher.VisitConsString(cons_string);
143 return hasher.GetHashField();
146 void IteratingStringHasher::VisitOneByteString(
const uint8_t* chars,
148 AddCharacters(chars, length);
151 void IteratingStringHasher::VisitTwoByteString(
const uint16_t* chars,
153 AddCharacters(chars, length);
156 std::size_t SeededStringHasher::operator()(
const char* name)
const {
157 return StringHasher::HashSequentialString(
158 name, static_cast<int>(strlen(name)), hashseed_);
164 #endif // V8_STRING_HASHER_INL_H_