diff options
Diffstat (limited to 'deps/v8/src/strings/string-hasher-inl.h')
-rw-r--r-- | deps/v8/src/strings/string-hasher-inl.h | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/deps/v8/src/strings/string-hasher-inl.h b/deps/v8/src/strings/string-hasher-inl.h index b547d0a78d..0c69e6c7ba 100644 --- a/deps/v8/src/strings/string-hasher-inl.h +++ b/deps/v8/src/strings/string-hasher-inl.h @@ -34,32 +34,63 @@ uint32_t StringHasher::GetHashCore(uint32_t running_hash) { uint32_t StringHasher::GetTrivialHash(int length) { DCHECK_GT(length, String::kMaxHashCalcLength); // String hash of a large string is simply the length. - return (length << String::kHashShift) | String::kIsNotArrayIndexMask; + return (static_cast<uint32_t>(length) << String::kHashShift) | + String::kIsNotArrayIndexMask | String::kIsNotIntegerIndexMask; } template <typename schar> uint32_t StringHasher::HashSequentialString(const schar* chars, int length, uint64_t seed) { - // Check whether the string is a valid array index. In that case, compute the - // array index hash. It'll fall through to compute a regular string hash from - // the start if it turns out that the string isn't a valid array index. - if (IsInRange(length, 1, String::kMaxArrayIndexSize)) { + DCHECK_LE(0, length); + DCHECK_IMPLIES(0 < length, chars != nullptr); + if (length >= 1) { if (IsDecimalDigit(chars[0]) && (length == 1 || chars[0] != '0')) { - uint32_t index = chars[0] - '0'; - int i = 1; - do { - if (i == length) { - return MakeArrayIndexHash(index, length); + uint32_t index = 0; + if (length <= String::kMaxArrayIndexSize) { + // Possible array index; try to compute the array index hash. + index = chars[0] - '0'; + int i = 1; + do { + if (i == length) { + return MakeArrayIndexHash(index, length); + } + } while (TryAddIndexChar(&index, chars[i++])); + } + // The following block wouldn't do anything on 32-bit platforms, + // because kMaxArrayIndexSize == kMaxIntegerIndexSize there, and + // if we wanted to compile it everywhere, then {index_big} would + // have to be a {size_t}, which the Mac compiler doesn't like to + // implicitly cast to uint64_t for the {TryAddIndexChar} call. +#if V8_HOST_ARCH_64_BIT + // No "else" here: if the block above was entered and fell through, + // we'll have to take this branch. + if (length <= String::kMaxIntegerIndexSize) { + // Not an array index, but it could still be an integer index. + // Perform a regular hash computation, and additionally check + // if there are non-digit characters. + uint32_t is_integer_index = 0; + uint32_t running_hash = static_cast<uint32_t>(seed); + uint64_t index_big = index; + const schar* end = &chars[length]; + while (chars != end) { + if (is_integer_index == 0 && !TryAddIndexChar(&index_big, *chars)) { + is_integer_index = String::kIsNotIntegerIndexMask; + } + running_hash = AddCharacterCore(running_hash, *chars++); } - } while (TryAddIndexChar(&index, chars[i++])); + return (GetHashCore(running_hash) << String::kHashShift) | + String::kIsNotArrayIndexMask | is_integer_index; + } +#endif + } + // No "else" here: if the first character was a decimal digit, we might + // still have to take this branch. + if (length > String::kMaxHashCalcLength) { + return GetTrivialHash(length); } - } else if (length > String::kMaxHashCalcLength) { - return GetTrivialHash(length); } - // Non-array-index hash. - DCHECK_LE(0, length); - DCHECK_IMPLIES(0 < length, chars != nullptr); + // Non-index hash. uint32_t running_hash = static_cast<uint32_t>(seed); const schar* end = &chars[length]; while (chars != end) { @@ -67,7 +98,7 @@ uint32_t StringHasher::HashSequentialString(const schar* chars, int length, } return (GetHashCore(running_hash) << String::kHashShift) | - String::kIsNotArrayIndexMask; + String::kIsNotArrayIndexMask | String::kIsNotIntegerIndexMask; } std::size_t SeededStringHasher::operator()(const char* name) const { |