summaryrefslogtreecommitdiff
path: root/deps/v8/src/strings/string-hasher-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/strings/string-hasher-inl.h')
-rw-r--r--deps/v8/src/strings/string-hasher-inl.h65
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 {