[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:
parent
c85ab364d6
commit
93d49c39d8
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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(':');
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
};
|
};
|
||||||
|
@ -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()) {
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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},
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user