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

[runtime] Devirtualize CompilationCacheKey::HashForObject

Distinguish the compilation caches instead by the shape of the key (cow fixed
array map meaning eval or script cache). This allows us to remove the odd "key"
argument from Shrink, EnsureCapacity and Rehash.

Bug: v8:6474
Change-Id: Ibcad22813063c3a9050da13dc51359f5b59e1254
Reviewed-on: https://chromium-review.googlesource.com/531184Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45873}
parent 49ecce8a
......@@ -333,12 +333,12 @@ void UncacheTemplateInstantiation(Isolate* isolate, int serial_number,
Handle<UnseededNumberDictionary> cache =
isolate->slow_template_instantiations_cache();
int entry = cache->FindEntry(serial_number);
DCHECK(entry != UnseededNumberDictionary::kNotFound);
DCHECK_NE(UnseededNumberDictionary::kNotFound, entry);
Handle<Object> result =
UnseededNumberDictionary::DeleteProperty(cache, entry);
USE(result);
DCHECK(result->IsTrue(isolate));
auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
auto new_cache = UnseededNumberDictionary::Shrink(cache);
isolate->native_context()->set_slow_template_instantiations_cache(
*new_cache);
}
......
......@@ -204,7 +204,7 @@ class DeletePropertyBaseAssembler : public CodeStubAssembler {
Node* capacity = GetCapacity<NameDictionary>(properties);
GotoIf(SmiGreaterThan(new_nof, SmiShr(capacity, 2)), &shrinking_done);
GotoIf(SmiLessThan(new_nof, SmiConstant(16)), &shrinking_done);
CallRuntime(Runtime::kShrinkPropertyDictionary, context, receiver, name);
CallRuntime(Runtime::kShrinkPropertyDictionary, context, receiver);
Goto(&shrinking_done);
BIND(&shrinking_done);
......
......@@ -1412,12 +1412,10 @@ class DictionaryElementsAccessor
// TODO(verwaest): Remove reliance on index in Shrink.
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(obj->elements()));
uint32_t index = GetIndexForEntryImpl(*dict, entry);
Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
USE(result);
DCHECK(result->IsTrue(dict->GetIsolate()));
Handle<FixedArray> new_elements =
SeededNumberDictionary::Shrink(dict, index);
Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict);
obj->set_elements(*new_elements);
}
......@@ -3707,15 +3705,12 @@ class SlowSloppyArgumentsElementsAccessor
Isolate* isolate = obj->GetIsolate();
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(elements->arguments()), isolate);
// TODO(verwaest): Remove reliance on index in Shrink.
uint32_t index = GetIndexForEntryImpl(*dict, entry);
int length = elements->parameter_map_length();
Handle<Object> result =
SeededNumberDictionary::DeleteProperty(dict, entry - length);
USE(result);
DCHECK(result->IsTrue(isolate));
Handle<FixedArray> new_elements =
SeededNumberDictionary::Shrink(dict, index);
Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict);
elements->set_arguments(*new_elements);
}
......
......@@ -982,8 +982,7 @@ void MarkCompactCollector::Finish() {
}
// The hashing of weak_object_to_code_table is no longer valid.
heap()->weak_object_to_code_table()->Rehash(
heap()->isolate()->factory()->undefined_value());
heap()->weak_object_to_code_table()->Rehash();
// Clear the marking state of live large objects.
heap_->lo_space()->ClearMarkingStateOfLiveObjects();
......
......@@ -2693,15 +2693,15 @@ bool StringSetShape::IsMatch(String* key, Object* value) {
uint32_t StringSetShape::Hash(String* key) { return key->Hash(); }
uint32_t StringSetShape::HashForObject(String* key, Object* object) {
return object->IsString() ? String::cast(object)->Hash() : 0;
uint32_t StringSetShape::HashForObject(Object* object) {
return String::cast(object)->Hash();
}
Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) {
return key->AsHandle(isolate);
}
uint32_t StringTableShape::HashForObject(HashTableKey* key, Object* object) {
uint32_t StringTableShape::HashForObject(Object* object) {
return String::cast(object)->Hash();
}
......@@ -6143,9 +6143,7 @@ uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
return ComputeIntegerHash(key, 0);
}
uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
Object* other) {
uint32_t UnseededNumberDictionaryShape::HashForObject(Object* other) {
DCHECK(other->IsNumber());
return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
}
......@@ -6158,9 +6156,7 @@ uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
return ComputeIntegerHash(key, seed);
}
uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
uint32_t seed,
uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t seed,
Object* other) {
DCHECK(other->IsNumber());
return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
......@@ -6183,8 +6179,7 @@ uint32_t NameDictionaryShape::Hash(Handle<Name> key) {
return key->Hash();
}
uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) {
uint32_t NameDictionaryShape::HashForObject(Object* other) {
return Name::cast(other)->Hash();
}
......@@ -6234,9 +6229,7 @@ uint32_t ObjectHashTableShape::Hash(Handle<Object> key) {
return Smi::cast(key->GetHash())->value();
}
uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key,
Object* other) {
uint32_t ObjectHashTableShape::HashForObject(Object* other) {
return Smi::cast(other->GetHash())->value();
}
......@@ -6246,10 +6239,8 @@ Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
return key;
}
Handle<ObjectHashTable> ObjectHashTable::Shrink(
Handle<ObjectHashTable> table, Handle<Object> key) {
return DerivedHashTable::Shrink(table, key);
Handle<ObjectHashTable> ObjectHashTable::Shrink(Handle<ObjectHashTable> table) {
return DerivedHashTable::Shrink(table);
}
template <int entrysize>
......@@ -6269,10 +6260,8 @@ uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) {
return (uint32_t)(hash & 0xFFFFFFFF);
}
template <int entrysize>
uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key,
Object* other) {
uint32_t WeakHashTableShape<entrysize>::HashForObject(Object* other) {
if (other->IsWeakCell()) other = WeakCell::cast(other)->value();
intptr_t hash = reinterpret_cast<intptr_t>(other);
return (uint32_t)(hash & 0xFFFFFFFF);
......
This diff is collapsed.
......@@ -70,8 +70,7 @@ class CodeCacheHashTableShape : public BaseShape<CodeCacheHashTableKey*> {
return key->Hash();
}
static inline uint32_t HashForObject(CodeCacheHashTableKey* key,
Object* object) {
static inline uint32_t HashForObject(Object* object) {
FixedArray* pair = FixedArray::cast(object);
Name* name = Name::cast(pair->get(0));
Code* code = Code::cast(pair->get(1));
......
......@@ -16,10 +16,53 @@ namespace internal {
CAST_ACCESSOR(CompilationCacheTable)
Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate,
CompilationCacheKey* key) {
HashTableKey* key) {
return key->AsHandle(isolate);
}
uint32_t CompilationCacheShape::RegExpHash(String* string, Smi* flags) {
return string->Hash() + flags->value();
}
uint32_t CompilationCacheShape::StringSharedHash(String* source,
SharedFunctionInfo* shared,
LanguageMode language_mode,
int position) {
uint32_t hash = source->Hash();
if (shared->HasSourceCode()) {
// Instead of using the SharedFunctionInfo pointer in the hash
// code computation, we use a combination of the hash of the
// script source code and the start position of the calling scope.
// We do this to ensure that the cache entries can survive garbage
// collection.
Script* script(Script::cast(shared->script()));
hash ^= String::cast(script->source())->Hash();
STATIC_ASSERT(LANGUAGE_END == 2);
if (is_strict(language_mode)) hash ^= 0x8000;
hash += position;
}
return hash;
}
uint32_t CompilationCacheShape::HashForObject(Object* object) {
if (object->IsNumber()) return static_cast<uint32_t>(object->Number());
FixedArray* val = FixedArray::cast(object);
if (val->map() == val->GetHeap()->fixed_cow_array_map()) {
DCHECK_EQ(4, val->length());
SharedFunctionInfo* shared = SharedFunctionInfo::cast(val->get(0));
String* source = String::cast(val->get(1));
int language_unchecked = Smi::cast(val->get(2))->value();
DCHECK(is_valid_language_mode(language_unchecked));
LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
int position = Smi::cast(val->get(3))->value();
return StringSharedHash(source, shared, language_mode, position);
}
DCHECK_LT(2, val->length());
return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
Smi::cast(val->get(JSRegExp::kFlagsIndex)));
}
} // namespace internal
} // namespace v8
......
......@@ -13,26 +13,24 @@
namespace v8 {
namespace internal {
class CompilationCacheKey : public HashTableKey {
class CompilationCacheShape : public BaseShape<HashTableKey*> {
public:
virtual uint32_t HashForObject(Object* object) = 0;
};
class CompilationCacheShape : public BaseShape<CompilationCacheKey*> {
public:
static inline bool IsMatch(CompilationCacheKey* key, Object* value) {
static inline bool IsMatch(HashTableKey* key, Object* value) {
return key->IsMatch(value);
}
static inline uint32_t Hash(CompilationCacheKey* key) { return key->Hash(); }
static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); }
static inline uint32_t HashForObject(CompilationCacheKey* key,
Object* object) {
return key->HashForObject(object);
}
static inline uint32_t RegExpHash(String* string, Smi* flags);
static inline uint32_t StringSharedHash(String* source,
SharedFunctionInfo* shared,
LanguageMode language_mode,
int position);
static inline uint32_t HashForObject(Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate,
CompilationCacheKey* key);
static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
static const int kPrefixSize = 0;
static const int kEntrySize = 3;
......
......@@ -57,8 +57,8 @@ class Dictionary : public HashTable<Derived, Shape> {
// Attempt to shrink the dictionary after deletion of key.
MUST_USE_RESULT static inline Handle<Derived> Shrink(
Handle<Derived> dictionary, Key key) {
return DerivedHashTable::Shrink(dictionary, key);
Handle<Derived> dictionary) {
return DerivedHashTable::Shrink(dictionary);
}
int NumberOfEnumerableProperties();
......@@ -103,7 +103,7 @@ class Dictionary : public HashTable<Derived, Shape> {
void SetRequiresCopyOnCapacityChange();
// Ensure enough space for n additional elements.
static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key);
static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n);
#ifdef OBJECT_PRINT
// For our gdb macros, we should perhaps change these in the future.
......@@ -181,7 +181,7 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
public:
static inline bool IsMatch(Handle<Name> key, Object* other);
static inline uint32_t Hash(Handle<Name> key);
static inline uint32_t HashForObject(Handle<Name> key, Object* object);
static inline uint32_t HashForObject(Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
......@@ -244,8 +244,7 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape {
static const int kEntrySize = 3;
static inline uint32_t SeededHash(uint32_t key, uint32_t seed);
static inline uint32_t SeededHashForObject(uint32_t key, uint32_t seed,
Object* object);
static inline uint32_t SeededHashForObject(uint32_t seed, Object* object);
};
class UnseededNumberDictionaryShape : public NumberDictionaryShape {
......@@ -254,7 +253,7 @@ class UnseededNumberDictionaryShape : public NumberDictionaryShape {
static const int kEntrySize = 2;
static inline uint32_t Hash(uint32_t key);
static inline uint32_t HashForObject(uint32_t key, Object* object);
static inline uint32_t HashForObject(Object* object);
template <typename Dictionary>
static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) {
......
......@@ -27,16 +27,16 @@ namespace internal {
// - Elements with key == undefined have not been used yet.
// - Elements with key == the_hole have been deleted.
//
// The hash table class is parameterized with a Shape and a Key.
// The hash table class is parameterized with a Shape.
// Shape must be a class with the following interface:
// class ExampleShape {
// public:
// // Tells whether key matches other.
// static bool IsMatch(Key key, Object* other);
// static bool IsMatch(Object* other);
// // Returns the hash value for key.
// static uint32_t Hash(Key key);
// // Returns the hash value for object.
// static uint32_t HashForObject(Key key, Object* object);
// static uint32_t HashForObject(Object* object);
// // Convert key to an object.
// static inline Handle<Object> AsHandle(Isolate* isolate, Key key);
// // The prefix size indicates number of elements in the beginning
......@@ -59,10 +59,10 @@ class BaseShape {
DCHECK(UsesSeed);
return Hash(key);
}
static uint32_t HashForObject(Key key, Object* object) { return 0; }
static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) {
static uint32_t HashForObject(Object* object) { return 0; }
static uint32_t SeededHashForObject(uint32_t seed, Object* object) {
DCHECK(UsesSeed);
return HashForObject(key, object);
return HashForObject(object);
}
static inline Map* GetMap(Isolate* isolate);
};
......@@ -149,11 +149,11 @@ class HashTable : public HashTableBase {
}
}
inline uint32_t HashForObject(Key key, Object* object) {
inline uint32_t HashForObject(Object* object) {
if (Shape::UsesSeed) {
return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object);
return Shape::SeededHashForObject(GetHeap()->HashSeed(), object);
} else {
return Shape::HashForObject(key, object);
return Shape::HashForObject(object);
}
}
......@@ -177,7 +177,7 @@ class HashTable : public HashTableBase {
inline bool Has(Key key);
// Rehashes the table in-place.
void Rehash(Key key);
void Rehash();
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); }
......@@ -213,12 +213,11 @@ class HashTable : public HashTableBase {
uint32_t FindInsertionEntry(uint32_t hash);
// Attempt to shrink hash table after removal of key.
MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table, Key key);
MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table);
// Ensure enough space for n additional elements.
MUST_USE_RESULT static Handle<Derived> EnsureCapacity(
Handle<Derived> table, int n, Key key,
PretenureFlag pretenure = NOT_TENURED);
Handle<Derived> table, int n, PretenureFlag pretenure = NOT_TENURED);
// Returns true if this table has sufficient capacity for adding n elements.
bool HasSufficientCapacityToAdd(int number_of_additional_elements);
......@@ -245,12 +244,12 @@ class HashTable : public HashTableBase {
// Returns _expected_ if one of entries given by the first _probe_ probes is
// equal to _expected_. Otherwise, returns the entry given by the probe
// number _probe_.
uint32_t EntryForProbe(Key key, Object* k, int probe, uint32_t expected);
uint32_t EntryForProbe(Object* k, int probe, uint32_t expected);
void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode);
// Rehashes this hash-table into the new table.
void Rehash(Handle<Derived> new_table, Key key);
void Rehash(Handle<Derived> new_table);
};
// HashTableKey is an abstract superclass for virtual key behavior.
......@@ -270,7 +269,7 @@ class ObjectHashTableShape : public BaseShape<Handle<Object>> {
public:
static inline bool IsMatch(Handle<Object> key, Object* other);
static inline uint32_t Hash(Handle<Object> key);
static inline uint32_t HashForObject(Handle<Object> key, Object* object);
static inline uint32_t HashForObject(Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key);
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
......@@ -287,7 +286,7 @@ class ObjectHashTable
// Attempt to shrink hash table after removal of key.
MUST_USE_RESULT static inline Handle<ObjectHashTable> Shrink(
Handle<ObjectHashTable> table, Handle<Object> key);
Handle<ObjectHashTable> table);
// Looks up the value associated with the given key. The hole value is
// returned in case the key is not present.
......@@ -553,7 +552,7 @@ class WeakHashTableShape : public BaseShape<Handle<Object>> {
public:
static inline bool IsMatch(Handle<Object> key, Object* other);
static inline uint32_t Hash(Handle<Object> key);
static inline uint32_t HashForObject(Handle<Object> key, Object* object);
static inline uint32_t HashForObject(Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key);
static const int kPrefixSize = 0;
static const int kEntrySize = entrysize;
......
......@@ -21,7 +21,7 @@ class StringTableShape : public BaseShape<HashTableKey*> {
static inline uint32_t Hash(HashTableKey* key) { return key->Hash(); }
static inline uint32_t HashForObject(HashTableKey* key, Object* object);
static inline uint32_t HashForObject(Object* object);
static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
......@@ -72,7 +72,7 @@ class StringSetShape : public BaseShape<String*> {
public:
static inline bool IsMatch(String* key, Object* value);
static inline uint32_t Hash(String* key);
static inline uint32_t HashForObject(String* key, Object* object);
static inline uint32_t HashForObject(Object* object);
static const int kPrefixSize = 0;
static const int kEntrySize = 1;
......
......@@ -546,12 +546,10 @@ RUNTIME_FUNCTION(Runtime_DeleteProperty) {
RUNTIME_FUNCTION(Runtime_ShrinkPropertyDictionary) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
Handle<NameDictionary> new_properties =
NameDictionary::Shrink(dictionary, key);
Handle<NameDictionary> new_properties = NameDictionary::Shrink(dictionary);
receiver->set_properties(*new_properties);
return Smi::kZero;
}
......
......@@ -405,7 +405,7 @@ namespace internal {
F(AddElement, 3, 1) \
F(AppendElement, 2, 1) \
F(DeleteProperty, 3, 1) \
F(ShrinkPropertyDictionary, 2, 1) \
F(ShrinkPropertyDictionary, 1, 1) \
F(HasProperty, 2, 1) \
F(GetOwnPropertyKeys, 2, 1) \
F(GetInterceptorInfo, 1, 1) \
......
......@@ -214,7 +214,7 @@ TEST(HashTableRehash) {
for (int i = 0; i < capacity - 1; i++) {
t->insert(i, i * i, i);
}
t->Rehash(handle(Smi::kZero, isolate));
t->Rehash();
for (int i = 0; i < capacity - 1; i++) {
CHECK_EQ(i, t->lookup(i * i));
}
......@@ -227,7 +227,7 @@ TEST(HashTableRehash) {
for (int i = 0; i < capacity / 2; i++) {
t->insert(i, i * i, i);
}
t->Rehash(handle(Smi::kZero, isolate));
t->Rehash();
for (int i = 0; i < capacity / 2; i++) {
CHECK_EQ(i, t->lookup(i * i));
}
......
......@@ -105,11 +105,11 @@ TEST_F(ObjectWithIsolate, DictionaryGrowth) {
// If we grow by larger chunks, the next (sufficiently big) power of 2 is
// chosen as the capacity.
dict = SeededNumberDictionary::New(isolate(), 1);
dict = SeededNumberDictionary::EnsureCapacity(dict, 65, 1);
dict = SeededNumberDictionary::EnsureCapacity(dict, 65);
CHECK_EQ(128, dict->Capacity());
dict = SeededNumberDictionary::New(isolate(), 1);
dict = SeededNumberDictionary::EnsureCapacity(dict, 30, 1);
dict = SeededNumberDictionary::EnsureCapacity(dict, 30);
CHECK_EQ(64, dict->Capacity());
}
......
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