| 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;
|
| }
|
|
|