Commit 37d733ba authored by Patrick Thier's avatar Patrick Thier Committed by V8 LUCI CQ

Implicitly retreive hash from string forwarding table

When a name's hash is a forwarding index, HasHashCode() and hash() now
implicitly retreive the hash from the string forwarding table.

Bug: v8:12957
Change-Id: Ibb278df16b1ae6a54c7cbe757c65d3a5210168e9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3827880
Commit-Queue: Patrick Thier <pthier@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82525}
parent 5c4267d5
......@@ -11,6 +11,7 @@
#include "src/objects/name.h"
#include "src/objects/primitive-heap-object-inl.h"
#include "src/objects/string-inl.h"
#include "src/objects/string-table.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -126,7 +127,6 @@ uint32_t Name::CreateHashFieldValue(uint32_t hash, HashFieldType type) {
return HashBits::encode(hash & HashBits::kMax) |
HashFieldTypeBits::encode(type);
}
// static
uint32_t Name::CreateInternalizedForwardingIndex(uint32_t index) {
return ForwardingIndexValueBits::encode(index) |
......@@ -143,7 +143,10 @@ uint32_t Name::CreateExternalForwardingIndex(uint32_t index) {
HashFieldTypeBits::encode(HashFieldType::kForwardingIndex);
}
bool Name::HasHashCode() const { return IsHashFieldComputed(raw_hash_field()); }
bool Name::HasHashCode() const {
uint32_t field = raw_hash_field();
return IsHashFieldComputed(field) || IsForwardingIndex(field);
}
bool Name::HasForwardingIndex(AcquireLoadTag) const {
return IsForwardingIndex(raw_hash_field(kAcquireLoad));
}
......@@ -154,10 +157,22 @@ bool Name::HasExternalForwardingIndex(AcquireLoadTag) const {
return IsExternalForwardingIndex(raw_hash_field(kAcquireLoad));
}
uint32_t Name::GetRawHashFromForwardingTable(uint32_t raw_hash) const {
DCHECK(IsForwardingIndex(raw_hash));
// TODO(pthier): Add parameter for isolate so we don't need to calculate it.
Isolate* isolate = GetIsolateFromWritableObject(*this);
const int index = ForwardingIndexValueBits::decode(raw_hash);
return isolate->string_forwarding_table()->GetRawHash(isolate, index);
}
uint32_t Name::EnsureRawHash() {
// Fast case: has hash code already been computed?
uint32_t field = raw_hash_field();
uint32_t field = raw_hash_field(kAcquireLoad);
if (IsHashFieldComputed(field)) return field;
// The computed hash might be stored in the forwarding table.
if (V8_UNLIKELY(IsForwardingIndex(field))) {
return GetRawHashFromForwardingTable(field);
}
// Slow case: compute hash code and set it. Has to be a string.
return String::cast(*this).ComputeAndSetRawHash();
}
......@@ -165,8 +180,12 @@ uint32_t Name::EnsureRawHash() {
uint32_t Name::EnsureRawHash(
const SharedStringAccessGuardIfNeeded& access_guard) {
// Fast case: has hash code already been computed?
uint32_t field = raw_hash_field();
uint32_t field = raw_hash_field(kAcquireLoad);
if (IsHashFieldComputed(field)) return field;
// The computed hash might be stored in the forwarding table.
if (V8_UNLIKELY(IsForwardingIndex(field))) {
return GetRawHashFromForwardingTable(field);
}
// Slow case: compute hash code and set it. Has to be a string.
return String::cast(*this).ComputeAndSetRawHash(access_guard);
}
......@@ -194,17 +213,24 @@ void Name::set_raw_hash_field_if_empty(uint32_t hash) {
}
uint32_t Name::hash() const {
uint32_t field = raw_hash_field();
DCHECK(IsHashFieldComputed(field));
uint32_t field = raw_hash_field(kAcquireLoad);
if (V8_UNLIKELY(!IsHashFieldComputed(field))) {
DCHECK(IsForwardingIndex(field));
return HashBits::decode(GetRawHashFromForwardingTable(field));
}
return HashBits::decode(field);
}
bool Name::TryGetHash(uint32_t* hash) const {
uint32_t field = raw_hash_field();
uint32_t field = raw_hash_field(kAcquireLoad);
if (IsHashFieldComputed(field)) {
*hash = HashBits::decode(field);
return true;
}
if (V8_UNLIKELY(IsForwardingIndex(field))) {
*hash = HashBits::decode(GetRawHashFromForwardingTable(field));
return true;
}
return false;
}
......
......@@ -204,6 +204,9 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
static inline uint32_t CreateExternalForwardingIndex(uint32_t index);
TQ_OBJECT_CONSTRUCTORS(Name)
private:
inline uint32_t GetRawHashFromForwardingTable(uint32_t raw_hash) const;
};
// ES6 symbols.
......
......@@ -855,6 +855,14 @@ class StringForwardingTable::Block {
return String::cast(Get(isolate, IndexOfForwardString(index)));
}
uint32_t GetRawHash(Isolate* isolate, int index) const {
DCHECK_LT(index, capacity());
String internalized = GetForwardString(isolate, index);
uint32_t raw_hash = internalized.raw_hash_field();
DCHECK(Name::IsHashFieldComputed(raw_hash));
return raw_hash;
}
void IterateElements(RootVisitor* visitor, int up_to_index) {
OffHeapObjectSlot first_slot = slot(0);
OffHeapObjectSlot end_slot = slot(IndexOfOriginalString(up_to_index));
......@@ -1096,6 +1104,15 @@ Address StringForwardingTable::GetForwardStringAddress(Isolate* isolate,
.ptr();
}
uint32_t StringForwardingTable::GetRawHash(Isolate* isolate, int index) const {
CHECK_LT(index, Size());
uint32_t index_in_block;
const uint32_t block = BlockForIndex(index, &index_in_block);
Block* data =
blocks_.load(std::memory_order_acquire)->LoadBlock(block, kAcquireLoad);
return data->GetRawHash(isolate, index_in_block);
}
void StringForwardingTable::IterateElements(RootVisitor* visitor) {
isolate_->heap()->safepoint()->AssertActive();
DCHECK_NE(isolate_->heap()->gc_state(), Heap::NOT_IN_GC);
......
......@@ -121,6 +121,7 @@ class StringForwardingTable {
int Add(Isolate* isolate, String string, String forward_to);
String GetForwardString(Isolate* isolate, int index) const;
static Address GetForwardStringAddress(Isolate* isolate, int index);
V8_EXPORT_PRIVATE uint32_t GetRawHash(Isolate* isolate, int index) const;
void IterateElements(RootVisitor* visitor);
void Reset();
void UpdateAfterEvacuation();
......
......@@ -1511,18 +1511,6 @@ uint32_t String::ComputeAndSetRawHash(
// same. The raw hash field is stored with relaxed ordering.
DCHECK_IMPLIES(!FLAG_shared_string_table, !HasHashCode());
uint32_t field = raw_hash_field(kAcquireLoad);
if (Name::IsInternalizedForwardingIndex(field)) {
// Get the real hash from the forwarded string.
Isolate* isolate = GetIsolateFromWritableObject(*this);
const int forward_index = Name::ForwardingIndexValueBits::decode(field);
String internalized = isolate->string_forwarding_table()->GetForwardString(
isolate, forward_index);
uint32_t hash = internalized.raw_hash_field();
DCHECK(IsHashFieldComputed(hash));
return hash;
}
// Store the hash code in the object.
uint64_t seed = HashSeed(GetReadOnlyRoots());
size_t start = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment