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

Side by Side Diff: src/objects.cc

Issue 1316213008: Speedup JSReceiver::GetKeys (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixing DCHECK Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <iomanip> 7 #include <iomanip>
8 #include <sstream> 8 #include <sstream>
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 6572 matching lines...) Expand 10 before | Expand all | Expand 10 after
6583 if (length == 0) { 6583 if (length == 0) {
6584 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 6584 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6585 } 6585 }
6586 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 6586 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6587 dictionary->CopyEnumKeysTo(*storage); 6587 dictionary->CopyEnumKeysTo(*storage);
6588 return storage; 6588 return storage;
6589 } 6589 }
6590 } 6590 }
6591 6591
6592 6592
6593 Handle<FixedArray> KeyAccumulator::GetKeys() {
6594 if (length_ == 0) {
6595 return isolate_->factory()->empty_fixed_array();
6596 }
6597 if (set_.is_null()) {
6598 keys_->Shrink(length_);
6599 return keys_;
6600 }
6601 // copy over results from set_
6602 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_);
6603 for (int i = 0; i < length_; i++) {
6604 result->set(i, set_->KeyAt(i));
6605 }
6606 return result;
6607 }
6608
6609
6610 int KeyAccumulator::GetLength() { return length_; }
6611
6612
6613 void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) {
6614 #ifdef ENABLE_SLOW_DCHECKS
6615 if (FLAG_enable_slow_asserts) {
6616 DCHECK(key->IsNumber() || key->IsName());
6617 }
6618 #endif
6619 if (!set_.is_null()) {
6620 set_ = OrderedHashSet::Add(set_, key);
6621 length_ = set_->NumberOfElements();
6622 return;
6623 }
6624 // check if we already have the key in the case we are still using
6625 // the keys_ FixedArray
6626 check_limit = Min(check_limit, length_);
6627 for (int i = 0; i < check_limit; i++) {
6628 Object* current = keys_->get(i);
6629 if (current->KeyEquals(*key)) return;
6630 }
6631 EnsureCapacity(length_);
6632 keys_->set(length_, *key);
6633 length_++;
6634 }
6635
6636
6637 void KeyAccumulator::AddKeys(Handle<FixedArray> array,
6638 FixedArray::KeyFilter filter) {
6639 int add_length = array->length();
6640 if (add_length == 0) return;
6641 if (keys_.is_null() && filter == FixedArray::ALL_KEYS) {
6642 keys_ = array;
6643 length_ = keys_->length();
6644 return;
6645 }
6646 PrepareForComparisons(add_length);
6647 int previous_key_count = length_;
6648 for (int i = 0; i < add_length; i++) {
6649 Handle<Object> current(array->get(i), isolate_);
6650 if (filter == FixedArray::NON_SYMBOL_KEYS && current->IsSymbol()) continue;
6651 AddKey(current, previous_key_count);
6652 }
6653 }
6654
6655
6656 void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
6657 FixedArray::KeyFilter filter) {
6658 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
6659 ElementsAccessor* accessor = array_like->GetElementsAccessor();
6660 accessor->AddElementsToFixedArrayWithAccumulator(array_like, this, filter);
6661 }
6662
6663
6664 void KeyAccumulator::PrepareForComparisons(int count) {
6665 // Depending on how many comparisons we do we should switch to the
6666 // hash-table-based checks which have a one-time overhead for
6667 // initializing but O(1) for HasKey checks.
6668 if (!set_.is_null()) return;
6669 // This limit was obtained through evaluation of a microbench.
6670 if (length_ * count < 50) return;
6671 set_ = OrderedHashSet::Allocate(isolate_, length_);
6672 for (int i = 0; i < length_; i++) {
6673 Handle<Object> value(keys_->get(i), isolate_);
6674 set_ = OrderedHashSet::Add(set_, value);
6675 }
6676 }
6677
6678
6679 void KeyAccumulator::EnsureCapacity(int capacity) {
6680 if (keys_.is_null() || keys_->length() <= capacity) {
6681 Grow();
6682 }
6683 }
6684
6685
6686 void KeyAccumulator::Grow() {
6687 // The OrderedHashSet handles growing by itself.
6688 if (!set_.is_null()) return;
6689 // Otherwise, grow the internal keys_ FixedArray
6690 int capacity = keys_.is_null() ? 16 : keys_->length() * 2 + 16;
6691 Handle<FixedArray> new_keys = isolate_->factory()->NewFixedArray(capacity);
6692 if (keys_.is_null()) {
6693 keys_ = new_keys;
6694 return;
6695 }
6696 int buffer_length = keys_->length();
6697 {
6698 DisallowHeapAllocation no_gc;
6699 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc);
6700 for (int i = 0; i < buffer_length; i++) {
6701 new_keys->set(i, keys_->get(i), mode);
6702 }
6703 }
6704 keys_ = new_keys;
6705 }
6706
6707
6593 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 6708 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6594 KeyCollectionType type) { 6709 KeyCollectionType type) {
6595 USE(ContainsOnlyValidKeys); 6710 USE(ContainsOnlyValidKeys);
6596 Isolate* isolate = object->GetIsolate(); 6711 Isolate* isolate = object->GetIsolate();
6597 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); 6712 KeyAccumulator accumulator(isolate);
6598 Handle<JSFunction> arguments_function( 6713 Handle<JSFunction> arguments_function(
6599 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 6714 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6600 6715
6601 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 6716 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6602 ? PrototypeIterator::END_AT_NON_HIDDEN 6717 ? PrototypeIterator::END_AT_NON_HIDDEN
6603 : PrototypeIterator::END_AT_NULL; 6718 : PrototypeIterator::END_AT_NULL;
6604 // Only collect keys if access is permitted. 6719 // Only collect keys if access is permitted.
6605 for (PrototypeIterator iter(isolate, object, 6720 for (PrototypeIterator iter(isolate, object,
6606 PrototypeIterator::START_AT_RECEIVER); 6721 PrototypeIterator::START_AT_RECEIVER);
6607 !iter.IsAtEnd(end); iter.Advance()) { 6722 !iter.IsAtEnd(end); iter.Advance()) {
6608 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 6723 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6609 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 6724 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
6610 Handle<Object> args[] = { proxy }; 6725 Handle<Object> args[] = { proxy };
6611 Handle<Object> names; 6726 Handle<Object> names;
6612 ASSIGN_RETURN_ON_EXCEPTION( 6727 ASSIGN_RETURN_ON_EXCEPTION(
6613 isolate, names, 6728 isolate, names,
6614 Execution::Call(isolate, 6729 Execution::Call(isolate,
6615 isolate->proxy_enumerate(), 6730 isolate->proxy_enumerate(),
6616 object, 6731 object,
6617 arraysize(args), 6732 arraysize(args),
6618 args), 6733 args),
6619 FixedArray); 6734 FixedArray);
6620 ASSIGN_RETURN_ON_EXCEPTION( 6735 accumulator.AddKeys(Handle<JSObject>::cast(names),
6621 isolate, content, 6736 FixedArray::NON_SYMBOL_KEYS);
Igor Sheludko 2015/09/17 09:55:12 Why do you use a different filter than in the old
Camillo Bruni 2015/09/17 11:01:08 my mistake :)
6622 FixedArray::AddKeysFromArrayLike(
6623 content, Handle<JSObject>::cast(names)),
6624 FixedArray);
6625 break; 6737 break;
6626 } 6738 }
6627 6739
6628 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 6740 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
6629 6741
6630 // Check access rights if required. 6742 // Check access rights if required.
6631 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { 6743 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6632 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 6744 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6633 isolate->ReportFailedAccessCheck(current); 6745 isolate->ReportFailedAccessCheck(current);
6634 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); 6746 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6635 } 6747 }
6636 break; 6748 break;
6637 } 6749 }
6638 6750
6639 // Compute the element keys. 6751 // Compute the element keys.
6640 Handle<FixedArray> element_keys = 6752 Handle<FixedArray> element_keys =
6641 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); 6753 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6642 current->GetEnumElementKeys(*element_keys); 6754 current->GetEnumElementKeys(*element_keys);
6643 ASSIGN_RETURN_ON_EXCEPTION( 6755 accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS);
6644 isolate, content, 6756 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6645 FixedArray::UnionOfKeys(content, element_keys),
6646 FixedArray);
6647 DCHECK(ContainsOnlyValidKeys(content));
6648 6757
6649 // Add the element keys from the interceptor. 6758 // Add the element keys from the interceptor.
6650 if (current->HasIndexedInterceptor()) { 6759 if (current->HasIndexedInterceptor()) {
6651 Handle<JSObject> result; 6760 Handle<JSObject> result;
6652 if (JSObject::GetKeysForIndexedInterceptor( 6761 if (JSObject::GetKeysForIndexedInterceptor(
6653 current, object).ToHandle(&result)) { 6762 current, object).ToHandle(&result)) {
6654 ASSIGN_RETURN_ON_EXCEPTION( 6763 accumulator.AddKeys(result, FixedArray::ALL_KEYS);
6655 isolate, content,
6656 FixedArray::AddKeysFromArrayLike(content, result),
6657 FixedArray);
6658 } 6764 }
6659 DCHECK(ContainsOnlyValidKeys(content)); 6765 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6660 } 6766 }
6661 6767
6662 // We can cache the computed property keys if access checks are 6768 // We can cache the computed property keys if access checks are
6663 // not needed and no interceptors are involved. 6769 // not needed and no interceptors are involved.
6664 // 6770 //
6665 // We do not use the cache if the object has elements and 6771 // We do not use the cache if the object has elements and
6666 // therefore it does not make sense to cache the property names 6772 // therefore it does not make sense to cache the property names
6667 // for arguments objects. Arguments objects will always have 6773 // for arguments objects. Arguments objects will always have
6668 // elements. 6774 // elements.
6669 // Wrapped strings have elements, but don't have an elements 6775 // Wrapped strings have elements, but don't have an elements
6670 // array or dictionary. So the fast inline test for whether to 6776 // array or dictionary. So the fast inline test for whether to
6671 // use the cache says yes, so we should not create a cache. 6777 // use the cache says yes, so we should not create a cache.
6672 bool cache_enum_keys = 6778 bool cache_enum_keys =
6673 ((current->map()->GetConstructor() != *arguments_function) && 6779 ((current->map()->GetConstructor() != *arguments_function) &&
6674 !current->IsJSValue() && !current->IsAccessCheckNeeded() && 6780 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6675 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); 6781 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6676 // Compute the property keys and cache them if possible. 6782 // Compute the property keys and cache them if possible.
6677 ASSIGN_RETURN_ON_EXCEPTION( 6783
6678 isolate, content, 6784 Handle<FixedArray> enum_keys =
6679 FixedArray::UnionOfKeys( 6785 JSObject::GetEnumPropertyKeys(current, cache_enum_keys);
6680 content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)), 6786 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS);
6681 FixedArray); 6787 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6682 DCHECK(ContainsOnlyValidKeys(content));
6683 6788
6684 // Add the non-symbol property keys from the interceptor. 6789 // Add the non-symbol property keys from the interceptor.
6685 if (current->HasNamedInterceptor()) { 6790 if (current->HasNamedInterceptor()) {
6686 Handle<JSObject> result; 6791 Handle<JSObject> result;
6687 if (JSObject::GetKeysForNamedInterceptor( 6792 if (JSObject::GetKeysForNamedInterceptor(
6688 current, object).ToHandle(&result)) { 6793 current, object).ToHandle(&result)) {
6689 ASSIGN_RETURN_ON_EXCEPTION( 6794 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS);
6690 isolate, content, FixedArray::AddKeysFromArrayLike(
6691 content, result, FixedArray::NON_SYMBOL_KEYS),
6692 FixedArray);
6693 } 6795 }
6694 DCHECK(ContainsOnlyValidKeys(content)); 6796 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6695 } 6797 }
6696 } 6798 }
6697 return content; 6799
6800 Handle<FixedArray> keys = accumulator.GetKeys();
6801 DCHECK(ContainsOnlyValidKeys(keys));
6802 return keys;
6698 } 6803 }
6699 6804
6700 6805
6701 bool Map::DictionaryElementsInPrototypeChainOnly() { 6806 bool Map::DictionaryElementsInPrototypeChainOnly() {
6702 if (IsDictionaryElementsKind(elements_kind())) { 6807 if (IsDictionaryElementsKind(elements_kind())) {
6703 return false; 6808 return false;
6704 } 6809 }
6705 6810
6706 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { 6811 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6707 // Be conservative, don't walk into proxies. 6812 // Be conservative, don't walk into proxies.
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after
8188 8293
8189 void FixedArray::Shrink(int new_length) { 8294 void FixedArray::Shrink(int new_length) {
8190 DCHECK(0 <= new_length && new_length <= length()); 8295 DCHECK(0 <= new_length && new_length <= length());
8191 if (new_length < length()) { 8296 if (new_length < length()) {
8192 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( 8297 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
8193 this, length() - new_length); 8298 this, length() - new_length);
8194 } 8299 }
8195 } 8300 }
8196 8301
8197 8302
8198 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8199 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
8200 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
8201 ElementsAccessor* accessor = array->GetElementsAccessor();
8202 Handle<FixedArray> result =
8203 accessor->AddElementsToFixedArray(array, content, filter);
8204
8205 #ifdef ENABLE_SLOW_DCHECKS
8206 if (FLAG_enable_slow_asserts) {
8207 DisallowHeapAllocation no_allocation;
8208 for (int i = 0; i < result->length(); i++) {
8209 Object* current = result->get(i);
8210 DCHECK(current->IsNumber() || current->IsName());
8211 }
8212 }
8213 #endif
8214 return result;
8215 }
8216
8217
8218 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8219 Handle<FixedArray> second) {
8220 if (second->length() == 0) return first;
8221 if (first->length() == 0) return second;
8222 Isolate* isolate = first->GetIsolate();
8223 Handle<FixedArray> result =
8224 isolate->factory()->NewFixedArray(first->length() + second->length());
8225 for (int i = 0; i < first->length(); i++) {
8226 result->set(i, first->get(i));
8227 }
8228 int pos = first->length();
8229 for (int j = 0; j < second->length(); j++) {
8230 Object* current = second->get(j);
8231 int i;
8232 for (i = 0; i < first->length(); i++) {
8233 if (current->KeyEquals(first->get(i))) break;
8234 }
8235 if (i == first->length()) {
8236 result->set(pos++, current);
8237 }
8238 }
8239
8240 result->Shrink(pos);
8241 return result;
8242 }
8243
8244
8245 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { 8303 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8246 DisallowHeapAllocation no_gc; 8304 DisallowHeapAllocation no_gc;
8247 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); 8305 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8248 for (int index = 0; index < len; index++) { 8306 for (int index = 0; index < len; index++) {
8249 dest->set(dest_pos+index, get(pos+index), mode); 8307 dest->set(dest_pos+index, get(pos+index), mode);
8250 } 8308 }
8251 } 8309 }
8252 8310
8253 8311
8254 #ifdef DEBUG 8312 #ifdef DEBUG
(...skipping 7109 matching lines...) Expand 10 before | Expand all | Expand 10 after
15364 15422
15365 15423
15366 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { 15424 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
15367 return Lookup(GetIsolate(), key, hash); 15425 return Lookup(GetIsolate(), key, hash);
15368 } 15426 }
15369 15427
15370 15428
15371 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, 15429 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15372 Handle<Object> key, 15430 Handle<Object> key,
15373 Handle<Object> value) { 15431 Handle<Object> value) {
15432 Isolate* isolate = table->GetIsolate();
Igor Sheludko 2015/09/17 09:55:12 Spurious change.
Camillo Bruni 2015/09/17 11:01:08 reverted
15374 DCHECK(table->IsKey(*key)); 15433 DCHECK(table->IsKey(*key));
15375 DCHECK(!value->IsTheHole()); 15434 DCHECK(!value->IsTheHole());
15376 15435
15377 Isolate* isolate = table->GetIsolate();
15378 // Make sure the key object has an identity hash code. 15436 // Make sure the key object has an identity hash code.
15379 int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); 15437 int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
15380 15438
15381 return Put(table, key, value, hash); 15439 return Put(table, key, value, hash);
15382 } 15440 }
15383 15441
15384 15442
15385 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, 15443 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15386 Handle<Object> key, 15444 Handle<Object> key,
15387 Handle<Object> value, 15445 Handle<Object> value,
15388 int32_t hash) { 15446 int32_t hash) {
15447 Isolate* isolate = table->GetIsolate();
Igor Sheludko 2015/09/17 09:55:12 Spurious change.
Camillo Bruni 2015/09/17 11:01:08 reverted
15389 DCHECK(table->IsKey(*key)); 15448 DCHECK(table->IsKey(*key));
15390 DCHECK(!value->IsTheHole()); 15449 DCHECK(!value->IsTheHole());
15391 15450
15392 Isolate* isolate = table->GetIsolate();
15393
15394 int entry = table->FindEntry(isolate, key, hash); 15451 int entry = table->FindEntry(isolate, key, hash);
15395 15452
15396 // Key is already in table, just overwrite value. 15453 // Key is already in table, just overwrite value.
15397 if (entry != kNotFound) { 15454 if (entry != kNotFound) {
15398 table->set(EntryToIndex(entry) + 1, *value); 15455 table->set(EntryToIndex(entry) + 1, *value);
15399 return table; 15456 return table;
15400 } 15457 }
15401 15458
15402 // Check whether the hash table should be extended. 15459 // Check whether the hash table should be extended.
15403 table = EnsureCapacity(table, 1, key); 15460 table = EnsureCapacity(table, 1, key);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
15557 Allocate(table->GetIsolate(), 15614 Allocate(table->GetIsolate(),
15558 kMinCapacity, 15615 kMinCapacity,
15559 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); 15616 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15560 15617
15561 table->SetNextTable(*new_table); 15618 table->SetNextTable(*new_table);
15562 table->SetNumberOfDeletedElements(kClearedTableSentinel); 15619 table->SetNumberOfDeletedElements(kClearedTableSentinel);
15563 15620
15564 return new_table; 15621 return new_table;
15565 } 15622 }
15566 15623
15624 template <class Derived, class Iterator, int entrysize>
15625 bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
15626 Handle<Derived> table, Handle<Object> key) {
15627 int entry = table->KeyToFirstEntry(*key);
15628 // Walk the chain in the bucket to find the key.
15629 while (entry != kNotFound) {
15630 Object* candidate_key = table->KeyAt(entry);
15631 if (candidate_key->SameValueZero(*key)) return true;
15632 entry = table->NextChainEntry(entry);
15633 }
15634 return false;
15635 }
15636
15637
15638 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
15639 Handle<Object> key) {
15640 int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
15641 int entry = table->HashToEntry(hash);
15642 // Walk the chain of the bucket and try finding the key.
15643 while (entry != kNotFound) {
15644 Object* candidate_key = table->KeyAt(entry);
15645 // Do not add if we have the key already
15646 if (candidate_key->SameValueZero(*key)) return table;
15647 entry = table->NextChainEntry(entry);
15648 }
15649
15650 table = OrderedHashSet::EnsureGrowable(table);
15651 // Read the enxisting bucket values.
15652 int bucket = table->HashToBucket(hash);
15653 int previous_entry = table->HashToEntry(hash);
15654 int nof = table->NumberOfElements();
15655 // Insert a new entry at the end,
15656 int new_entry = nof + table->NumberOfDeletedElements();
15657 int new_index = table->EntryToIndex(new_entry);
15658 table->set(new_index, *key);
15659 table->set(new_index + 1, Smi::FromInt(previous_entry));
Igor Sheludko 2015/09/17 09:55:12 I think "+ kChainOffset" is better than "+ 1" for
Camillo Bruni 2015/09/17 11:01:08 indeed
15660 // and point the bucket to the new entry.
15661 table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15662 table->SetNumberOfElements(nof + 1);
15663 return table;
15664 }
15665
15567 15666
15568 template<class Derived, class Iterator, int entrysize> 15667 template<class Derived, class Iterator, int entrysize>
15569 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash( 15668 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15570 Handle<Derived> table, int new_capacity) { 15669 Handle<Derived> table, int new_capacity) {
15571 DCHECK(!table->IsObsolete()); 15670 DCHECK(!table->IsObsolete());
15572 15671
15573 Handle<Derived> new_table = 15672 Handle<Derived> new_table =
15574 Allocate(table->GetIsolate(), 15673 Allocate(table->GetIsolate(),
15575 new_capacity, 15674 new_capacity,
15576 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); 15675 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
15619 Handle<OrderedHashSet> table); 15718 Handle<OrderedHashSet> table);
15620 15719
15621 template Handle<OrderedHashSet> 15720 template Handle<OrderedHashSet>
15622 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink( 15721 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15623 Handle<OrderedHashSet> table); 15722 Handle<OrderedHashSet> table);
15624 15723
15625 template Handle<OrderedHashSet> 15724 template Handle<OrderedHashSet>
15626 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear( 15725 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15627 Handle<OrderedHashSet> table); 15726 Handle<OrderedHashSet> table);
15628 15727
15728 template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
15729 Handle<OrderedHashSet> table, Handle<Object> key);
15730
15629 15731
15630 template Handle<OrderedHashMap> 15732 template Handle<OrderedHashMap>
15631 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate( 15733 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15632 Isolate* isolate, int capacity, PretenureFlag pretenure); 15734 Isolate* isolate, int capacity, PretenureFlag pretenure);
15633 15735
15634 template Handle<OrderedHashMap> 15736 template Handle<OrderedHashMap>
15635 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable( 15737 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15636 Handle<OrderedHashMap> table); 15738 Handle<OrderedHashMap> table);
15637 15739
15638 template Handle<OrderedHashMap> 15740 template Handle<OrderedHashMap>
15639 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink( 15741 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15640 Handle<OrderedHashMap> table); 15742 Handle<OrderedHashMap> table);
15641 15743
15642 template Handle<OrderedHashMap> 15744 template Handle<OrderedHashMap>
15643 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear( 15745 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15644 Handle<OrderedHashMap> table); 15746 Handle<OrderedHashMap> table);
15645 15747
15748 template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
15749 Handle<OrderedHashMap> table, Handle<Object> key);
15750
15646 15751
15647 template<class Derived, class TableType> 15752 template<class Derived, class TableType>
15648 void OrderedHashTableIterator<Derived, TableType>::Transition() { 15753 void OrderedHashTableIterator<Derived, TableType>::Transition() {
15649 DisallowHeapAllocation no_allocation; 15754 DisallowHeapAllocation no_allocation;
15650 TableType* table = TableType::cast(this->table()); 15755 TableType* table = TableType::cast(this->table());
15651 if (!table->IsObsolete()) return; 15756 if (!table->IsObsolete()) return;
15652 15757
15653 int index = Smi::cast(this->index())->value(); 15758 int index = Smi::cast(this->index())->value();
15654 while (table->IsObsolete()) { 15759 while (table->IsObsolete()) {
15655 TableType* next_table = table->NextTable(); 15760 TableType* next_table = table->NextTable();
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after
16473 if (cell->value() != *new_value) { 16578 if (cell->value() != *new_value) {
16474 cell->set_value(*new_value); 16579 cell->set_value(*new_value);
16475 Isolate* isolate = cell->GetIsolate(); 16580 Isolate* isolate = cell->GetIsolate();
16476 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16581 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16477 isolate, DependentCode::kPropertyCellChangedGroup); 16582 isolate, DependentCode::kPropertyCellChangedGroup);
16478 } 16583 }
16479 } 16584 }
16480 16585
16481 } // namespace internal 16586 } // namespace internal
16482 } // namespace v8 16587 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698