Commit c31302d0 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[cleanup] Devirtualize HashForObject on StringTableKey and CodeCacheHashTableKey

Only the CompilationCache doesn't actually specialize the table to the point where it knows how to hash stored keys. This moves the virtual HashForObject down from HashTableKey to CompilationCacheKey, and moves previous virtual implementations to the respective shapes.

Bug: v8:6474
Change-Id: I0a1ae26a224d602d16692d2b09c96a2ab193f07f
Reviewed-on: https://chromium-review.googlesource.com/529110Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45842}
parent ee596af2
...@@ -69,10 +69,6 @@ class AstRawStringInternalizationKey : public HashTableKey { ...@@ -69,10 +69,6 @@ class AstRawStringInternalizationKey : public HashTableKey {
uint32_t Hash() override { return string_->hash() >> Name::kHashShift; } uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
uint32_t HashForObject(Object* key) override {
return String::cast(key)->Hash();
}
Handle<Object> AsHandle(Isolate* isolate) override { Handle<Object> AsHandle(Isolate* isolate) override {
if (string_->is_one_byte()) if (string_->is_one_byte())
return isolate->factory()->NewOneByteInternalizedString( return isolate->factory()->NewOneByteInternalizedString(
......
...@@ -886,10 +886,6 @@ class SequentialStringKey : public HashTableKey { ...@@ -886,10 +886,6 @@ class SequentialStringKey : public HashTableKey {
return result; return result;
} }
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
Vector<const Char> string_; Vector<const Char> string_;
uint32_t hash_field_; uint32_t hash_field_;
uint32_t seed_; uint32_t seed_;
...@@ -936,10 +932,6 @@ class SeqOneByteSubStringKey : public HashTableKey { ...@@ -936,10 +932,6 @@ class SeqOneByteSubStringKey : public HashTableKey {
#pragma warning(pop) #pragma warning(pop)
#endif #endif
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
bool IsMatch(Object* string) override; bool IsMatch(Object* string) override;
Handle<Object> AsHandle(Isolate* isolate) override; Handle<Object> AsHandle(Isolate* isolate) override;
...@@ -980,10 +972,6 @@ class Utf8StringKey : public HashTableKey { ...@@ -980,10 +972,6 @@ class Utf8StringKey : public HashTableKey {
return result; return result;
} }
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
Handle<Object> AsHandle(Isolate* isolate) override { Handle<Object> AsHandle(Isolate* isolate) override {
if (hash_field_ == 0) Hash(); if (hash_field_ == 0) Hash();
return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_, return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
...@@ -3006,6 +2994,10 @@ uint32_t StringSetShape::HashForObject(String* key, Object* object) { ...@@ -3006,6 +2994,10 @@ uint32_t StringSetShape::HashForObject(String* key, Object* object) {
return object->IsString() ? String::cast(object)->Hash() : 0; return object->IsString() ? String::cast(object)->Hash() : 0;
} }
uint32_t StringTableShape::HashForObject(HashTableKey* key, Object* object) {
return String::cast(object)->Hash();
}
bool SeededNumberDictionary::requires_slow_elements() { bool SeededNumberDictionary::requires_slow_elements() {
Object* max_index_object = get(kMaxNumberKeyIndex); Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi()) return false; if (!max_index_object->IsSmi()) return false;
......
...@@ -9751,61 +9751,6 @@ Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) { ...@@ -9751,61 +9751,6 @@ Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
} }
// The key in the code cache hash table consists of the property name and the
// code object. The actual match is on the name and the code flags. If a key
// is created using the flags and not a code object it can only be used for
// lookup not to create a new entry.
class CodeCacheHashTableKey : public HashTableKey {
public:
CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
: name_(name), flags_(flags), code_() {
DCHECK(name_->IsUniqueName());
}
CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
: name_(name), flags_(code->flags()), code_(code) {
DCHECK(name_->IsUniqueName());
}
bool IsMatch(Object* other) override {
DCHECK(other->IsFixedArray());
FixedArray* pair = FixedArray::cast(other);
Name* name = Name::cast(pair->get(0));
Code::Flags flags = Code::cast(pair->get(1))->flags();
if (flags != flags_) return false;
DCHECK(name->IsUniqueName());
return *name_ == name;
}
static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
return name->Hash() ^ flags;
}
uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
uint32_t HashForObject(Object* obj) override {
FixedArray* pair = FixedArray::cast(obj);
Name* name = Name::cast(pair->get(0));
Code* code = Code::cast(pair->get(1));
return NameFlagsHashHelper(name, code->flags());
}
MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
Handle<Code> code = code_.ToHandleChecked();
Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
pair->set(0, *name_);
pair->set(1, *code);
return pair;
}
private:
Handle<Name> name_;
Code::Flags flags_;
// TODO(jkummerow): We should be able to get by without this.
MaybeHandle<Code> code_;
};
Handle<CodeCacheHashTable> CodeCacheHashTable::Put( Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) { Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
CodeCacheHashTableKey key(name, code); CodeCacheHashTableKey key(name, code);
...@@ -15949,7 +15894,7 @@ void Symbol::SymbolShortPrint(std::ostream& os) { ...@@ -15949,7 +15894,7 @@ void Symbol::SymbolShortPrint(std::ostream& os) {
// StringSharedKeys are used as keys in the eval cache. // StringSharedKeys are used as keys in the eval cache.
class StringSharedKey : public HashTableKey { class StringSharedKey : public CompilationCacheKey {
public: public:
// This tuple unambiguously identifies calls to eval() or // This tuple unambiguously identifies calls to eval() or
// CreateDynamicFunction() (such as through the Function() constructor). // CreateDynamicFunction() (such as through the Function() constructor).
...@@ -16247,7 +16192,7 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp, ...@@ -16247,7 +16192,7 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
// RegExpKey carries the source and flags of a regular expression as key. // RegExpKey carries the source and flags of a regular expression as key.
class RegExpKey : public HashTableKey { class RegExpKey : public CompilationCacheKey {
public: public:
RegExpKey(Handle<String> string, JSRegExp::Flags flags) RegExpKey(Handle<String> string, JSRegExp::Flags flags)
: string_(string), flags_(Smi::FromInt(flags)) {} : string_(string), flags_(Smi::FromInt(flags)) {}
...@@ -16322,10 +16267,6 @@ class InternalizedStringKey : public HashTableKey { ...@@ -16322,10 +16267,6 @@ class InternalizedStringKey : public HashTableKey {
uint32_t Hash() override { return string_->Hash(); } uint32_t Hash() override { return string_->Hash(); }
uint32_t HashForObject(Object* other) override {
return String::cast(other)->Hash();
}
Handle<Object> AsHandle(Isolate* isolate) override { Handle<Object> AsHandle(Isolate* isolate) override {
// Internalize the string if possible. // Internalize the string if possible.
MaybeHandle<Map> maybe_map = MaybeHandle<Map> maybe_map =
...@@ -17304,10 +17245,6 @@ class TwoCharHashTableKey : public HashTableKey { ...@@ -17304,10 +17245,6 @@ class TwoCharHashTableKey : public HashTableKey {
} }
uint32_t Hash() override { return hash_; } uint32_t Hash() override { return hash_; }
uint32_t HashForObject(Object* key) override {
if (!key->IsString()) return 0;
return String::cast(key)->Hash();
}
Handle<Object> AsHandle(Isolate* isolate) override { Handle<Object> AsHandle(Isolate* isolate) override {
// The TwoCharHashTableKey is only used for looking in the string // The TwoCharHashTableKey is only used for looking in the string
...@@ -17600,10 +17537,6 @@ class StringTableNoAllocateKey : public HashTableKey { ...@@ -17600,10 +17537,6 @@ class StringTableNoAllocateKey : public HashTableKey {
uint32_t Hash() override { return hash_; } uint32_t Hash() override { return hash_; }
uint32_t HashForObject(Object* key) override {
return String::cast(key)->Hash();
}
MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override { MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -16,7 +16,7 @@ namespace internal { ...@@ -16,7 +16,7 @@ namespace internal {
CAST_ACCESSOR(CodeCacheHashTable) CAST_ACCESSOR(CodeCacheHashTable)
Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate, Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate,
HashTableKey* key) { CodeCacheHashTableKey* key) {
return key->AsHandle(isolate); return key->AsHandle(isolate);
} }
......
...@@ -13,19 +13,73 @@ ...@@ -13,19 +13,73 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CodeCacheHashTableShape : public BaseShape<HashTableKey*> { // The key in the code cache hash table consists of the property name and the
// code object. The actual match is on the name and the code flags. If a key
// is created using the flags and not a code object it can only be used for
// lookup not to create a new entry.
class CodeCacheHashTableKey final {
public: public:
static inline bool IsMatch(HashTableKey* key, Object* value) { CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
: name_(name), flags_(flags), code_() {
DCHECK(name_->IsUniqueName());
}
CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
: name_(name), flags_(code->flags()), code_(code) {
DCHECK(name_->IsUniqueName());
}
bool IsMatch(Object* other) {
DCHECK(other->IsFixedArray());
FixedArray* pair = FixedArray::cast(other);
Name* name = Name::cast(pair->get(0));
Code::Flags flags = Code::cast(pair->get(1))->flags();
if (flags != flags_) return false;
DCHECK(name->IsUniqueName());
return *name_ == name;
}
static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
return name->Hash() ^ flags;
}
uint32_t Hash() { return NameFlagsHashHelper(*name_, flags_); }
MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) {
Handle<Code> code = code_.ToHandleChecked();
Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
pair->set(0, *name_);
pair->set(1, *code);
return pair;
}
private:
Handle<Name> name_;
Code::Flags flags_;
// TODO(jkummerow): We should be able to get by without this.
MaybeHandle<Code> code_;
};
class CodeCacheHashTableShape : public BaseShape<CodeCacheHashTableKey*> {
public:
static inline bool IsMatch(CodeCacheHashTableKey* key, Object* value) {
return key->IsMatch(value); return key->IsMatch(value);
} }
static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); } static inline uint32_t Hash(CodeCacheHashTableKey* key) {
return key->Hash();
}
static inline uint32_t HashForObject(HashTableKey* key, Object* object) { static inline uint32_t HashForObject(CodeCacheHashTableKey* key,
return key->HashForObject(object); Object* object) {
FixedArray* pair = FixedArray::cast(object);
Name* name = Name::cast(pair->get(0));
Code* code = Code::cast(pair->get(1));
return CodeCacheHashTableKey::NameFlagsHashHelper(name, code->flags());
} }
static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); static inline Handle<Object> AsHandle(Isolate* isolate,
CodeCacheHashTableKey* key);
static const int kPrefixSize = 0; static const int kPrefixSize = 0;
// The both the key (name + flags) and value (code object) can be derived from // The both the key (name + flags) and value (code object) can be derived from
......
...@@ -16,7 +16,7 @@ namespace internal { ...@@ -16,7 +16,7 @@ namespace internal {
CAST_ACCESSOR(CompilationCacheTable) CAST_ACCESSOR(CompilationCacheTable)
Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
HashTableKey* key) { CompilationCacheKey* key) {
return key->AsHandle(isolate); return key->AsHandle(isolate);
} }
......
...@@ -13,19 +13,26 @@ ...@@ -13,19 +13,26 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CompilationCacheShape : public BaseShape<HashTableKey*> { class CompilationCacheKey : public HashTableKey {
public: public:
static inline bool IsMatch(HashTableKey* key, Object* value) { virtual uint32_t HashForObject(Object* object) = 0;
};
class CompilationCacheShape : public BaseShape<CompilationCacheKey*> {
public:
static inline bool IsMatch(CompilationCacheKey* key, Object* value) {
return key->IsMatch(value); return key->IsMatch(value);
} }
static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); } static inline uint32_t Hash(CompilationCacheKey* key) { return key->Hash(); }
static inline uint32_t HashForObject(HashTableKey* key, Object* object) { static inline uint32_t HashForObject(CompilationCacheKey* key,
Object* object) {
return key->HashForObject(object); return key->HashForObject(object);
} }
static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); static inline Handle<Object> AsHandle(Isolate* isolate,
CompilationCacheKey* key);
static const int kPrefixSize = 0; static const int kPrefixSize = 0;
static const int kEntrySize = 3; static const int kEntrySize = 3;
......
...@@ -260,8 +260,6 @@ class HashTableKey { ...@@ -260,8 +260,6 @@ class HashTableKey {
virtual bool IsMatch(Object* other) = 0; virtual bool IsMatch(Object* other) = 0;
// Returns the hash value for this key. // Returns the hash value for this key.
virtual uint32_t Hash() = 0; virtual uint32_t Hash() = 0;
// Returns the hash value for object.
virtual uint32_t HashForObject(Object* key) = 0;
// Returns the key object for storing into the hash table. // Returns the key object for storing into the hash table.
MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) = 0; MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) = 0;
// Required. // Required.
......
...@@ -21,9 +21,7 @@ class StringTableShape : public BaseShape<HashTableKey*> { ...@@ -21,9 +21,7 @@ class StringTableShape : public BaseShape<HashTableKey*> {
static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); } static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); }
static inline uint32_t HashForObject(HashTableKey* key, Object* object) { static inline uint32_t HashForObject(HashTableKey* key, Object* object);
return key->HashForObject(object);
}
static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
......
...@@ -284,24 +284,20 @@ void Deserializer::PrintDisassembledCodeObjects() { ...@@ -284,24 +284,20 @@ void Deserializer::PrintDisassembledCodeObjects() {
class StringTableInsertionKey : public HashTableKey { class StringTableInsertionKey : public HashTableKey {
public: public:
explicit StringTableInsertionKey(String* string) explicit StringTableInsertionKey(String* string)
: string_(string), hash_(HashForObject(string)) { : string_(string), hash_(string->Hash()) {
DCHECK(string->IsInternalizedString()); DCHECK(string->IsInternalizedString());
} }
bool IsMatch(Object* string) override { bool IsMatch(Object* string) override {
// We know that all entries in a hash table had their hash keys created. // We know that all entries in a hash table had their hash keys created.
// Use that knowledge to have fast failure. // Use that knowledge to have fast failure.
if (hash_ != HashForObject(string)) return false; if (hash_ != String::cast(string)->Hash()) return false;
// We want to compare the content of two internalized strings here. // We want to compare the content of two internalized strings here.
return string_->SlowEquals(String::cast(string)); return string_->SlowEquals(String::cast(string));
} }
uint32_t Hash() override { return hash_; } uint32_t Hash() override { return hash_; }
uint32_t HashForObject(Object* key) override {
return String::cast(key)->Hash();
}
MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override { MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
return handle(string_, isolate); return handle(string_, isolate);
} }
......
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