Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(843)

Unified Diff: src/objects.cc

Issue 1846963002: Use a dictionary-mode code cache on the map rather than a dual system. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 8d42ceb7c54337bc0e6c6459c7e627ca962e56b6..092383ccacff3b936605bedf8df88d2cd2ba072f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -10064,215 +10064,22 @@ void Map::UpdateCodeCache(Handle<Map> map,
Isolate* isolate = map->GetIsolate();
HandleScope scope(isolate);
// Allocate the code cache if not present.
- if (map->code_cache()->IsFixedArray()) {
- Handle<Object> result = isolate->factory()->NewCodeCache();
+ if (!map->has_code_cache()) {
+ Handle<Object> result =
+ CodeCacheHashTable::New(isolate, CodeCacheHashTable::kInitialSize);
map->set_code_cache(*result);
}
// Update the code cache.
- Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
- CodeCache::Update(code_cache, name, code);
-}
-
-
-Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
- // Do a lookup if a code cache exists.
- if (!code_cache()->IsFixedArray()) {
- return CodeCache::cast(code_cache())->Lookup(name, flags);
- } else {
- return GetHeap()->undefined_value();
- }
-}
-
-
-int Map::IndexInCodeCache(Object* name, Code* code) {
- // Get the internal index if a code cache exists.
- if (!code_cache()->IsFixedArray()) {
- return CodeCache::cast(code_cache())->GetIndex(name, code);
- }
- return -1;
-}
-
-
-void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
- // No GC is supposed to happen between a call to IndexInCodeCache and
- // RemoveFromCodeCache so the code cache must be there.
- DCHECK(!code_cache()->IsFixedArray());
- CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
-}
-
-
-void CodeCache::Update(
- Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
- // The number of monomorphic stubs for normal load/store/call IC's can grow to
- // a large number and therefore they need to go into a hash table. They are
- // used to load global properties from cells.
- if (code->type() == Code::NORMAL) {
- // Make sure that a hash table is allocated for the normal load code cache.
- if (code_cache->normal_type_cache()->IsUndefined()) {
- Handle<Object> result =
- CodeCacheHashTable::New(code_cache->GetIsolate(),
- CodeCacheHashTable::kInitialSize);
- code_cache->set_normal_type_cache(*result);
- }
- UpdateNormalTypeCache(code_cache, name, code);
- } else {
- DCHECK(code_cache->default_cache()->IsFixedArray());
- UpdateDefaultCache(code_cache, name, code);
- }
-}
-
-
-void CodeCache::UpdateDefaultCache(
- Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
- Isolate* isolate = code_cache->GetIsolate();
- // When updating the default code cache we disregard the type encoded in the
- // flags. This allows call constant stubs to overwrite call field
- // stubs, etc.
- Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
-
- // First check whether we can update existing code cache without
- // extending it.
- Handle<FixedArray> cache = handle(code_cache->default_cache());
- int length = cache->length();
- {
- DisallowHeapAllocation no_alloc;
- int deleted_index = -1;
- Object* null = isolate->heap()->null_value();
- Object* undefined = isolate->heap()->undefined_value();
- DCHECK(name->IsUniqueName());
- for (int i = 0; i < length; i += kCodeCacheEntrySize) {
- Object* key = cache->get(i);
- if (key == null) {
- if (deleted_index < 0) deleted_index = i;
- continue;
- }
- if (key == undefined) {
- if (deleted_index >= 0) i = deleted_index;
- cache->set(i + kCodeCacheEntryNameOffset, *name);
- cache->set(i + kCodeCacheEntryCodeOffset, *code);
- return;
- }
- DCHECK(key->IsUniqueName());
- if (*name == key) {
- Code::Flags found =
- Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
- if (Code::RemoveTypeFromFlags(found) == flags) {
- cache->set(i + kCodeCacheEntryCodeOffset, *code);
- return;
- }
- }
- }
-
- // Reached the end of the code cache. If there were deleted
- // elements, reuse the space for the first of them.
- if (deleted_index >= 0) {
- cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
- cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
- return;
- }
- }
-
- // Extend the code cache with some new entries (at least one). Must be a
- // multiple of the entry size.
- int new_length = length + (length >> 1) + kCodeCacheEntrySize;
- new_length = new_length - new_length % kCodeCacheEntrySize;
- DCHECK((new_length % kCodeCacheEntrySize) == 0);
- cache = isolate->factory()->CopyFixedArrayAndGrow(cache, new_length - length);
-
- // Add the (name, code) pair to the new cache.
- cache->set(length + kCodeCacheEntryNameOffset, *name);
- cache->set(length + kCodeCacheEntryCodeOffset, *code);
- code_cache->set_default_cache(*cache);
-}
-
-
-void CodeCache::UpdateNormalTypeCache(
- Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
- // Adding a new entry can cause a new cache to be allocated.
- Handle<CodeCacheHashTable> cache(
- CodeCacheHashTable::cast(code_cache->normal_type_cache()));
+ Handle<CodeCacheHashTable> cache(CodeCacheHashTable::cast(map->code_cache()),
+ isolate);
Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
- code_cache->set_normal_type_cache(*new_cache);
-}
-
-
-Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
- Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
- if (result->IsCode()) {
- if (Code::cast(result)->flags() == flags) return result;
- return GetHeap()->undefined_value();
- }
- return LookupNormalTypeCache(name, flags);
-}
-
-
-Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
- FixedArray* cache = default_cache();
- Heap* heap = GetHeap();
- Object* null = heap->null_value();
- Object* undefined = heap->undefined_value();
- int length = cache->length();
- DCHECK(name->IsUniqueName());
- for (int i = 0; i < length; i += kCodeCacheEntrySize) {
- Object* key = cache->get(i + kCodeCacheEntryNameOffset);
- // Skip deleted elements.
- if (key == null) continue;
- if (key == undefined) return key;
- DCHECK(key->IsUniqueName());
- if (name == key) {
- Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
- if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
- return code;
- }
- }
- }
- return GetHeap()->undefined_value();
-}
-
-
-Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
- if (!normal_type_cache()->IsUndefined()) {
- CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- return cache->Lookup(name, flags);
- } else {
- return GetHeap()->undefined_value();
- }
-}
-
-
-int CodeCache::GetIndex(Object* name, Code* code) {
- if (code->type() == Code::NORMAL) {
- if (normal_type_cache()->IsUndefined()) return -1;
- CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- return cache->GetIndex(Name::cast(name), code->flags());
- }
-
- FixedArray* array = default_cache();
- int len = array->length();
- for (int i = 0; i < len; i += kCodeCacheEntrySize) {
- if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
- }
- return -1;
+ map->set_code_cache(*new_cache);
}
-
-void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
- if (code->type() == Code::NORMAL) {
- DCHECK(!normal_type_cache()->IsUndefined());
- CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
- DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
- cache->RemoveByIndex(index);
- } else {
- FixedArray* array = default_cache();
- DCHECK(array->length() >= index && array->get(index)->IsCode());
- // Use null instead of undefined for deleted elements to distinguish
- // deleted elements from unused elements. This distinction is used
- // when looking up in the cache and when updating the cache.
- DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
- array->set_null(index - 1); // Name.
- array->set_null(index); // Code.
- }
+Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
+ if (!has_code_cache()) return nullptr;
+ return CodeCacheHashTable::cast(code_cache())->Lookup(name, flags);
}
@@ -10283,20 +10090,23 @@ void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
class CodeCacheHashTableKey : public HashTableKey {
public:
CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
- : name_(name), flags_(flags), code_() { }
+ : name_(name), flags_(flags), code_() {
+ DCHECK(name_->IsUniqueName());
+ }
CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
- : name_(name), flags_(code->flags()), code_(code) { }
+ : name_(name), flags_(code->flags()), code_(code) {
+ DCHECK(name_->IsUniqueName());
+ }
bool IsMatch(Object* other) override {
- if (!other->IsFixedArray()) return false;
+ 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;
- }
- return name_->Equals(name);
+ if (flags != flags_) return false;
+ DCHECK(name->IsUniqueName());
+ return *name_ == name;
}
static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
@@ -10328,15 +10138,6 @@ class CodeCacheHashTableKey : public HashTableKey {
};
-Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
- DisallowHeapAllocation no_alloc;
- CodeCacheHashTableKey key(handle(name), flags);
- int entry = FindEntry(&key);
- if (entry == kNotFound) return GetHeap()->undefined_value();
- return get(EntryToIndex(entry) + 1);
-}
-
-
Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
CodeCacheHashTableKey key(name, code);
@@ -10347,179 +10148,18 @@ Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
Handle<Object> k = key.AsHandle(cache->GetIsolate());
new_cache->set(EntryToIndex(entry), *k);
- new_cache->set(EntryToIndex(entry) + 1, *code);
new_cache->ElementAdded();
return new_cache;
}
-
-int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
+Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
DisallowHeapAllocation no_alloc;
CodeCacheHashTableKey key(handle(name), flags);
int entry = FindEntry(&key);
- return (entry == kNotFound) ? -1 : entry;
-}
-
-
-void CodeCacheHashTable::RemoveByIndex(int index) {
- DCHECK(index >= 0);
- Heap* heap = GetHeap();
- set(EntryToIndex(index), heap->the_hole_value());
- set(EntryToIndex(index) + 1, heap->the_hole_value());
- ElementRemoved();
+ if (entry == kNotFound) return nullptr;
+ return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
}
-
-void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
- MapHandleList* maps,
- Code::Flags flags,
- Handle<Code> code) {
- Isolate* isolate = code_cache->GetIsolate();
- if (code_cache->cache()->IsUndefined()) {
- Handle<PolymorphicCodeCacheHashTable> result =
- PolymorphicCodeCacheHashTable::New(
- isolate,
- PolymorphicCodeCacheHashTable::kInitialSize);
- code_cache->set_cache(*result);
- } else {
- // This entry shouldn't be contained in the cache yet.
- DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
- ->Lookup(maps, flags)->IsUndefined());
- }
- Handle<PolymorphicCodeCacheHashTable> hash_table =
- handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
- Handle<PolymorphicCodeCacheHashTable> new_cache =
- PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
- code_cache->set_cache(*new_cache);
-}
-
-
-Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
- Code::Flags flags) {
- if (!cache()->IsUndefined()) {
- PolymorphicCodeCacheHashTable* hash_table =
- PolymorphicCodeCacheHashTable::cast(cache());
- return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
- } else {
- return GetIsolate()->factory()->undefined_value();
- }
-}
-
-
-// Despite their name, object of this class are not stored in the actual
-// hash table; instead they're temporarily used for lookups. It is therefore
-// safe to have a weak (non-owning) pointer to a MapList as a member field.
-class PolymorphicCodeCacheHashTableKey : public HashTableKey {
- public:
- // Callers must ensure that |maps| outlives the newly constructed object.
- PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
- : maps_(maps),
- code_flags_(code_flags) {}
-
- bool IsMatch(Object* other) override {
- MapHandleList other_maps(kDefaultListAllocationSize);
- int other_flags;
- FromObject(other, &other_flags, &other_maps);
- if (code_flags_ != other_flags) return false;
- if (maps_->length() != other_maps.length()) return false;
- // Compare just the hashes first because it's faster.
- int this_hash = MapsHashHelper(maps_, code_flags_);
- int other_hash = MapsHashHelper(&other_maps, other_flags);
- if (this_hash != other_hash) return false;
-
- // Full comparison: for each map in maps_, look for an equivalent map in
- // other_maps. This implementation is slow, but probably good enough for
- // now because the lists are short (<= 4 elements currently).
- for (int i = 0; i < maps_->length(); ++i) {
- bool match_found = false;
- for (int j = 0; j < other_maps.length(); ++j) {
- if (*(maps_->at(i)) == *(other_maps.at(j))) {
- match_found = true;
- break;
- }
- }
- if (!match_found) return false;
- }
- return true;
- }
-
- static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
- uint32_t hash = code_flags;
- for (int i = 0; i < maps->length(); ++i) {
- hash ^= maps->at(i)->Hash();
- }
- return hash;
- }
-
- uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
-
- uint32_t HashForObject(Object* obj) override {
- MapHandleList other_maps(kDefaultListAllocationSize);
- int other_flags;
- FromObject(obj, &other_flags, &other_maps);
- return MapsHashHelper(&other_maps, other_flags);
- }
-
- MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
- // The maps in |maps_| must be copied to a newly allocated FixedArray,
- // both because the referenced MapList is short-lived, and because C++
- // objects can't be stored in the heap anyway.
- Handle<FixedArray> list =
- isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
- list->set(0, Smi::FromInt(code_flags_));
- for (int i = 0; i < maps_->length(); ++i) {
- list->set(i + 1, *maps_->at(i));
- }
- return list;
- }
-
- private:
- static MapHandleList* FromObject(Object* obj,
- int* code_flags,
- MapHandleList* maps) {
- FixedArray* list = FixedArray::cast(obj);
- maps->Rewind(0);
- *code_flags = Smi::cast(list->get(0))->value();
- for (int i = 1; i < list->length(); ++i) {
- maps->Add(Handle<Map>(Map::cast(list->get(i))));
- }
- return maps;
- }
-
- MapHandleList* maps_; // weak.
- int code_flags_;
- static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
-};
-
-
-Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
- int code_kind) {
- DisallowHeapAllocation no_alloc;
- PolymorphicCodeCacheHashTableKey key(maps, code_kind);
- int entry = FindEntry(&key);
- if (entry == kNotFound) return GetHeap()->undefined_value();
- return get(EntryToIndex(entry) + 1);
-}
-
-
-Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
- Handle<PolymorphicCodeCacheHashTable> hash_table,
- MapHandleList* maps,
- int code_kind,
- Handle<Code> code) {
- PolymorphicCodeCacheHashTableKey key(maps, code_kind);
- Handle<PolymorphicCodeCacheHashTable> cache =
- EnsureCapacity(hash_table, 1, &key);
- int entry = cache->FindInsertionEntry(key.Hash());
-
- Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
- cache->set(EntryToIndex(entry), *obj);
- cache->set(EntryToIndex(entry) + 1, *code);
- cache->ElementAdded();
- return cache;
-}
-
-
void FixedArray::Shrink(int new_length) {
DCHECK(0 <= new_length && new_length <= length());
if (new_length < length()) {
@@ -14803,8 +14443,8 @@ const char* Code::ICState2String(InlineCacheState state) {
case UNINITIALIZED: return "UNINITIALIZED";
case PREMONOMORPHIC: return "PREMONOMORPHIC";
case MONOMORPHIC: return "MONOMORPHIC";
- case PROTOTYPE_FAILURE:
- return "PROTOTYPE_FAILURE";
+ case RECOMPUTE_HANDLER:
+ return "RECOMPUTE_HANDLER";
case POLYMORPHIC: return "POLYMORPHIC";
case MEGAMORPHIC: return "MEGAMORPHIC";
case GENERIC: return "GENERIC";
@@ -14815,16 +14455,6 @@ const char* Code::ICState2String(InlineCacheState state) {
}
-const char* Code::StubType2String(StubType type) {
- switch (type) {
- case NORMAL: return "NORMAL";
- case FAST: return "FAST";
- }
- UNREACHABLE(); // keep the compiler happy
- return NULL;
-}
-
-
void Code::PrintExtraICState(std::ostream& os, // NOLINT
Kind kind, ExtraICState extra) {
os << "extra_ic_state = ";
@@ -14846,9 +14476,6 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
if (is_inline_cache_stub()) {
os << "ic_state = " << ICState2String(ic_state()) << "\n";
PrintExtraICState(os, kind(), extra_ic_state());
- if (ic_state() == MONOMORPHIC) {
- os << "type = " << StubType2String(type()) << "\n";
- }
if (is_compare_ic_stub()) {
DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
CompareICStub stub(stub_key(), GetIsolate());
@@ -17166,10 +16793,13 @@ void HashTable<Derived, Shape, Key>::Rehash(
// Rehash the elements.
int capacity = this->Capacity();
+ Heap* heap = new_table->GetHeap();
+ Object* the_hole = heap->the_hole_value();
+ Object* undefined = heap->undefined_value();
for (int i = 0; i < capacity; i++) {
uint32_t from_index = EntryToIndex(i);
Object* k = this->get(from_index);
- if (IsKey(k)) {
+ if (k != the_hole && k != undefined) {
uint32_t hash = this->HashForObject(key, k);
uint32_t insertion_index =
EntryToIndex(new_table->FindInsertionEntry(hash));
@@ -17333,9 +16963,12 @@ uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
uint32_t entry = FirstProbe(hash, capacity);
uint32_t count = 1;
// EnsureCapacity will guarantee the hash table is never full.
+ Heap* heap = GetHeap();
+ Object* the_hole = heap->the_hole_value();
+ Object* undefined = heap->undefined_value();
while (true) {
Object* element = KeyAt(entry);
- if (element->IsUndefined() || element->IsTheHole()) break;
+ if (element == the_hole || element == undefined) break;
entry = NextProbe(entry, count++, capacity);
}
return entry;
@@ -18819,21 +18452,23 @@ Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
template<class Derived, class Iterator, int entrysize>
Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
Handle<Derived> table, int new_capacity) {
+ Isolate* isolate = table->GetIsolate();
+ Heap* heap = isolate->heap();
DCHECK(!table->IsObsolete());
- Handle<Derived> new_table =
- Allocate(table->GetIsolate(),
- new_capacity,
- table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
+ Handle<Derived> new_table = Allocate(
+ isolate, new_capacity, heap->InNewSpace(*table) ? NOT_TENURED : TENURED);
int nof = table->NumberOfElements();
int nod = table->NumberOfDeletedElements();
int new_buckets = new_table->NumberOfBuckets();
int new_entry = 0;
int removed_holes_index = 0;
+ DisallowHeapAllocation no_gc;
+ Object* the_hole = heap->the_hole_value();
for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
Object* key = table->KeyAt(old_entry);
- if (key->IsTheHole()) {
+ if (key == the_hole) {
table->SetRemovedIndexAt(removed_holes_index++, old_entry);
continue;
}
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698