[dictionaries] Use IsKey(Isolate* i, Object* o) everywhere
Using the isolate to check for IsUndefined and IsTheHole is roughly at least 20% faster in the worst-case and up to a factor 2x in the best case. BUG= Review-Url: https://codereview.chromium.org/2031533002 Cr-Commit-Position: refs/heads/master@{#36787}
This commit is contained in:
parent
3cfcc7e111
commit
764d4e6103
@ -2661,7 +2661,7 @@ void NativeWeakMap::Set(Local<Value> v8_key, Local<Value> v8_value) {
|
||||
}
|
||||
i::Handle<i::ObjectHashTable> table(
|
||||
i::ObjectHashTable::cast(weak_collection->table()));
|
||||
if (!table->IsKey(*key)) {
|
||||
if (!table->IsKey(isolate, *key)) {
|
||||
DCHECK(false);
|
||||
return;
|
||||
}
|
||||
@ -2681,7 +2681,7 @@ Local<Value> NativeWeakMap::Get(Local<Value> v8_key) {
|
||||
}
|
||||
i::Handle<i::ObjectHashTable> table(
|
||||
i::ObjectHashTable::cast(weak_collection->table()));
|
||||
if (!table->IsKey(*key)) {
|
||||
if (!table->IsKey(isolate, *key)) {
|
||||
DCHECK(false);
|
||||
return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
|
||||
}
|
||||
@ -2704,7 +2704,7 @@ bool NativeWeakMap::Has(Local<Value> v8_key) {
|
||||
}
|
||||
i::Handle<i::ObjectHashTable> table(
|
||||
i::ObjectHashTable::cast(weak_collection->table()));
|
||||
if (!table->IsKey(*key)) {
|
||||
if (!table->IsKey(isolate, *key)) {
|
||||
DCHECK(false);
|
||||
return false;
|
||||
}
|
||||
@ -2725,7 +2725,7 @@ bool NativeWeakMap::Delete(Local<Value> v8_key) {
|
||||
}
|
||||
i::Handle<i::ObjectHashTable> table(
|
||||
i::ObjectHashTable::cast(weak_collection->table()));
|
||||
if (!table->IsKey(*key)) {
|
||||
if (!table->IsKey(isolate, *key)) {
|
||||
DCHECK(false);
|
||||
return false;
|
||||
}
|
||||
|
@ -3570,7 +3570,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
||||
int capacity = properties->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* raw_key(properties->KeyAt(i));
|
||||
if (properties->IsKey(raw_key)) {
|
||||
if (properties->IsKey(isolate(), raw_key)) {
|
||||
DCHECK(raw_key->IsName());
|
||||
// If the property is already there we skip it.
|
||||
Handle<Name> key(Name::cast(raw_key));
|
||||
@ -3593,7 +3593,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
||||
int capacity = properties->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* raw_key(properties->KeyAt(i));
|
||||
if (properties->IsKey(raw_key)) {
|
||||
if (properties->IsKey(isolate(), raw_key)) {
|
||||
DCHECK(raw_key->IsName());
|
||||
// If the property is already there we skip it.
|
||||
Handle<Name> key(Name::cast(raw_key));
|
||||
|
@ -865,6 +865,7 @@ class ArrayConcatVisitor {
|
||||
|
||||
|
||||
uint32_t EstimateElementCount(Handle<JSArray> array) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
uint32_t length = static_cast<uint32_t>(array->length()->Number());
|
||||
int element_count = 0;
|
||||
switch (array->GetElementsKind()) {
|
||||
@ -877,7 +878,7 @@ uint32_t EstimateElementCount(Handle<JSArray> array) {
|
||||
DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
|
||||
int fast_length = static_cast<int>(length);
|
||||
Isolate* isolate = array->GetIsolate();
|
||||
Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate);
|
||||
FixedArray* elements = FixedArray::cast(array->elements());
|
||||
for (int i = 0; i < fast_length; i++) {
|
||||
if (!elements->get(i)->IsTheHole(isolate)) element_count++;
|
||||
}
|
||||
@ -893,20 +894,20 @@ uint32_t EstimateElementCount(Handle<JSArray> array) {
|
||||
DCHECK(FixedArray::cast(array->elements())->length() == 0);
|
||||
break;
|
||||
}
|
||||
Handle<FixedDoubleArray> elements(
|
||||
FixedDoubleArray::cast(array->elements()));
|
||||
FixedDoubleArray* elements = FixedDoubleArray::cast(array->elements());
|
||||
for (int i = 0; i < fast_length; i++) {
|
||||
if (!elements->is_the_hole(i)) element_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
Handle<SeededNumberDictionary> dictionary(
|
||||
SeededNumberDictionary::cast(array->elements()));
|
||||
SeededNumberDictionary* dictionary =
|
||||
SeededNumberDictionary::cast(array->elements());
|
||||
Isolate* isolate = dictionary->GetIsolate();
|
||||
int capacity = dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
|
||||
if (dictionary->IsKey(*key)) {
|
||||
Object* key = dictionary->KeyAt(i);
|
||||
if (dictionary->IsKey(isolate, key)) {
|
||||
element_count++;
|
||||
}
|
||||
}
|
||||
@ -983,13 +984,9 @@ void CollectElementIndices(Handle<JSObject> object, uint32_t range,
|
||||
SeededNumberDictionary* dict =
|
||||
SeededNumberDictionary::cast(object->elements());
|
||||
uint32_t capacity = dict->Capacity();
|
||||
Heap* heap = isolate->heap();
|
||||
Object* undefined = heap->undefined_value();
|
||||
Object* the_hole = heap->the_hole_value();
|
||||
FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
|
||||
Object* k = dict->KeyAt(j);
|
||||
if (k == undefined) continue;
|
||||
if (k == the_hole) continue;
|
||||
if (!dict->IsKey(isolate, k)) continue;
|
||||
DCHECK(k->IsNumber());
|
||||
uint32_t index = static_cast<uint32_t>(k->Number());
|
||||
if (index < range) {
|
||||
|
@ -1186,12 +1186,10 @@ class DictionaryElementsAccessor
|
||||
SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
|
||||
if (!dict->requires_slow_elements()) return false;
|
||||
int capacity = dict->Capacity();
|
||||
Heap* heap = holder->GetHeap();
|
||||
Object* undefined = heap->undefined_value();
|
||||
Object* the_hole = heap->the_hole_value();
|
||||
Isolate* isolate = dict->GetIsolate();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key == the_hole || key == undefined) continue;
|
||||
if (!dict->IsKey(isolate, key)) continue;
|
||||
DCHECK(!dict->IsDeleted(i));
|
||||
PropertyDetails details = dict->DetailsAt(i);
|
||||
if (details.type() == ACCESSOR_CONSTANT) return true;
|
||||
@ -1301,23 +1299,12 @@ class DictionaryElementsAccessor
|
||||
return static_cast<uint32_t>(raw_key->Number());
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
|
||||
static uint32_t GetKeyForEntryImpl(Isolate* isolate,
|
||||
Handle<SeededNumberDictionary> dictionary,
|
||||
int entry, PropertyFilter filter) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* raw_key = dictionary->KeyAt(entry);
|
||||
if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
|
||||
return FilterKey(dictionary, entry, raw_key, filter);
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
|
||||
int entry, PropertyFilter filter,
|
||||
Object* undefined, Object* the_hole) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* raw_key = dictionary->KeyAt(entry);
|
||||
// Replace the IsKey check with a direct comparison which is much faster.
|
||||
if (raw_key == undefined || raw_key == the_hole) {
|
||||
return kMaxUInt32;
|
||||
}
|
||||
if (!dictionary->IsKey(isolate, raw_key)) return kMaxUInt32;
|
||||
return FilterKey(dictionary, entry, raw_key, filter);
|
||||
}
|
||||
|
||||
@ -1325,21 +1312,18 @@ class DictionaryElementsAccessor
|
||||
Handle<FixedArrayBase> backing_store,
|
||||
KeyAccumulator* keys) {
|
||||
if (keys->filter() & SKIP_STRINGS) return;
|
||||
Factory* factory = keys->isolate()->factory();
|
||||
Handle<Object> undefined = factory->undefined_value();
|
||||
Handle<Object> the_hole = factory->the_hole_value();
|
||||
Isolate* isolate = keys->isolate();
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
Handle<SeededNumberDictionary>::cast(backing_store);
|
||||
int capacity = dictionary->Capacity();
|
||||
Handle<FixedArray> elements =
|
||||
factory->NewFixedArray(GetMaxNumberOfEntries(*object, *backing_store));
|
||||
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(
|
||||
GetMaxNumberOfEntries(*object, *backing_store));
|
||||
int insertion_index = 0;
|
||||
PropertyFilter filter = keys->filter();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
uint32_t key =
|
||||
GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
|
||||
uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
|
||||
if (key == kMaxUInt32) continue;
|
||||
Handle<Object> key_handle = factory->NewNumberFromUint(key);
|
||||
Handle<Object> key_handle = isolate->factory()->NewNumberFromUint(key);
|
||||
elements->set(insertion_index, *key_handle);
|
||||
insertion_index++;
|
||||
}
|
||||
@ -1357,14 +1341,11 @@ class DictionaryElementsAccessor
|
||||
if (filter & SKIP_STRINGS) return list;
|
||||
if (filter & ONLY_ALL_CAN_READ) return list;
|
||||
|
||||
Handle<Object> undefined = isolate->factory()->undefined_value();
|
||||
Handle<Object> the_hole = isolate->factory()->the_hole_value();
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
Handle<SeededNumberDictionary>::cast(backing_store);
|
||||
uint32_t capacity = dictionary->Capacity();
|
||||
for (uint32_t i = 0; i < capacity; i++) {
|
||||
uint32_t key =
|
||||
GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
|
||||
uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
|
||||
if (key == kMaxUInt32) continue;
|
||||
Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
|
||||
list->set(insertion_index, *index);
|
||||
|
@ -473,9 +473,10 @@ static void PatchIncrementalMarkingRecordWriteStubs(
|
||||
UnseededNumberDictionary* stubs = heap->code_stubs();
|
||||
|
||||
int capacity = stubs->Capacity();
|
||||
Isolate* isolate = heap->isolate();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = stubs->KeyAt(i);
|
||||
if (stubs->IsKey(k)) {
|
||||
if (stubs->IsKey(isolate, k)) {
|
||||
uint32_t key = NumberToUint32(k);
|
||||
|
||||
if (CodeStub::MajorKeyFromKey(key) == CodeStub::RecordWrite) {
|
||||
|
@ -2464,7 +2464,7 @@ void MarkCompactCollector::MarkDependentCodeForDeoptimization(
|
||||
for (uint32_t i = 0; i < capacity; i++) {
|
||||
uint32_t key_index = table->EntryToIndex(i);
|
||||
Object* key = table->get(key_index);
|
||||
if (!table->IsKey(key)) continue;
|
||||
if (!table->IsKey(isolate, key)) continue;
|
||||
uint32_t value_index = table->EntryToValueIndex(i);
|
||||
Object* value = table->get(value_index);
|
||||
DCHECK(key->IsWeakCell());
|
||||
|
@ -3052,7 +3052,8 @@ int HashTableBase::ComputeCapacity(int at_least_space_for) {
|
||||
return Max(capacity, kMinCapacity);
|
||||
}
|
||||
|
||||
bool HashTableBase::IsKey(Heap* heap, Object* k) {
|
||||
bool HashTableBase::IsKey(Isolate* isolate, Object* k) {
|
||||
Heap* heap = isolate->heap();
|
||||
return k != heap->the_hole_value() && k != heap->undefined_value();
|
||||
}
|
||||
|
||||
|
101
src/objects.cc
101
src/objects.cc
@ -1520,10 +1520,10 @@ Map* Object::GetRootMap(Isolate* isolate) {
|
||||
|
||||
|
||||
Object* Object::GetHash() {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* hash = GetSimpleHash();
|
||||
if (hash->IsSmi()) return hash;
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
DCHECK(IsJSReceiver());
|
||||
JSReceiver* receiver = JSReceiver::cast(this);
|
||||
Isolate* isolate = receiver->GetIsolate();
|
||||
@ -5701,7 +5701,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
|
||||
// Compute the length of the instance descriptor.
|
||||
for (int i = 0; i < instance_descriptor_length; i++) {
|
||||
int index = Smi::cast(iteration_order->get(i))->value();
|
||||
DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
|
||||
DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
|
||||
|
||||
Object* value = dictionary->ValueAt(index);
|
||||
PropertyType type = dictionary->DetailsAt(index).type();
|
||||
@ -7636,9 +7636,10 @@ template <typename Dictionary>
|
||||
static void ApplyAttributesToDictionary(Dictionary* dictionary,
|
||||
const PropertyAttributes attributes) {
|
||||
int capacity = dictionary->Capacity();
|
||||
Isolate* isolate = dictionary->GetIsolate();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = dictionary->KeyAt(i);
|
||||
if (dictionary->IsKey(k) &&
|
||||
if (dictionary->IsKey(isolate, k) &&
|
||||
!(k->IsSymbol() && Symbol::cast(k)->is_private())) {
|
||||
PropertyDetails details = dictionary->DetailsAt(i);
|
||||
int attrs = attributes;
|
||||
@ -7965,7 +7966,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
||||
int capacity = element_dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = element_dictionary->KeyAt(i);
|
||||
if (element_dictionary->IsKey(k)) {
|
||||
if (element_dictionary->IsKey(isolate, k)) {
|
||||
Handle<Object> value(element_dictionary->ValueAt(i), isolate);
|
||||
if (value->IsJSObject()) {
|
||||
Handle<JSObject> result;
|
||||
@ -15373,10 +15374,11 @@ int JSObject::GetFastElementsUsage() {
|
||||
#ifdef OBJECT_PRINT
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) { // NOLINT
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
if (this->IsKey(isolate, k)) {
|
||||
os << "\n ";
|
||||
if (k->IsString()) {
|
||||
String::cast(k)->StringPrint(os);
|
||||
@ -15397,13 +15399,14 @@ void Dictionary<Derived, Shape, Key>::Print() {
|
||||
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int pos = 0;
|
||||
int capacity = this->Capacity();
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
if (this->IsKey(isolate, k)) {
|
||||
elements->set(pos++, this->ValueAt(i), mode);
|
||||
}
|
||||
}
|
||||
@ -16208,6 +16211,7 @@ template<typename Derived, typename Shape, typename Key>
|
||||
void HashTable<Derived, Shape, Key>::Rehash(Key key) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
|
||||
Isolate* isolate = GetIsolate();
|
||||
uint32_t capacity = Capacity();
|
||||
bool done = false;
|
||||
for (int probe = 1; !done; probe++) {
|
||||
@ -16216,7 +16220,7 @@ void HashTable<Derived, Shape, Key>::Rehash(Key key) {
|
||||
done = true;
|
||||
for (uint32_t current = 0; current < capacity; current++) {
|
||||
Object* current_key = get(EntryToIndex(current));
|
||||
if (IsKey(current_key)) {
|
||||
if (IsKey(isolate, current_key)) {
|
||||
uint32_t target = EntryForProbe(key, current_key, probe, current);
|
||||
if (current == target) continue;
|
||||
Object* target_key = get(EntryToIndex(target));
|
||||
@ -16235,9 +16239,8 @@ void HashTable<Derived, Shape, Key>::Rehash(Key key) {
|
||||
}
|
||||
}
|
||||
// Wipe deleted entries.
|
||||
Heap* heap = GetHeap();
|
||||
Object* the_hole = heap->the_hole_value();
|
||||
Object* undefined = heap->undefined_value();
|
||||
Object* the_hole = isolate->heap()->the_hole_value();
|
||||
Object* undefined = isolate->heap()->undefined_value();
|
||||
for (uint32_t current = 0; current < capacity; current++) {
|
||||
if (get(EntryToIndex(current)) == the_hole) {
|
||||
set(EntryToIndex(current), undefined);
|
||||
@ -16328,12 +16331,10 @@ 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();
|
||||
Isolate* isolate = GetIsolate();
|
||||
while (true) {
|
||||
Object* element = KeyAt(entry);
|
||||
if (element == the_hole || element == undefined) break;
|
||||
if (!IsKey(isolate, element)) break;
|
||||
entry = NextProbe(entry, count++, capacity);
|
||||
}
|
||||
return entry;
|
||||
@ -16525,7 +16526,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
|
||||
DisallowHeapAllocation no_gc;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = dict->KeyAt(i);
|
||||
if (!dict->IsKey(k)) continue;
|
||||
if (!dict->IsKey(isolate, k)) continue;
|
||||
|
||||
DCHECK(k->IsNumber());
|
||||
DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
|
||||
@ -17164,7 +17165,8 @@ Handle<Derived> Dictionary<Derived, Shape, Key>::New(
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
|
||||
Handle<Derived> dictionary) {
|
||||
Factory* factory = dictionary->GetIsolate()->factory();
|
||||
Isolate* isolate = dictionary->GetIsolate();
|
||||
Factory* factory = isolate->factory();
|
||||
int length = dictionary->NumberOfElements();
|
||||
|
||||
Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
|
||||
@ -17175,7 +17177,7 @@ Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
|
||||
int capacity = dictionary->Capacity();
|
||||
int pos = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
if (dictionary->IsKey(dictionary->KeyAt(i))) {
|
||||
if (dictionary->IsKey(isolate, dictionary->KeyAt(i))) {
|
||||
int index = dictionary->DetailsAt(i).dictionary_index();
|
||||
iteration_order->set(pos, Smi::FromInt(i));
|
||||
enumeration_order->set(pos, Smi::FromInt(index));
|
||||
@ -17322,17 +17324,17 @@ void Dictionary<Derived, Shape, Key>::AddEntry(
|
||||
|
||||
bool SeededNumberDictionary::HasComplexElements() {
|
||||
if (!requires_slow_elements()) return false;
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
if (!this->IsKey(isolate, k)) continue;
|
||||
DCHECK(!IsDeleted(i));
|
||||
PropertyDetails details = this->DetailsAt(i);
|
||||
if (details.type() == ACCESSOR_CONSTANT) return true;
|
||||
PropertyAttributes attr = details.attributes();
|
||||
if (attr & ALL_ATTRIBUTES_MASK) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -17427,11 +17429,12 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
|
||||
PropertyFilter filter) {
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int capacity = this->Capacity();
|
||||
int result = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !k->FilterKey(filter)) {
|
||||
if (this->IsKey(isolate, k) && !k->FilterKey(filter)) {
|
||||
if (this->IsDeleted(i)) continue;
|
||||
PropertyDetails details = this->DetailsAt(i);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
@ -17456,12 +17459,13 @@ struct EnumIndexComparator {
|
||||
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int length = storage->length();
|
||||
int capacity = this->Capacity();
|
||||
int properties = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k) && !k->IsSymbol()) {
|
||||
if (this->IsKey(isolate, k) && !k->IsSymbol()) {
|
||||
PropertyDetails details = this->DetailsAt(i);
|
||||
if (details.IsDontEnum() || this->IsDeleted(i)) continue;
|
||||
storage->set(properties, Smi::FromInt(i));
|
||||
@ -17483,9 +17487,10 @@ template <typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
||||
Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
|
||||
PropertyFilter filter) {
|
||||
Isolate* isolate = keys->isolate();
|
||||
int capacity = dictionary->Capacity();
|
||||
Handle<FixedArray> array =
|
||||
keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
|
||||
isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
|
||||
int array_size = 0;
|
||||
|
||||
{
|
||||
@ -17493,7 +17498,7 @@ void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
||||
Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = raw_dict->KeyAt(i);
|
||||
if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
|
||||
if (!raw_dict->IsKey(isolate, k) || k->FilterKey(filter)) continue;
|
||||
if (raw_dict->IsDeleted(i)) continue;
|
||||
PropertyDetails details = raw_dict->DetailsAt(i);
|
||||
if ((details.attributes() & filter) != 0) continue;
|
||||
@ -17538,10 +17543,11 @@ void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
||||
// Backwards lookup (slow).
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = this->KeyAt(i);
|
||||
if (this->IsKey(k)) {
|
||||
if (!this->IsKey(isolate, k)) continue;
|
||||
Object* e = this->ValueAt(i);
|
||||
// TODO(dcarney): this should be templatized.
|
||||
if (e->IsPropertyCell()) {
|
||||
@ -17549,16 +17555,14 @@ Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
|
||||
}
|
||||
if (e == value) return k;
|
||||
}
|
||||
}
|
||||
Heap* heap = Dictionary::GetHeap();
|
||||
return heap->undefined_value();
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
|
||||
int32_t hash) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
DCHECK(IsKey(*key));
|
||||
DCHECK(IsKey(isolate, *key));
|
||||
|
||||
int entry = FindEntry(isolate, key, hash);
|
||||
if (entry == kNotFound) return isolate->heap()->the_hole_value();
|
||||
@ -17568,9 +17572,9 @@ Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
|
||||
|
||||
Object* ObjectHashTable::Lookup(Handle<Object> key) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
DCHECK(IsKey(*key));
|
||||
|
||||
Isolate* isolate = GetIsolate();
|
||||
DCHECK(IsKey(isolate, *key));
|
||||
|
||||
// If the object does not have an identity hash, it was never used as a key.
|
||||
Object* hash = key->GetHash();
|
||||
@ -17590,8 +17594,7 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
||||
Handle<Object> key,
|
||||
Handle<Object> value) {
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
|
||||
DCHECK(table->IsKey(*key));
|
||||
DCHECK(table->IsKey(isolate, *key));
|
||||
DCHECK(!value->IsTheHole(isolate));
|
||||
|
||||
// Make sure the key object has an identity hash code.
|
||||
@ -17606,8 +17609,7 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
||||
Handle<Object> value,
|
||||
int32_t hash) {
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
|
||||
DCHECK(table->IsKey(*key));
|
||||
DCHECK(table->IsKey(isolate, *key));
|
||||
DCHECK(!value->IsTheHole(isolate));
|
||||
|
||||
int entry = table->FindEntry(isolate, key, hash);
|
||||
@ -17634,7 +17636,7 @@ Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
|
||||
Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
|
||||
Handle<Object> key,
|
||||
bool* was_present) {
|
||||
DCHECK(table->IsKey(*key));
|
||||
DCHECK(table->IsKey(table->GetIsolate(), *key));
|
||||
|
||||
Object* hash = key->GetHash();
|
||||
if (hash->IsUndefined(table->GetIsolate())) {
|
||||
@ -17650,9 +17652,10 @@ Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
|
||||
Handle<Object> key,
|
||||
bool* was_present,
|
||||
int32_t hash) {
|
||||
DCHECK(table->IsKey(*key));
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
DCHECK(table->IsKey(isolate, *key));
|
||||
|
||||
int entry = table->FindEntry(table->GetIsolate(), key, hash);
|
||||
int entry = table->FindEntry(isolate, key, hash);
|
||||
if (entry == kNotFound) {
|
||||
*was_present = false;
|
||||
return table;
|
||||
@ -17680,9 +17683,10 @@ void ObjectHashTable::RemoveEntry(int entry) {
|
||||
|
||||
Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
DCHECK(IsKey(*key));
|
||||
Isolate* isolate = GetIsolate();
|
||||
DCHECK(IsKey(isolate, *key));
|
||||
int entry = FindEntry(key);
|
||||
if (entry == kNotFound) return GetHeap()->the_hole_value();
|
||||
if (entry == kNotFound) return isolate->heap()->the_hole_value();
|
||||
return get(EntryToValueIndex(entry));
|
||||
}
|
||||
|
||||
@ -17690,7 +17694,8 @@ Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
|
||||
Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
|
||||
Handle<HeapObject> key,
|
||||
Handle<HeapObject> value) {
|
||||
DCHECK(table->IsKey(*key));
|
||||
Isolate* isolate = key->GetIsolate();
|
||||
DCHECK(table->IsKey(isolate, *key));
|
||||
int entry = table->FindEntry(key);
|
||||
// Key is already in table, just overwrite value.
|
||||
if (entry != kNotFound) {
|
||||
@ -17698,7 +17703,7 @@ Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
|
||||
return table;
|
||||
}
|
||||
|
||||
Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
|
||||
Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
|
||||
|
||||
// Check whether the hash table should be extended.
|
||||
table = EnsureCapacity(table, 1, key, TENURED);
|
||||
@ -17792,11 +17797,14 @@ Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
|
||||
template <class Derived, class Iterator, int entrysize>
|
||||
bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
|
||||
Handle<Derived> table, Handle<Object> key) {
|
||||
int entry = table->KeyToFirstEntry(*key);
|
||||
DisallowHeapAllocation no_gc;
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
Object* raw_key = *key;
|
||||
int entry = table->KeyToFirstEntry(isolate, raw_key);
|
||||
// Walk the chain in the bucket to find the key.
|
||||
while (entry != kNotFound) {
|
||||
Object* candidate_key = table->KeyAt(entry);
|
||||
if (candidate_key->SameValueZero(*key)) return true;
|
||||
if (candidate_key->SameValueZero(raw_key)) return true;
|
||||
entry = table->NextChainEntry(entry);
|
||||
}
|
||||
return false;
|
||||
@ -17856,11 +17864,11 @@ 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(
|
||||
isolate, new_capacity, heap->InNewSpace(*table) ? NOT_TENURED : TENURED);
|
||||
Handle<Derived> new_table =
|
||||
Allocate(isolate, new_capacity,
|
||||
isolate->heap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
|
||||
int nof = table->NumberOfElements();
|
||||
int nod = table->NumberOfDeletedElements();
|
||||
int new_buckets = new_table->NumberOfBuckets();
|
||||
@ -17868,10 +17876,9 @@ Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
|
||||
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 == the_hole) {
|
||||
if (key->IsTheHole(isolate)) {
|
||||
table->SetRemovedIndexAt(removed_holes_index++, old_entry);
|
||||
continue;
|
||||
}
|
||||
|
@ -3154,7 +3154,7 @@ class HashTableBase : public FixedArray {
|
||||
// Tells whether k is a real key. The hole and undefined are not allowed
|
||||
// as keys and can be used to indicate missing or deleted elements.
|
||||
inline bool IsKey(Object* k);
|
||||
inline bool IsKey(Heap* heap, Object* k);
|
||||
inline bool IsKey(Isolate* isolate, Object* k);
|
||||
|
||||
// Compute the probe offset (quadratic probing).
|
||||
INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
|
||||
@ -3879,10 +3879,10 @@ class OrderedHashTable: public FixedArray {
|
||||
return Smi::cast(entry)->value();
|
||||
}
|
||||
|
||||
int KeyToFirstEntry(Object* key) {
|
||||
int KeyToFirstEntry(Isolate* isolate, Object* key) {
|
||||
Object* hash = key->GetHash();
|
||||
// If the object does not have an identity hash, it was never used as a key
|
||||
if (hash->IsUndefined(GetIsolate())) return kNotFound;
|
||||
if (hash->IsUndefined(isolate)) return kNotFound;
|
||||
return HashToEntry(Smi::cast(hash)->value());
|
||||
}
|
||||
|
||||
|
@ -1558,6 +1558,7 @@ void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
|
||||
|
||||
|
||||
void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
Isolate* isolate = js_obj->GetIsolate();
|
||||
if (js_obj->HasFastProperties()) {
|
||||
DescriptorArray* descs = js_obj->map()->instance_descriptors();
|
||||
int real_size = js_obj->map()->NumberOfOwnDescriptors();
|
||||
@ -1591,7 +1592,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
int length = dictionary->Capacity();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Object* k = dictionary->KeyAt(i);
|
||||
if (dictionary->IsKey(k)) {
|
||||
if (dictionary->IsKey(isolate, k)) {
|
||||
DCHECK(dictionary->ValueAt(i)->IsPropertyCell());
|
||||
PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(i));
|
||||
Object* value = cell->value();
|
||||
@ -1605,7 +1606,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
int length = dictionary->Capacity();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Object* k = dictionary->KeyAt(i);
|
||||
if (dictionary->IsKey(k)) {
|
||||
if (dictionary->IsKey(isolate, k)) {
|
||||
Object* value = dictionary->ValueAt(i);
|
||||
PropertyDetails details = dictionary->DetailsAt(i);
|
||||
SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
|
||||
@ -1635,13 +1636,14 @@ void V8HeapExplorer::ExtractAccessorPairProperty(JSObject* js_obj, int entry,
|
||||
|
||||
|
||||
void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
|
||||
Isolate* isolate = js_obj->GetIsolate();
|
||||
if (js_obj->HasFastObjectElements()) {
|
||||
FixedArray* elements = FixedArray::cast(js_obj->elements());
|
||||
int length = js_obj->IsJSArray() ?
|
||||
Smi::cast(JSArray::cast(js_obj)->length())->value() :
|
||||
elements->length();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (!elements->get(i)->IsTheHole(heap_->isolate())) {
|
||||
if (!elements->get(i)->IsTheHole(isolate)) {
|
||||
SetElementReference(js_obj, entry, i, elements->get(i));
|
||||
}
|
||||
}
|
||||
@ -1650,7 +1652,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
|
||||
int length = dictionary->Capacity();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Object* k = dictionary->KeyAt(i);
|
||||
if (dictionary->IsKey(heap_, k)) {
|
||||
if (dictionary->IsKey(isolate, k)) {
|
||||
DCHECK(k->IsNumber());
|
||||
uint32_t index = static_cast<uint32_t>(k->Number());
|
||||
SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
|
||||
|
@ -250,7 +250,7 @@ RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
|
||||
int count = 0;
|
||||
for (int i = 0; count / 2 < max_entries && i < table->Capacity(); i++) {
|
||||
Handle<Object> key(table->KeyAt(i), isolate);
|
||||
if (table->IsKey(*key)) {
|
||||
if (table->IsKey(isolate, *key)) {
|
||||
entries->set(count++, *key);
|
||||
Object* value = table->Lookup(key);
|
||||
entries->set(count++, value);
|
||||
@ -289,7 +289,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
|
||||
RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
|
||||
Handle<ObjectHashTable> table(
|
||||
ObjectHashTable::cast(weak_collection->table()));
|
||||
RUNTIME_ASSERT(table->IsKey(*key));
|
||||
RUNTIME_ASSERT(table->IsKey(isolate, *key));
|
||||
Handle<Object> lookup(table->Lookup(key, hash), isolate);
|
||||
return lookup->IsTheHole(isolate) ? isolate->heap()->undefined_value()
|
||||
: *lookup;
|
||||
@ -305,7 +305,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
|
||||
RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
|
||||
Handle<ObjectHashTable> table(
|
||||
ObjectHashTable::cast(weak_collection->table()));
|
||||
RUNTIME_ASSERT(table->IsKey(*key));
|
||||
RUNTIME_ASSERT(table->IsKey(isolate, *key));
|
||||
Handle<Object> lookup(table->Lookup(key, hash), isolate);
|
||||
return isolate->heap()->ToBoolean(!lookup->IsTheHole(isolate));
|
||||
}
|
||||
@ -320,7 +320,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
|
||||
RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
|
||||
Handle<ObjectHashTable> table(
|
||||
ObjectHashTable::cast(weak_collection->table()));
|
||||
RUNTIME_ASSERT(table->IsKey(*key));
|
||||
RUNTIME_ASSERT(table->IsKey(isolate, *key));
|
||||
bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
|
||||
return isolate->heap()->ToBoolean(was_present);
|
||||
}
|
||||
@ -336,7 +336,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
|
||||
CONVERT_SMI_ARG_CHECKED(hash, 3)
|
||||
Handle<ObjectHashTable> table(
|
||||
ObjectHashTable::cast(weak_collection->table()));
|
||||
RUNTIME_ASSERT(table->IsKey(*key));
|
||||
RUNTIME_ASSERT(table->IsKey(isolate, *key));
|
||||
JSWeakCollection::Set(weak_collection, key, value, hash);
|
||||
return *weak_collection;
|
||||
}
|
||||
@ -362,8 +362,8 @@ RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
int count = 0;
|
||||
for (int i = 0; count < max_values && i < table->Capacity(); i++) {
|
||||
Handle<Object> key(table->KeyAt(i), isolate);
|
||||
if (table->IsKey(*key)) values->set(count++, *key);
|
||||
Object* key = table->KeyAt(i);
|
||||
if (table->IsKey(isolate, key)) values->set(count++, key);
|
||||
}
|
||||
DCHECK_EQ(max_values, count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user