[runtime] Rename Name::Hash() to Name::EnsureHash()

... and use Name::hash() where the hash is expected to be computed.
In particular, when we are dealing with internalized strings or symbols.

Bug: v8:11074
Change-Id: Ida22f134fee0ddf2c9b962d1bcca6aa0b632af5f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2529451
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71200}
This commit is contained in:
Igor Sheludko 2020-11-13 18:00:46 +01:00 committed by Commit Bot
parent c85ab364d6
commit 93d49c39d8
27 changed files with 78 additions and 68 deletions

View File

@ -5135,7 +5135,7 @@ MaybeLocal<String> v8::Function::FunctionProtoToString(Local<Context> context) {
int Name::GetIdentityHash() { int Name::GetIdentityHash() {
auto self = Utils::OpenHandle(this); auto self = Utils::OpenHandle(this);
return static_cast<int>(self->Hash()); return static_cast<int>(self->EnsureHash());
} }
int String::Length() const { int String::Length() const {

View File

@ -77,7 +77,11 @@ class AstRawString final : public ZoneObject {
// For storing AstRawStrings in a hash map. // For storing AstRawStrings in a hash map.
uint32_t raw_hash_field() const { return raw_hash_field_; } uint32_t raw_hash_field() const { return raw_hash_field_; }
uint32_t Hash() const { return raw_hash_field_ >> Name::kHashShift; } uint32_t Hash() const {
// Hash field must be computed.
DCHECK_EQ(raw_hash_field_ & Name::kHashNotComputedMask, 0);
return raw_hash_field_ >> Name::kHashShift;
}
// This function can be called after internalizing. // This function can be called after internalizing.
V8_INLINE Handle<String> string() const { V8_INLINE Handle<String> string() const {

View File

@ -278,7 +278,7 @@ void HeapObject::VerifyHeapPointer(Isolate* isolate, Object p) {
void Symbol::SymbolVerify(Isolate* isolate) { void Symbol::SymbolVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::SymbolVerify(*this, isolate); TorqueGeneratedClassVerifiers::SymbolVerify(*this, isolate);
CHECK(HasHashCode()); CHECK(HasHashCode());
CHECK_GT(Hash(), 0); CHECK_GT(hash(), 0);
CHECK(description().IsUndefined(isolate) || description().IsString()); CHECK(description().IsUndefined(isolate) || description().IsString());
CHECK_IMPLIES(IsPrivateName(), IsPrivate()); CHECK_IMPLIES(IsPrivateName(), IsPrivate());
CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName()); CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName());
@ -938,7 +938,13 @@ void Oddball::OddballVerify(Isolate* isolate) {
} }
} }
USE_TORQUE_VERIFIER(PropertyCell) void PropertyCell::PropertyCellVerify(Isolate* isolate) {
// TODO(torque): replace with USE_TORQUE_VERIFIER(PropertyCell) once
// it supports UniqueName type.
TorqueGeneratedClassVerifiers::PropertyCellVerify(*this, isolate);
CHECK(name().IsUniqueName());
}
void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) { void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) {
CHECK(IsCodeDataContainer()); CHECK(IsCodeDataContainer());

View File

@ -1026,8 +1026,8 @@ void Heap::CreateInitialObjects() {
AllocationType::kReadOnly)); AllocationType::kReadOnly));
// Evaluate the hash values which will then be cached in the strings. // Evaluate the hash values which will then be cached in the strings.
isolate()->factory()->zero_string()->Hash(); isolate()->factory()->zero_string()->EnsureHash();
isolate()->factory()->one_string()->Hash(); isolate()->factory()->one_string()->EnsureHash();
// Initialize builtins constants table. // Initialize builtins constants table.
set_builtins_constants_table(roots.empty_fixed_array()); set_builtins_constants_table(roots.empty_fixed_array());

View File

@ -71,7 +71,6 @@ bool CommonStubCacheChecks(StubCache* stub_cache, Name name, Map map,
DCHECK(!Heap::InYoungGeneration(name)); DCHECK(!Heap::InYoungGeneration(name));
DCHECK(!Heap::InYoungGeneration(handler)); DCHECK(!Heap::InYoungGeneration(handler));
DCHECK(name.IsUniqueName()); DCHECK(name.IsUniqueName());
DCHECK(name.HasHashCode());
if (handler->ptr() != kNullAddress) DCHECK(IC::IsHandler(handler)); if (handler->ptr() != kNullAddress) DCHECK(IC::IsHandler(handler));
return true; return true;
} }

