Fine-tune cached array indices on strings
When converting a Smi to a String, we can skip the check for a cached array index on the result in case of a number-to-string cache hit. When trying to convert a String back to an index, the inlined fast path can check for a cached index (in addition to checking for a cached known negative). Locally this yields about 5% on the JSTests/Proxies/GetIndex* tests. Bug: chromium:1028021 Change-Id: I117eae01b1ad9c5d107ad7e598464b96dae9a6b9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1943160 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#65299}
This commit is contained in:
parent
7ecb124a67
commit
f33902c05b
@ -3589,15 +3589,25 @@ Handle<String> Factory::SmiToString(Smi number, bool check_cache) {
|
||||
Vector<char> buffer(arr, arraysize(arr));
|
||||
const char* string = IntToCString(number.value(), buffer);
|
||||
|
||||
return NumberToStringCacheSet(handle(number, isolate()), hash, string,
|
||||
check_cache);
|
||||
Handle<String> result = NumberToStringCacheSet(handle(number, isolate()),
|
||||
hash, string, check_cache);
|
||||
// Compute the hash here (rather than letting the caller take care of it) so
|
||||
// that the "cache hit" case above doesn't have to bother with it.
|
||||
STATIC_ASSERT(Smi::kMaxValue <= std::numeric_limits<uint32_t>::max());
|
||||
if (result->hash_field() == String::kEmptyHashField && number.value() >= 0) {
|
||||
uint32_t field = StringHasher::MakeArrayIndexHash(
|
||||
static_cast<uint32_t>(number.value()), result->length());
|
||||
result->set_hash_field(field);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Handle<String> Factory::SizeToString(size_t value, bool check_cache) {
|
||||
Handle<String> result;
|
||||
if (value <= Smi::kMaxValue) {
|
||||
int32_t int32v = static_cast<int32_t>(static_cast<uint32_t>(value));
|
||||
result = SmiToString(Smi::FromInt(int32v), check_cache);
|
||||
// SmiToString sets the hash when needed, we can return immediately.
|
||||
return SmiToString(Smi::FromInt(int32v), check_cache);
|
||||
} else if (value <= kMaxSafeInteger) {
|
||||
// TODO(jkummerow): Refactor the cache to not require Objects as keys.
|
||||
double double_value = static_cast<double>(value);
|
||||
|
@ -773,6 +773,14 @@ void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
|
||||
bool String::AsArrayIndex(uint32_t* index) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint32_t field = hash_field();
|
||||
// The {IsHashFieldComputed} check is not functionally necessary as the
|
||||
// subsequent mask includes it; it's here to make the logic more obvious,
|
||||
// and the compile will fold it away so it doesn't hurt performance.
|
||||
if (IsHashFieldComputed(field) &&
|
||||
(field & kDoesNotContainCachedArrayIndexMask) == 0) {
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
}
|
||||
if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
|
||||
return false;
|
||||
}
|
||||
@ -781,6 +789,14 @@ bool String::AsArrayIndex(uint32_t* index) {
|
||||
|
||||
bool String::AsIntegerIndex(size_t* index) {
|
||||
uint32_t field = hash_field();
|
||||
// The {IsHashFieldComputed} check is not functionally necessary as the
|
||||
// subsequent mask includes it; it's here to make the logic more obvious,
|
||||
// and the compile will fold it away so it doesn't hurt performance.
|
||||
if (IsHashFieldComputed(field) &&
|
||||
(field & kDoesNotContainCachedArrayIndexMask) == 0) {
|
||||
*index = ArrayIndexValueBits::decode(field);
|
||||
return true;
|
||||
}
|
||||
if (IsHashFieldComputed(field) && (field & kIsNotIntegerIndexMask)) {
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user