[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/531184 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#45873}
This commit is contained in:
parent
49ecce8ad6
commit
dda2b5b1ec
@ -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);
|
||||
|
137
src/objects.cc
137
src/objects.cc
@ -6043,8 +6043,7 @@ void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
|
||||
DCHECK_NE(NameDictionary::kNotFound, entry);
|
||||
|
||||
NameDictionary::DeleteProperty(dictionary, entry);
|
||||
Handle<NameDictionary> new_properties =
|
||||
NameDictionary::Shrink(dictionary, name);
|
||||
Handle<NameDictionary> new_properties = NameDictionary::Shrink(dictionary);
|
||||
object->set_properties(*new_properties);
|
||||
}
|
||||
}
|
||||
@ -9753,7 +9752,7 @@ Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
|
||||
Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
|
||||
CodeCacheHashTableKey key(name, code);
|
||||
|
||||
Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
|
||||
Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1);
|
||||
|
||||
int entry = new_cache->FindInsertionEntry(key.Hash());
|
||||
Handle<Object> k = key.AsHandle(cache->GetIsolate());
|
||||
@ -15892,7 +15891,7 @@ void Symbol::SymbolShortPrint(std::ostream& os) {
|
||||
|
||||
|
||||
// StringSharedKeys are used as keys in the eval cache.
|
||||
class StringSharedKey : public CompilationCacheKey {
|
||||
class StringSharedKey : public HashTableKey {
|
||||
public:
|
||||
// This tuple unambiguously identifies calls to eval() or
|
||||
// CreateDynamicFunction() (such as through the Function() constructor).
|
||||
@ -15931,53 +15930,18 @@ class StringSharedKey : public CompilationCacheKey {
|
||||
return source->Equals(*source_);
|
||||
}
|
||||
|
||||
static uint32_t StringSharedHashHelper(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 Hash() override {
|
||||
return StringSharedHashHelper(*source_, *shared_, language_mode_,
|
||||
position_);
|
||||
return CompilationCacheShape::StringSharedHash(*source_, *shared_,
|
||||
language_mode_, position_);
|
||||
}
|
||||
|
||||
uint32_t HashForObject(Object* obj) override {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (obj->IsNumber()) {
|
||||
return static_cast<uint32_t>(obj->Number());
|
||||
}
|
||||
FixedArray* other_array = FixedArray::cast(obj);
|
||||
SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
|
||||
String* source = String::cast(other_array->get(1));
|
||||
int language_unchecked = Smi::cast(other_array->get(2))->value();
|
||||
DCHECK(is_valid_language_mode(language_unchecked));
|
||||
LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
|
||||
int position = Smi::cast(other_array->get(3))->value();
|
||||
return StringSharedHashHelper(source, shared, language_mode, position);
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> AsHandle(Isolate* isolate) override {
|
||||
Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
|
||||
array->set(0, *shared_);
|
||||
array->set(1, *source_);
|
||||
array->set(2, Smi::FromInt(language_mode_));
|
||||
array->set(3, Smi::FromInt(position_));
|
||||
array->set_map(isolate->heap()->fixed_cow_array_map());
|
||||
return array;
|
||||
}
|
||||
|
||||
@ -16190,7 +16154,7 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
|
||||
|
||||
|
||||
// RegExpKey carries the source and flags of a regular expression as key.
|
||||
class RegExpKey : public CompilationCacheKey {
|
||||
class RegExpKey : public HashTableKey {
|
||||
public:
|
||||
RegExpKey(Handle<String> string, JSRegExp::Flags flags)
|
||||
: string_(string), flags_(Smi::FromInt(flags)) {}
|
||||
@ -16205,7 +16169,9 @@ class RegExpKey : public CompilationCacheKey {
|
||||
&& (flags_ == val->get(JSRegExp::kFlagsIndex));
|
||||
}
|
||||
|
||||
uint32_t Hash() override { return RegExpHash(*string_, flags_); }
|
||||
uint32_t Hash() override {
|
||||
return CompilationCacheShape::RegExpHash(*string_, flags_);
|
||||
}
|
||||
|
||||
Handle<Object> AsHandle(Isolate* isolate) override {
|
||||
// Plain hash maps, which is where regexp keys are used, don't
|
||||
@ -16213,16 +16179,6 @@ class RegExpKey : public CompilationCacheKey {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
uint32_t HashForObject(Object* obj) override {
|
||||
FixedArray* val = FixedArray::cast(obj);
|
||||
return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
|
||||
Smi::cast(val->get(JSRegExp::kFlagsIndex)));
|
||||
}
|
||||
|
||||
static uint32_t RegExpHash(String* string, Smi* flags) {
|
||||
return string->Hash() + flags->value();
|
||||
}
|
||||
|
||||
Handle<String> string_;
|
||||
Smi* flags_;
|
||||
};
|
||||
@ -16375,7 +16331,7 @@ int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void HashTable<Derived, Shape>::Rehash(Handle<Derived> new_table, Key key) {
|
||||
void HashTable<Derived, Shape>::Rehash(Handle<Derived> new_table) {
|
||||
DCHECK(NumberOfElements() < new_table->Capacity());
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
@ -16397,7 +16353,7 @@ void HashTable<Derived, Shape>::Rehash(Handle<Derived> new_table, Key key) {
|
||||
uint32_t from_index = EntryToIndex(i);
|
||||
Object* k = this->get(from_index);
|
||||
if (k != the_hole && k != undefined) {
|
||||
uint32_t hash = this->HashForObject(key, k);
|
||||
uint32_t hash = this->HashForObject(k);
|
||||
uint32_t insertion_index =
|
||||
EntryToIndex(new_table->FindInsertionEntry(hash));
|
||||
for (int j = 0; j < Shape::kEntrySize; j++) {
|
||||
@ -16410,9 +16366,9 @@ void HashTable<Derived, Shape>::Rehash(Handle<Derived> new_table, Key key) {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
uint32_t HashTable<Derived, Shape>::EntryForProbe(Key key, Object* k, int probe,
|
||||
uint32_t HashTable<Derived, Shape>::EntryForProbe(Object* k, int probe,
|
||||
uint32_t expected) {
|
||||
uint32_t hash = this->HashForObject(key, k);
|
||||
uint32_t hash = this->HashForObject(k);
|
||||
uint32_t capacity = this->Capacity();
|
||||
uint32_t entry = FirstProbe(hash, capacity);
|
||||
for (int i = 1; i < probe; i++) {
|
||||
@ -16440,7 +16396,7 @@ void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void HashTable<Derived, Shape>::Rehash(Key key) {
|
||||
void HashTable<Derived, Shape>::Rehash() {
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
|
||||
Isolate* isolate = GetIsolate();
|
||||
@ -16453,11 +16409,11 @@ void HashTable<Derived, Shape>::Rehash(Key key) {
|
||||
for (uint32_t current = 0; current < capacity; current++) {
|
||||
Object* current_key = KeyAt(current);
|
||||
if (IsKey(isolate, current_key)) {
|
||||
uint32_t target = EntryForProbe(key, current_key, probe, current);
|
||||
uint32_t target = EntryForProbe(current_key, probe, current);
|
||||
if (current == target) continue;
|
||||
Object* target_key = KeyAt(target);
|
||||
if (!IsKey(isolate, target_key) ||
|
||||
EntryForProbe(key, target_key, probe, target) != target) {
|
||||
EntryForProbe(target_key, probe, target) != target) {
|
||||
// Put the current element into the correct position.
|
||||
Swap(current, target, mode);
|
||||
// The other element will be processed on the next iteration.
|
||||
@ -16483,7 +16439,7 @@ void HashTable<Derived, Shape>::Rehash(Key key) {
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
|
||||
Handle<Derived> table, int n, Key key, PretenureFlag pretenure) {
|
||||
Handle<Derived> table, int n, PretenureFlag pretenure) {
|
||||
if (table->HasSufficientCapacityToAdd(n)) return table;
|
||||
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
@ -16498,7 +16454,7 @@ Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
|
||||
HashTable::New(isolate, new_nof, USE_DEFAULT_MINIMUM_CAPACITY,
|
||||
should_pretenure ? TENURED : NOT_TENURED);
|
||||
|
||||
table->Rehash(new_table, key);
|
||||
table->Rehash(new_table);
|
||||
return new_table;
|
||||
}
|
||||
|
||||
@ -16519,8 +16475,7 @@ bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<Derived> HashTable<Derived, Shape>::Shrink(Handle<Derived> table,
|
||||
Key key) {
|
||||
Handle<Derived> HashTable<Derived, Shape>::Shrink(Handle<Derived> table) {
|
||||
int capacity = table->Capacity();
|
||||
int nof = table->NumberOfElements();
|
||||
|
||||
@ -16545,7 +16500,7 @@ Handle<Derived> HashTable<Derived, Shape>::Shrink(Handle<Derived> table,
|
||||
USE_DEFAULT_MINIMUM_CAPACITY,
|
||||
pretenure ? TENURED : NOT_TENURED);
|
||||
|
||||
table->Rehash(new_table, key);
|
||||
table->Rehash(new_table);
|
||||
return new_table;
|
||||
}
|
||||
|
||||
@ -16656,13 +16611,12 @@ HashTable<ObjectHashSet, ObjectHashSetShape>::New(Isolate*, int n,
|
||||
MinimumCapacity,
|
||||
PretenureFlag);
|
||||
|
||||
template Handle<NameDictionary>
|
||||
HashTable<NameDictionary, NameDictionaryShape>::Shrink(
|
||||
Handle<NameDictionary>, Handle<Name>);
|
||||
template Handle<NameDictionary> HashTable<
|
||||
NameDictionary, NameDictionaryShape>::Shrink(Handle<NameDictionary>);
|
||||
|
||||
template Handle<UnseededNumberDictionary>
|
||||
HashTable<UnseededNumberDictionary, UnseededNumberDictionaryShape>::Shrink(
|
||||
Handle<UnseededNumberDictionary>, uint32_t);
|
||||
Handle<UnseededNumberDictionary>);
|
||||
|
||||
template Handle<NameDictionary>
|
||||
Dictionary<NameDictionary, NameDictionaryShape>::Add(Handle<NameDictionary>,
|
||||
@ -16687,18 +16641,18 @@ Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape>::Add(
|
||||
|
||||
template Handle<SeededNumberDictionary>
|
||||
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape>::EnsureCapacity(
|
||||
Handle<SeededNumberDictionary>, int, uint32_t);
|
||||
Handle<SeededNumberDictionary>, int);
|
||||
|
||||
template Handle<UnseededNumberDictionary>
|
||||
Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape>::
|
||||
EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
|
||||
EnsureCapacity(Handle<UnseededNumberDictionary>, int);
|
||||
|
||||
template void Dictionary<
|
||||
NameDictionary, NameDictionaryShape>::SetRequiresCopyOnCapacityChange();
|
||||
|
||||
template Handle<NameDictionary>
|
||||
Dictionary<NameDictionary, NameDictionaryShape>::EnsureCapacity(
|
||||
Handle<NameDictionary>, int, Handle<Name>);
|
||||
Handle<NameDictionary>, int);
|
||||
|
||||
template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
|
||||
Handle<Name>);
|
||||
@ -17307,8 +17261,7 @@ void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
|
||||
int expected) {
|
||||
Handle<StringTable> table = isolate->factory()->string_table();
|
||||
// We need a key instance for the virtual hash function.
|
||||
InternalizedStringKey dummy_key(isolate->factory()->empty_string());
|
||||
table = StringTable::EnsureCapacity(table, expected, &dummy_key);
|
||||
table = StringTable::EnsureCapacity(table, expected);
|
||||
isolate->heap()->SetRootStringTable(*table);
|
||||
}
|
||||
|
||||
@ -17418,7 +17371,7 @@ Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
|
||||
}
|
||||
|
||||
// Adding new string. Grow table if needed.
|
||||
table = StringTable::EnsureCapacity(table, 1, key);
|
||||
table = StringTable::EnsureCapacity(table, 1);
|
||||
|
||||
// Create string object.
|
||||
Handle<Object> string = key->AsHandle(isolate);
|
||||
@ -17608,7 +17561,7 @@ Handle<StringSet> StringSet::New(Isolate* isolate) {
|
||||
Handle<StringSet> StringSet::Add(Handle<StringSet> stringset,
|
||||
Handle<String> name) {
|
||||
if (!stringset->Has(name)) {
|
||||
stringset = EnsureCapacity(stringset, 1, *name);
|
||||
stringset = EnsureCapacity(stringset, 1);
|
||||
uint32_t hash = StringSetShape::Hash(*name);
|
||||
int entry = stringset->FindInsertionEntry(hash);
|
||||
stringset->set(EntryToIndex(entry), *name);
|
||||
@ -17627,7 +17580,7 @@ Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> set,
|
||||
int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
|
||||
|
||||
if (!set->Has(isolate, key, hash)) {
|
||||
set = EnsureCapacity(set, 1, key);
|
||||
set = EnsureCapacity(set, 1);
|
||||
int entry = set->FindInsertionEntry(hash);
|
||||
set->set(EntryToIndex(entry), *key);
|
||||
set->ElementAdded();
|
||||
@ -17814,7 +17767,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::Put(
|
||||
Handle<SharedFunctionInfo> shared(context->closure()->shared());
|
||||
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
|
||||
Handle<Object> k = key.AsHandle(isolate);
|
||||
cache = EnsureCapacity(cache, 1, &key);
|
||||
cache = EnsureCapacity(cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
cache->set(EntryToIndex(entry), *k);
|
||||
cache->set(EntryToIndex(entry) + 1, *value);
|
||||
@ -17831,7 +17784,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
|
||||
Handle<Context> native_context(context->native_context());
|
||||
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
|
||||
Handle<Object> k = key.AsHandle(isolate);
|
||||
cache = EnsureCapacity(cache, 1, &key);
|
||||
cache = EnsureCapacity(cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
cache->set(EntryToIndex(entry), *k);
|
||||
cache->set(EntryToIndex(entry) + 1, *value);
|
||||
@ -17861,7 +17814,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
|
||||
}
|
||||
}
|
||||
|
||||
cache = EnsureCapacity(cache, 1, &key);
|
||||
cache = EnsureCapacity(cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
Handle<Object> k =
|
||||
isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
|
||||
@ -17876,7 +17829,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
|
||||
Handle<CompilationCacheTable> cache, Handle<String> src,
|
||||
JSRegExp::Flags flags, Handle<FixedArray> value) {
|
||||
RegExpKey key(src, flags);
|
||||
cache = EnsureCapacity(cache, 1, &key);
|
||||
cache = EnsureCapacity(cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
// We store the value in the key slot, and compare the search key
|
||||
// to the stored value with a custon IsMatch function during lookups.
|
||||
@ -17972,7 +17925,7 @@ void Dictionary<Derived, Shape>::SetRequiresCopyOnCapacityChange() {
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<Derived> Dictionary<Derived, Shape>::EnsureCapacity(
|
||||
Handle<Derived> dictionary, int n, Key key) {
|
||||
Handle<Derived> dictionary, int n) {
|
||||
// Check whether there are enough enumeration indices to add n elements.
|
||||
if (Shape::kIsEnumerable &&
|
||||
!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
|
||||
@ -18000,7 +17953,7 @@ Handle<Derived> Dictionary<Derived, Shape>::EnsureCapacity(
|
||||
dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
|
||||
length);
|
||||
}
|
||||
return DerivedHashTable::EnsureCapacity(dictionary, n, key);
|
||||
return DerivedHashTable::EnsureCapacity(dictionary, n);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
@ -18029,7 +17982,7 @@ Handle<Derived> Dictionary<Derived, Shape>::AtPut(Handle<Derived> dictionary,
|
||||
}
|
||||
|
||||
// Check whether the dictionary should be extended.
|
||||
dictionary = EnsureCapacity(dictionary, 1, key);
|
||||
dictionary = EnsureCapacity(dictionary, 1);
|
||||
#ifdef DEBUG
|
||||
USE(Shape::AsHandle(dictionary->GetIsolate(), key));
|
||||
#endif
|
||||
@ -18047,7 +18000,7 @@ Handle<Derived> Dictionary<Derived, Shape>::Add(Handle<Derived> dictionary,
|
||||
// Valdate key is absent.
|
||||
SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
|
||||
// Check whether the dictionary should be extended.
|
||||
dictionary = EnsureCapacity(dictionary, 1, key);
|
||||
dictionary = EnsureCapacity(dictionary, 1);
|
||||
|
||||
int entry = AddEntry(dictionary, key, value, details, dictionary->Hash(key));
|
||||
if (entry_out) *entry_out = entry;
|
||||
@ -18145,7 +18098,7 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
|
||||
dictionary->SetEntry(entry, factory->the_hole_value(),
|
||||
factory->the_hole_value());
|
||||
dictionary->ElementRemoved();
|
||||
return dictionary->Shrink(dictionary, key);
|
||||
return dictionary->Shrink(dictionary);
|
||||
}
|
||||
|
||||
Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
|
||||
@ -18454,7 +18407,7 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
||||
// Rehash if more than 33% of the entries are deleted entries.
|
||||
// TODO(jochen): Consider to shrink the fixed array in place.
|
||||
if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
|
||||
table->Rehash(isolate->factory()->undefined_value());
|
||||
table->Rehash();
|
||||
}
|
||||
// If we're out of luck, we didn't get a GC recently, and so rehashing
|
||||
// isn't enough to avoid a crash.
|
||||
@ -18467,12 +18420,12 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
||||
Heap::kFinalizeIncrementalMarkingMask,
|
||||
GarbageCollectionReason::kFullHashtable);
|
||||
}
|
||||
table->Rehash(isolate->factory()->undefined_value());
|
||||
table->Rehash();
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the hash table should be extended.
|
||||
table = EnsureCapacity(table, 1, key);
|
||||
table = EnsureCapacity(table, 1);
|
||||
table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
|
||||
return table;
|
||||
}
|
||||
@ -18508,7 +18461,7 @@ Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
|
||||
|
||||
*was_present = true;
|
||||
table->RemoveEntry(entry);
|
||||
return Shrink(table, key);
|
||||
return Shrink(table);
|
||||
}
|
||||
|
||||
|
||||
@ -18551,7 +18504,7 @@ Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
|
||||
Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
|
||||
|
||||
// Check whether the hash table should be extended.
|
||||
table = EnsureCapacity(table, 1, key, TENURED);
|
||||
table = EnsureCapacity(table, 1, TENURED);
|
||||
|
||||
table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
|
||||
return table;
|
||||
|
@ -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 Handle<Object> AsHandle(Isolate* isolate,
|
||||
CompilationCacheKey* key);
|
||||
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, 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());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user