View File

@ -192,7 +192,7 @@ void Log::MessageBuilder::AppendSymbolName(Symbol symbol) {
AppendSymbolNameDetails(String::cast(symbol.description()), false); AppendSymbolNameDetails(String::cast(symbol.description()), false);
os << "\" "; os << "\" ";
} }
os << "hash " << std::hex << symbol.Hash() << std::dec << ")"; os << "hash " << std::hex << symbol.hash() << std::dec << ")";
} }
void Log::MessageBuilder::AppendSymbolNameDetails(String str, void Log::MessageBuilder::AppendSymbolNameDetails(String str,

View File

@ -124,7 +124,7 @@ class CodeEventLogger::NameBuffer {
AppendBytes("\" "); AppendBytes("\" ");
} }
AppendBytes("hash "); AppendBytes("hash ");
AppendHex(symbol.Hash()); AppendHex(symbol.hash());
AppendByte(')'); AppendByte(')');
} }
} }
@ -232,7 +232,7 @@ void CodeEventLogger::CodeCreateEvent(LogEventsAndTags tag,
name_buffer_->AppendString(String::cast(*script_name)); name_buffer_->AppendString(String::cast(*script_name));
} else { } else {
name_buffer_->AppendBytes("symbol(hash "); name_buffer_->AppendBytes("symbol(hash ");
name_buffer_->AppendHex(Name::cast(*script_name).Hash()); name_buffer_->AppendHex(Name::cast(*script_name).hash());
name_buffer_->AppendByte(')'); name_buffer_->AppendByte(')');
} }
name_buffer_->AppendByte(':'); name_buffer_->AppendByte(':');

View File

@ -27,14 +27,14 @@ NEVER_READ_ONLY_SPACE_IMPL(CompilationCacheTable)
CAST_ACCESSOR(CompilationCacheTable) CAST_ACCESSOR(CompilationCacheTable)
uint32_t CompilationCacheShape::RegExpHash(String string, Smi flags) { uint32_t CompilationCacheShape::RegExpHash(String string, Smi flags) {
return string.Hash() + flags.value(); return string.EnsureHash() + flags.value();
} }
uint32_t CompilationCacheShape::StringSharedHash(String source, uint32_t CompilationCacheShape::StringSharedHash(String source,
SharedFunctionInfo shared, SharedFunctionInfo shared,
LanguageMode language_mode, LanguageMode language_mode,
int position) { int position) {
uint32_t hash = source.Hash(); uint32_t hash = source.EnsureHash();
if (shared.HasSourceCode()) { if (shared.HasSourceCode()) {
// Instead of using the SharedFunctionInfo pointer in the hash // Instead of using the SharedFunctionInfo pointer in the hash
// code computation, we use a combination of the hash of the // code computation, we use a combination of the hash of the
@ -42,7 +42,7 @@ uint32_t CompilationCacheShape::StringSharedHash(String source,
// We do this to ensure that the cache entries can survive garbage // We do this to ensure that the cache entries can survive garbage
// collection. // collection.
Script script(Script::cast(shared.script())); Script script(Script::cast(shared.script()));
hash ^= String::cast(script.source()).Hash(); hash ^= String::cast(script.source()).EnsureHash();
STATIC_ASSERT(LanguageModeSize == 2); STATIC_ASSERT(LanguageModeSize == 2);
if (is_strict(language_mode)) hash ^= 0x8000; if (is_strict(language_mode)) hash ^= 0x8000;
hash += position; hash += position;

View File

@ -223,7 +223,7 @@ void DescriptorArray::Append(Descriptor* desc) {
set_number_of_descriptors(descriptor_number + 1); set_number_of_descriptors(descriptor_number + 1);
Set(InternalIndex(descriptor_number), desc); Set(InternalIndex(descriptor_number), desc);
uint32_t hash = desc->GetKey()->Hash(); uint32_t hash = desc->GetKey()->hash();
int insertion; int insertion;

View File

@ -279,11 +279,13 @@ bool NameDictionaryShape::IsMatch(Handle<Name> key, Object other) {
} }
uint32_t NameDictionaryShape::Hash(ReadOnlyRoots roots, Handle<Name> key) { uint32_t NameDictionaryShape::Hash(ReadOnlyRoots roots, Handle<Name> key) {
return key->Hash(); DCHECK(key->IsUniqueName());
return key->hash();
} }
uint32_t NameDictionaryShape::HashForObject(ReadOnlyRoots roots, Object other) { uint32_t NameDictionaryShape::HashForObject(ReadOnlyRoots roots, Object other) {
return Name::cast(other).Hash(); DCHECK(other.IsUniqueName());
return Name::cast(other).hash();
} }
bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object other) { bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object other) {
@ -294,7 +296,7 @@ bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object other) {
uint32_t GlobalDictionaryShape::HashForObject(ReadOnlyRoots roots, uint32_t GlobalDictionaryShape::HashForObject(ReadOnlyRoots roots,
Object other) { Object other) {
return PropertyCell::cast(other).name().Hash(); return PropertyCell::cast(other).name().hash();
} }
Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate, Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,

View File

@ -2389,7 +2389,7 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
DCHECK(name->IsUniqueName()); DCHECK(name->IsUniqueName());
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
uint32_t hash = name->Hash(); uint32_t hash = name->hash();
if (object->IsJSGlobalObject()) { if (object->IsJSGlobalObject()) {
Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object); Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object);

View File

@ -1251,7 +1251,7 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
int unchecked_result_keys_size = 0; int unchecked_result_keys_size = 0;
for (int i = 0; i < trap_result->length(); ++i) { for (int i = 0; i < trap_result->length(); ++i) {
Handle<Name> key(Name::cast(trap_result->get(i)), isolate_); Handle<Name> key(Name::cast(trap_result->get(i)), isolate_);
auto entry = unchecked_result_keys.LookupOrInsert(key, key->Hash()); auto entry = unchecked_result_keys.LookupOrInsert(key, key->EnsureHash());
if (entry->value != kPresent) { if (entry->value != kPresent) {
entry->value = kPresent; entry->value = kPresent;
unchecked_result_keys_size++; unchecked_result_keys_size++;
@ -1313,7 +1313,7 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
Handle<Name> key(Name::cast(raw_key), isolate_); Handle<Name> key(Name::cast(raw_key), isolate_);
// 19a. If key is not an element of uncheckedResultKeys, throw a // 19a. If key is not an element of uncheckedResultKeys, throw a
// TypeError exception. // TypeError exception.
auto found = unchecked_result_keys.Lookup(key, key->Hash()); auto found = unchecked_result_keys.Lookup(key, key->hash());
if (found == nullptr || found->value == kGone) { if (found == nullptr || found->value == kGone) {
isolate_->Throw(*isolate_->factory()->NewTypeError( isolate_->Throw(*isolate_->factory()->NewTypeError(
MessageTemplate::kProxyOwnKeysMissing, key)); MessageTemplate::kProxyOwnKeysMissing, key));
@ -1334,7 +1334,7 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
Handle<Name> key(Name::cast(raw_key), isolate_); Handle<Name> key(Name::cast(raw_key), isolate_);
// 21a. If key is not an element of uncheckedResultKeys, throw a // 21a. If key is not an element of uncheckedResultKeys, throw a
// TypeError exception. // TypeError exception.
auto found = unchecked_result_keys.Lookup(key, key->Hash()); auto found = unchecked_result_keys.Lookup(key, key->hash());
if (found == nullptr || found->value == kGone) { if (found == nullptr || found->value == kGone) {
isolate_->Throw(*isolate_->factory()->NewTypeError( isolate_->Throw(*isolate_->factory()->NewTypeError(
MessageTemplate::kProxyOwnKeysMissing, key)); MessageTemplate::kProxyOwnKeysMissing, key));

View File

@ -5,10 +5,10 @@
#ifndef V8_OBJECTS_NAME_INL_H_ #ifndef V8_OBJECTS_NAME_INL_H_
#define V8_OBJECTS_NAME_INL_H_ #define V8_OBJECTS_NAME_INL_H_
#include "src/objects/name.h" #include "src/base/logging.h"
#include "src/heap/heap-write-barrier-inl.h" #include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/map-inl.h" #include "src/objects/map-inl.h"
#include "src/objects/name.h"
#include "src/objects/primitive-heap-object-inl.h" #include "src/objects/primitive-heap-object-inl.h"
// Has to be the last include (doesn't have include guards): // Has to be the last include (doesn't have include guards):
@ -60,6 +60,7 @@ DEF_GETTER(Name, IsUniqueName, bool) {
bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) != bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) !=
(kStringTag | kNotInternalizedTag); (kStringTag | kNotInternalizedTag);
SLOW_DCHECK(result == HeapObject::IsUniqueName()); SLOW_DCHECK(result == HeapObject::IsUniqueName());
DCHECK_IMPLIES(result, HasHashCode());
return result; return result;
} }
@ -82,13 +83,13 @@ bool Name::Equals(Isolate* isolate, Handle<Name> one, Handle<Name> two) {
Handle<String>::cast(two)); Handle<String>::cast(two));
} }
bool Name::IsHashFieldComputed(uint32_t field) { bool Name::IsHashFieldComputed(uint32_t raw_hash_field) {
return (field & kHashNotComputedMask) == 0; return (raw_hash_field & kHashNotComputedMask) == 0;
} }
bool Name::HasHashCode() { return IsHashFieldComputed(raw_hash_field()); } bool Name::HasHashCode() const { return IsHashFieldComputed(raw_hash_field()); }
uint32_t Name::Hash() { uint32_t Name::EnsureHash() {
// Fast case: has hash code already been computed? // Fast case: has hash code already been computed?
uint32_t field = raw_hash_field(); uint32_t field = raw_hash_field();
if (IsHashFieldComputed(field)) return field >> kHashShift; if (IsHashFieldComputed(field)) return field >> kHashShift;

View File

@ -23,12 +23,11 @@ namespace internal {
class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> { class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
public: public:
// Tells whether the hash code has been computed. // Tells whether the hash code has been computed.
inline bool HasHashCode(); inline bool HasHashCode() const;
// Returns a hash value used for the property table. Ensures that the hash // Returns a hash value used for the property table. Ensures that the hash
// value is computed. // value is computed.
// TODO(ishell): rename to EnsureHash(). inline uint32_t EnsureHash();
inline uint32_t Hash();
// Returns a hash value used for the property table (same as Hash()), assumes // Returns a hash value used for the property table (same as Hash()), assumes
// the hash is already computed. // the hash is already computed.
@ -139,8 +138,7 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
static const int kEmptyHashField = static const int kEmptyHashField =
kIsNotIntegerIndexMask | kHashNotComputedMask; kIsNotIntegerIndexMask | kHashNotComputedMask;
protected: static inline bool IsHashFieldComputed(uint32_t raw_hash_field);
static inline bool IsHashFieldComputed(uint32_t field);
TQ_OBJECT_CONSTRUCTORS(Name) TQ_OBJECT_CONSTRUCTORS(Name)
}; };

View File

@ -1044,11 +1044,11 @@ Object Object::GetSimpleHash(Object object) {
return Smi::FromInt(hash & Smi::kMaxValue); return Smi::FromInt(hash & Smi::kMaxValue);
} }
if (object.IsName()) { if (object.IsName()) {
uint32_t hash = Name::cast(object).Hash(); uint32_t hash = Name::cast(object).EnsureHash();
return Smi::FromInt(hash); return Smi::FromInt(hash);
} }
if (object.IsOddball()) { if (object.IsOddball()) {
uint32_t hash = Oddball::cast(object).to_string().Hash(); uint32_t hash = Oddball::cast(object).to_string().EnsureHash();
return Smi::FromInt(hash); return Smi::FromInt(hash);
} }
if (object.IsBigInt()) { if (object.IsBigInt()) {

View File

@ -2432,7 +2432,7 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) {
case INTERNALIZED_STRING_TYPE: case INTERNALIZED_STRING_TYPE:
// Rare case, rehash read-only space strings before they are sealed. // Rare case, rehash read-only space strings before they are sealed.
DCHECK(ReadOnlyHeap::Contains(*this)); DCHECK(ReadOnlyHeap::Contains(*this));
String::cast(*this).Hash(); String::cast(*this).EnsureHash();
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();

View File

@ -421,7 +421,7 @@ InternalIndex OrderedNameDictionary::FindEntry(LocalIsolate* isolate,
return InternalIndex::NotFound(); return InternalIndex::NotFound();
} }
int raw_entry = HashToEntryRaw(raw_key.Hash()); int raw_entry = HashToEntryRaw(raw_key.hash());
while (raw_entry != kNotFound) { while (raw_entry != kNotFound) {
InternalIndex entry(raw_entry); InternalIndex entry(raw_entry);
Object candidate_key = KeyAt(entry); Object candidate_key = KeyAt(entry);
@ -474,6 +474,7 @@ template <typename LocalIsolate>
MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Add( MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Add(
LocalIsolate* isolate, Handle<OrderedNameDictionary> table, LocalIsolate* isolate, Handle<OrderedNameDictionary> table,
Handle<Name> key, Handle<Object> value, PropertyDetails details) { Handle<Name> key, Handle<Object> value, PropertyDetails details) {
DCHECK(key->IsUniqueName());
DCHECK(table->FindEntry(isolate, *key).is_not_found()); DCHECK(table->FindEntry(isolate, *key).is_not_found());
MaybeHandle<OrderedNameDictionary> table_candidate = MaybeHandle<OrderedNameDictionary> table_candidate =
@ -482,7 +483,7 @@ MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Add(
return table_candidate; return table_candidate;
} }
// Read the existing bucket values. // Read the existing bucket values.
int hash = key->Hash(); int hash = key->hash();
int bucket = table->HashToBucket(hash); int bucket = table->HashToBucket(hash);
int previous_entry = table->HashToEntryRaw(hash); int previous_entry = table->HashToEntryRaw(hash);
int nof = table->NumberOfElements(); int nof = table->NumberOfElements();
@ -834,7 +835,7 @@ SmallOrderedHashTable<SmallOrderedNameDictionary>::FindEntry(Isolate* isolate,
DCHECK(key.IsUniqueName()); DCHECK(key.IsUniqueName());
Name raw_key = Name::cast(key); Name raw_key = Name::cast(key);
int raw_entry = HashToFirstEntry(raw_key.Hash()); int raw_entry = HashToFirstEntry(raw_key.hash());
// Walk the chain in the bucket to find the key. // Walk the chain in the bucket to find the key.
while (raw_entry != kNotFound) { while (raw_entry != kNotFound) {
@ -850,6 +851,7 @@ SmallOrderedHashTable<SmallOrderedNameDictionary>::FindEntry(Isolate* isolate,
MaybeHandle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Add( MaybeHandle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Add(
Isolate* isolate, Handle<SmallOrderedNameDictionary> table, Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
Handle<Name> key, Handle<Object> value, PropertyDetails details) { Handle<Name> key, Handle<Object> value, PropertyDetails details) {
DCHECK(key->IsUniqueName());
DCHECK(table->FindEntry(isolate, *key).is_not_found()); DCHECK(table->FindEntry(isolate, *key).is_not_found());
if (table->UsedCapacity() >= table->Capacity()) { if (table->UsedCapacity() >= table->Capacity()) {
@ -863,7 +865,7 @@ MaybeHandle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Add(
int nof = table->NumberOfElements(); int nof = table->NumberOfElements();
// Read the existing bucket values. // Read the existing bucket values.
int hash = key->Hash(); int hash = key->hash();
int bucket = table->HashToBucket(hash); int bucket = table->HashToBucket(hash);
int previous_entry = table->HashToFirstEntry(hash); int previous_entry = table->HashToFirstEntry(hash);

View File

@ -19,7 +19,7 @@ namespace internal {
struct StringHandleHash { struct StringHandleHash {
V8_INLINE size_t operator()(Handle<String> string) const { V8_INLINE size_t operator()(Handle<String> string) const {
return string->Hash(); return string->EnsureHash();
} }
}; };

View File

@ -26,11 +26,11 @@ bool StringSetShape::IsMatch(String key, Object value) {
} }
uint32_t StringSetShape::Hash(ReadOnlyRoots roots, String key) { uint32_t StringSetShape::Hash(ReadOnlyRoots roots, String key) {
return key.Hash(); return key.EnsureHash();
} }
uint32_t StringSetShape::HashForObject(ReadOnlyRoots roots, Object object) { uint32_t StringSetShape::HashForObject(ReadOnlyRoots roots, Object object) {
return String::cast(object).Hash(); return String::cast(object).EnsureHash();
} }
} // namespace internal } // namespace internal

View File

@ -237,7 +237,7 @@ std::unique_ptr<StringTable::Data> StringTable::Data::Resize(
Object element = data->Get(isolate, i); Object element = data->Get(isolate, i);
if (element == empty_element() || element == deleted_element()) continue; if (element == empty_element() || element == deleted_element()) continue;
String string = String::cast(element); String string = String::cast(element);
uint32_t hash = string.Hash(); uint32_t hash = string.hash();
InternalIndex insertion_index = new_data->FindInsertionEntry(isolate, hash); InternalIndex insertion_index = new_data->FindInsertionEntry(isolate, hash);
new_data->Set(insertion_index, string); new_data->Set(insertion_index, string);
} }
@ -354,7 +354,7 @@ class InternalizedStringKey final : public StringTableKey {
DCHECK(!string->IsInternalizedString()); DCHECK(!string->IsInternalizedString());
DCHECK(string->IsFlat()); DCHECK(string->IsFlat());
// Make sure hash_field is computed. // Make sure hash_field is computed.
string->Hash(); string->EnsureHash();
set_raw_hash_field(string->raw_hash_field()); set_raw_hash_field(string->raw_hash_field());
} }

View File

@ -206,7 +206,8 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
self.AllocateExternalPointerEntries(isolate); self.AllocateExternalPointerEntries(isolate);
self.SetResource(isolate, resource); self.SetResource(isolate, resource);
isolate->heap()->RegisterExternalString(*this); isolate->heap()->RegisterExternalString(*this);
if (is_internalized) self.Hash(); // Force regeneration of the hash value. // Force regeneration of the hash value.
if (is_internalized) self.EnsureHash();
return true; return true;
} }
@ -282,7 +283,8 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
self.AllocateExternalPointerEntries(isolate); self.AllocateExternalPointerEntries(isolate);
self.SetResource(isolate, resource); self.SetResource(isolate, resource);
isolate->heap()->RegisterExternalString(*this); isolate->heap()->RegisterExternalString(*this);
if (is_internalized) self.Hash(); // Force regeneration of the hash value. // Force regeneration of the hash value.
if (is_internalized) self.EnsureHash();
return true; return true;
} }
@ -515,9 +517,8 @@ Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) {
// Update the hash field to speed up sequential convertions. // Update the hash field to speed up sequential convertions.
uint32_t raw_hash_field = StringHasher::MakeArrayIndexHash(d, len); uint32_t raw_hash_field = StringHasher::MakeArrayIndexHash(d, len);
#ifdef DEBUG #ifdef DEBUG
subject->Hash(); // Force hash calculation. subject->EnsureHash(); // Force hash calculation.
DCHECK_EQ(static_cast<int>(subject->raw_hash_field()), DCHECK_EQ(subject->raw_hash_field(), raw_hash_field);
static_cast<int>(raw_hash_field));
#endif #endif
subject->set_raw_hash_field(raw_hash_field); subject->set_raw_hash_field(raw_hash_field);
} }
@ -813,7 +814,7 @@ bool String::SlowEquals(String other) {
if (HasHashCode() && other.HasHashCode()) { if (HasHashCode() && other.HasHashCode()) {
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
if (FLAG_enable_slow_asserts) { if (FLAG_enable_slow_asserts) {
if (Hash() != other.Hash()) { if (hash() != other.hash()) {
bool found_difference = false; bool found_difference = false;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (Get(i) != other.Get(i)) { if (Get(i) != other.Get(i)) {
@ -825,7 +826,7 @@ bool String::SlowEquals(String other) {
} }
} }
#endif #endif
if (Hash() != other.Hash()) return false; if (hash() != other.hash()) return false;
} }
// We know the strings are both non-empty. Compare the first chars // We know the strings are both non-empty. Compare the first chars
@ -864,7 +865,7 @@ bool String::SlowEquals(Isolate* isolate, Handle<String> one,
if (one->HasHashCode() && two->HasHashCode()) { if (one->HasHashCode() && two->HasHashCode()) {
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
if (FLAG_enable_slow_asserts) { if (FLAG_enable_slow_asserts) {
if (one->Hash() != two->Hash()) { if (one->hash() != two->hash()) {
bool found_difference = false; bool found_difference = false;
for (int i = 0; i < one_length; i++) { for (int i = 0; i < one_length; i++) {
if (one->Get(i) != two->Get(i)) { if (one->Get(i) != two->Get(i)) {
@ -876,7 +877,7 @@ bool String::SlowEquals(Isolate* isolate, Handle<String> one,
} }
} }
#endif #endif
if (one->Hash() != two->Hash()) return false; if (one->hash() != two->hash()) return false;
} }
// We know the strings are both non-empty. Compare the first chars // We know the strings are both non-empty. Compare the first chars
@ -1417,7 +1418,7 @@ bool String::SlowAsArrayIndex(uint32_t* index) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
int length = this->length(); int length = this->length();
if (length <= kMaxCachedArrayIndexLength) { if (length <= kMaxCachedArrayIndexLength) {
Hash(); // Force computation of hash code. EnsureHash(); // Force computation of hash code.
uint32_t field = raw_hash_field(); uint32_t field = raw_hash_field();
if ((field & kIsNotIntegerIndexMask) != 0) return false; if ((field & kIsNotIntegerIndexMask) != 0) return false;
*index = ArrayIndexValueBits::decode(field); *index = ArrayIndexValueBits::decode(field);
@ -1432,7 +1433,7 @@ bool String::SlowAsIntegerIndex(size_t* index) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
int length = this->length(); int length = this->length();
if (length <= kMaxCachedArrayIndexLength) { if (length <= kMaxCachedArrayIndexLength) {
Hash(); // Force computation of hash code. EnsureHash(); // Force computation of hash code.
uint32_t field = raw_hash_field(); uint32_t field = raw_hash_field();
if ((field & kIsNotIntegerIndexMask) != 0) return false; if ((field & kIsNotIntegerIndexMask) != 0) return false;
*index = ArrayIndexValueBits::decode(field); *index = ArrayIndexValueBits::decode(field);

View File

@ -188,9 +188,6 @@ int TransitionArray::SearchSpecial(Symbol symbol, int* out_insertion_index) {
int TransitionArray::SearchName(Name name, int* out_insertion_index) { int TransitionArray::SearchName(Name name, int* out_insertion_index) {
DCHECK(name.IsUniqueName()); DCHECK(name.IsUniqueName());
// The name is taken from DescriptorArray, so it must already has a computed
// hash.
DCHECK(name.HasHashCode());
return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(), return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
out_insertion_index); out_insertion_index);
} }

View File

@ -1123,7 +1123,7 @@ Object RegExpResultsCache::Lookup(Heap* heap, String key_string,
cache = heap->regexp_multiple_cache(); cache = heap->regexp_multiple_cache();
} }
uint32_t hash = key_string.Hash(); uint32_t hash = key_string.hash();
uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
~(kArrayEntriesPerCacheEntry - 1)); ~(kArrayEntriesPerCacheEntry - 1));
if (cache.get(index + kStringOffset) != key_string || if (cache.get(index + kStringOffset) != key_string ||
@ -1158,7 +1158,7 @@ void RegExpResultsCache::Enter(Isolate* isolate, Handle<String> key_string,
cache = factory->regexp_multiple_cache(); cache = factory->regexp_multiple_cache();
} }
uint32_t hash = key_string->Hash(); uint32_t hash = key_string->hash();
uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) & uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
~(kArrayEntriesPerCacheEntry - 1)); ~(kArrayEntriesPerCacheEntry - 1));
if (cache->get(index + kStringOffset) == Smi::zero()) { if (cache->get(index + kStringOffset) == Smi::zero()) {

View File

@ -321,7 +321,7 @@ Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) {
uint32_t StringTableInsertionKey::ComputeRawHashField(String string) { uint32_t StringTableInsertionKey::ComputeRawHashField(String string) {
// Make sure raw_hash_field() is computed. // Make sure raw_hash_field() is computed.
string.Hash(); string.EnsureHash();
return string.raw_hash_field(); return string.raw_hash_field();
} }

View File

@ -1011,15 +1011,14 @@ TEST(StringAllocation) {
Handle<String> one_byte_sym = Handle<String> one_byte_sym =
factory->InternalizeString(OneByteVector(one_byte, length)); factory->InternalizeString(OneByteVector(one_byte, length));
CHECK_EQ(length, one_byte_sym->length()); CHECK_EQ(length, one_byte_sym->length());
CHECK(one_byte_sym->HasHashCode());
Handle<String> non_one_byte_str = Handle<String> non_one_byte_str =
factory->NewStringFromUtf8(Vector<const char>(non_one_byte, 3 * length)) factory->NewStringFromUtf8(Vector<const char>(non_one_byte, 3 * length))
.ToHandleChecked(); .ToHandleChecked();
non_one_byte_str->Hash();
CHECK_EQ(length, non_one_byte_str->length()); CHECK_EQ(length, non_one_byte_str->length());
Handle<String> one_byte_str = Handle<String> one_byte_str =
factory->NewStringFromUtf8(Vector<const char>(one_byte, length)) factory->NewStringFromUtf8(Vector<const char>(one_byte, length))
.ToHandleChecked(); .ToHandleChecked();
one_byte_str->Hash();
CHECK_EQ(length, one_byte_str->length()); CHECK_EQ(length, one_byte_str->length());
DeleteArray(non_one_byte); DeleteArray(non_one_byte);
DeleteArray(one_byte); DeleteArray(one_byte);

View File

@ -1829,11 +1829,11 @@ void TestString(i::Isolate* isolate, const IndexData& data) {
size_t index; size_t index;
CHECK(s->AsIntegerIndex(&index)); CHECK(s->AsIntegerIndex(&index));
CHECK_EQ(data.integer_index, index); CHECK_EQ(data.integer_index, index);
s->Hash(); s->EnsureHash();
CHECK_EQ(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask); CHECK_EQ(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask);
CHECK(s->HasHashCode()); CHECK(s->HasHashCode());
} }
if (!s->HasHashCode()) s->Hash(); if (!s->HasHashCode()) s->EnsureHash();
CHECK(s->HasHashCode()); CHECK(s->HasHashCode());
if (!data.is_integer_index) { if (!data.is_integer_index) {
CHECK_NE(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask); CHECK_NE(0, s->raw_hash_field() & String::kIsNotIntegerIndexMask);
@ -1850,11 +1850,11 @@ TEST(HashArrayIndexStrings) {
CHECK_EQ(StringHasher::MakeArrayIndexHash(0 /* value */, 1 /* length */) >> CHECK_EQ(StringHasher::MakeArrayIndexHash(0 /* value */, 1 /* length */) >>
Name::kHashShift, Name::kHashShift,
isolate->factory()->zero_string()->Hash()); isolate->factory()->zero_string()->hash());
CHECK_EQ(StringHasher::MakeArrayIndexHash(1 /* value */, 1 /* length */) >> CHECK_EQ(StringHasher::MakeArrayIndexHash(1 /* value */, 1 /* length */) >>
Name::kHashShift, Name::kHashShift,
isolate->factory()->one_string()->Hash()); isolate->factory()->one_string()->hash());
IndexData tests[] = { IndexData tests[] = {
{"", false, 0, false, 0}, {"", false, 0, false, 0},

View File

@ -54,7 +54,8 @@ TEST(Create) {
CHECK(symbols[i]->IsName()); CHECK(symbols[i]->IsName());
CHECK(symbols[i]->IsSymbol()); CHECK(symbols[i]->IsSymbol());
CHECK(symbols[i]->HasHashCode()); CHECK(symbols[i]->HasHashCode());
CHECK_GT(symbols[i]->Hash(), 0u); CHECK(symbols[i]->IsUniqueName());
CHECK_GT(symbols[i]->hash(), 0u);
os << Brief(*symbols[i]) << "\n"; os << Brief(*symbols[i]) << "\n";
#if OBJECT_PRINT #if OBJECT_PRINT
symbols[i]->Print(os); symbols[i]->Print(os);