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

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: Using OrderedHasSet 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
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6462 matching lines...) Expand 10 before | Expand all | Expand 10 after
6473 if (length == 0) { 6473 if (length == 0) {
6474 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 6474 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6475 } 6475 }
6476 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 6476 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6477 dictionary->CopyEnumKeysTo(*storage); 6477 dictionary->CopyEnumKeysTo(*storage);
6478 return storage; 6478 return storage;
6479 } 6479 }
6480 } 6480 }
6481 6481
6482 6482
6483 Handle<FixedArray> KeyAccumulator::GetKeys() {
6484 if (length_ == 0) {
6485 return isolate_->factory()->empty_fixed_array();
6486 }
6487 if (set_.is_null()) {
6488 keys_->Shrink(length_);
6489 return keys_;
6490 }
6491 // copy over results from set_
6492 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_);
6493 for (int i = 0; i < length_; i++) {
6494 result->set(i, set_->KeyAt(i));
6495 }
6496 return result;
6497 }
6498
6499
6500 int KeyAccumulator::GetLength() { return length_; }
Igor Sheludko 2015/09/17 09:55:11 Please move this implementation to the class defin
6501
6502
6503 void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) {
6504 if (!set_.is_null()) {
6505 set_ = OrderedHashSet::Add(set_, key);
6506 length_ = set_->NumberOfElements();
6507 return;
6508 }
6509 // check if we already have the key in the case we are still using
6510 // the keys_ FixedArray
6511 check_limit = Min(check_limit, length_);
6512 for (int i = 0; i < check_limit; i++) {
6513 Object* current = keys_->get(i);
6514 if (current->KeyEquals(*key)) return;
6515 }
6516 EnsureCapacity(length_);
6517 keys_->set(length_, *key);
6518 length_++;
6519 }
6520
6521
6522 void KeyAccumulator::AddKeys(Handle<FixedArray> array,
6523 FixedArray::KeyFilter filter) {
6524 int add_length = array->length();
6525 if (add_length == 0) return;
6526 if (keys_.is_null() && filter == FixedArray::ALL_KEYS) {
6527 keys_ = array;
6528 length_ = keys_->length();
6529 return;
6530 }
6531 PrepareForComparisons(add_length);
6532 int previous_key_count = length_;
6533 for (int i = 0; i < add_length; i++) {
6534 Handle<Object> current(array->get(i), isolate_);
6535 if (filter == FixedArray::NON_SYMBOL_KEYS && current->IsSymbol()) continue;
6536 AddKey(current, previous_key_count);
6537 }
6538 }
6539
6540
6541 void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
6542 FixedArray::KeyFilter filter) {
6543 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
6544 ElementsAccessor* accessor = array_like->GetElementsAccessor();
6545 accessor->AddElementsToFixedArrayWithAccumulator(array_like, this, filter);
6546 #ifdef ENABLE_SLOW_DCHECKS
6547 if (FLAG_enable_slow_asserts) {
6548 DisallowHeapAllocation no_allocation;
6549 for (int i = 0; i < GetLength(); i++) {
6550 Object* current = keys_->get(i);
6551 DCHECK(current->IsNumber() || current->IsName());
6552 }
6553 }
6554 #endif
6555 }
6556
6557
6558 void KeyAccumulator::PrepareForComparisons(int count) {
6559 // Depending on how many comparisons we do we should switch to the
6560 // hash-table-based checks which have a one-time overhead for
6561 // initializing but O(1) for HasKey checks.
6562 if (!set_.is_null()) return;
6563 // This limit was obtained through evaluation of a microbench.
6564 if (length_ * count < 50) return;
6565 set_ = OrderedHashSet::Allocate(isolate_, length_);
6566 for (int i = 0; i < length_; i++) {
6567 Handle<Object> value(keys_->get(i), isolate_);
6568 set_ = OrderedHashSet::Add(set_, value);
6569 }
6570 }
6571
6572
6573 void KeyAccumulator::EnsureCapacity(int capacity) {
6574 if (keys_.is_null() || keys_->length() <= capacity) {
6575 Grow();
6576 }
6577 }
6578
6579
6580 void KeyAccumulator::Grow() {
6581 // The OrderedHashSet handles growing by itself.
6582 if (!set_.is_null()) return;
6583 // Otherwise, grow the internal keys_ FixedArray
6584 int capacity = keys_.is_null() ? 16 : keys_->length() * 2 + 16;
6585 Handle<FixedArray> new_keys = isolate_->factory()->NewFixedArray(capacity);
6586 if (keys_.is_null()) {
6587 keys_ = new_keys;
6588 return;
6589 }
6590 int buffer_length = keys_->length();
6591 {
6592 DisallowHeapAllocation no_gc;
6593 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc);
6594 for (int i = 0; i < buffer_length; i++) {
6595 new_keys->set(i, keys_->get(i), mode);
6596 }
6597 }
6598 keys_ = new_keys;
6599 }
6600
6601
6483 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 6602 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6484 KeyCollectionType type) { 6603 KeyCollectionType type) {
6485 USE(ContainsOnlyValidKeys); 6604 USE(ContainsOnlyValidKeys);
6486 Isolate* isolate = object->GetIsolate(); 6605 Isolate* isolate = object->GetIsolate();
6487 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); 6606 KeyAccumulator accumulator(isolate);
6488 Handle<JSFunction> arguments_function( 6607 Handle<JSFunction> arguments_function(
6489 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 6608 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6490 6609
6491 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 6610 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6492 ? PrototypeIterator::END_AT_NON_HIDDEN 6611 ? PrototypeIterator::END_AT_NON_HIDDEN
6493 : PrototypeIterator::END_AT_NULL; 6612 : PrototypeIterator::END_AT_NULL;
6494 // Only collect keys if access is permitted. 6613 // Only collect keys if access is permitted.
6495 for (PrototypeIterator iter(isolate, object, 6614 for (PrototypeIterator iter(isolate, object,
6496 PrototypeIterator::START_AT_RECEIVER); 6615 PrototypeIterator::START_AT_RECEIVER);
6497 !iter.IsAtEnd(end); iter.Advance()) { 6616 !iter.IsAtEnd(end); iter.Advance()) {
6498 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 6617 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6499 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 6618 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
6500 Handle<Object> args[] = { proxy }; 6619 Handle<Object> args[] = { proxy };
6501 Handle<Object> names; 6620 Handle<Object> names;
6502 ASSIGN_RETURN_ON_EXCEPTION( 6621 ASSIGN_RETURN_ON_EXCEPTION(
6503 isolate, names, 6622 isolate, names,
6504 Execution::Call(isolate, 6623 Execution::Call(isolate,
6505 isolate->proxy_enumerate(), 6624 isolate->proxy_enumerate(),
6506 object, 6625 object,
6507 arraysize(args), 6626 arraysize(args),
6508 args), 6627 args),
6509 FixedArray); 6628 FixedArray);
6510 ASSIGN_RETURN_ON_EXCEPTION( 6629 accumulator.AddKeys(Handle<JSObject>::cast(names),
6511 isolate, content, 6630 FixedArray::NON_SYMBOL_KEYS);
6512 FixedArray::AddKeysFromArrayLike(
6513 content, Handle<JSObject>::cast(names)),
6514 FixedArray);
6515 break; 6631 break;
6516 } 6632 }
6517 6633
6518 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 6634 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
6519 6635
6520 // Check access rights if required. 6636 // Check access rights if required.
6521 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { 6637 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6522 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 6638 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6523 isolate->ReportFailedAccessCheck(current); 6639 isolate->ReportFailedAccessCheck(current);
6524 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); 6640 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6525 } 6641 }
6526 break; 6642 break;
6527 } 6643 }
6528 6644
6529 // Compute the element keys. 6645 // Compute the element keys.
6530 Handle<FixedArray> element_keys = 6646 Handle<FixedArray> element_keys =
6531 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); 6647 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6532 current->GetEnumElementKeys(*element_keys); 6648 current->GetEnumElementKeys(*element_keys);
6533 ASSIGN_RETURN_ON_EXCEPTION( 6649 accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS);
6534 isolate, content, 6650 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6535 FixedArray::UnionOfKeys(content, element_keys),
6536 FixedArray);
6537 DCHECK(ContainsOnlyValidKeys(content));
6538 6651
6539 // Add the element keys from the interceptor. 6652 // Add the element keys from the interceptor.
6540 if (current->HasIndexedInterceptor()) { 6653 if (current->HasIndexedInterceptor()) {
6541 Handle<JSObject> result; 6654 Handle<JSObject> result;
6542 if (JSObject::GetKeysForIndexedInterceptor( 6655 if (JSObject::GetKeysForIndexedInterceptor(
6543 current, object).ToHandle(&result)) { 6656 current, object).ToHandle(&result)) {
6544 ASSIGN_RETURN_ON_EXCEPTION( 6657 accumulator.AddKeys(result, FixedArray::ALL_KEYS);
6545 isolate, content,
6546 FixedArray::AddKeysFromArrayLike(content, result),
6547 FixedArray);
6548 } 6658 }
6549 DCHECK(ContainsOnlyValidKeys(content)); 6659 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6550 } 6660 }
6551 6661
6552 // We can cache the computed property keys if access checks are 6662 // We can cache the computed property keys if access checks are
6553 // not needed and no interceptors are involved. 6663 // not needed and no interceptors are involved.
6554 // 6664 //
6555 // We do not use the cache if the object has elements and 6665 // We do not use the cache if the object has elements and
6556 // therefore it does not make sense to cache the property names 6666 // therefore it does not make sense to cache the property names
6557 // for arguments objects. Arguments objects will always have 6667 // for arguments objects. Arguments objects will always have
6558 // elements. 6668 // elements.
6559 // Wrapped strings have elements, but don't have an elements 6669 // Wrapped strings have elements, but don't have an elements
6560 // array or dictionary. So the fast inline test for whether to 6670 // array or dictionary. So the fast inline test for whether to
6561 // use the cache says yes, so we should not create a cache. 6671 // use the cache says yes, so we should not create a cache.
6562 bool cache_enum_keys = 6672 bool cache_enum_keys =
6563 ((current->map()->GetConstructor() != *arguments_function) && 6673 ((current->map()->GetConstructor() != *arguments_function) &&
6564 !current->IsJSValue() && !current->IsAccessCheckNeeded() && 6674 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6565 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); 6675 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6566 // Compute the property keys and cache them if possible. 6676 // Compute the property keys and cache them if possible.
6567 ASSIGN_RETURN_ON_EXCEPTION( 6677
6568 isolate, content, 6678 Handle<FixedArray> enum_keys =
6569 FixedArray::UnionOfKeys( 6679 JSObject::GetEnumPropertyKeys(current, cache_enum_keys);
6570 content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)), 6680 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS);
6571 FixedArray); 6681 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6572 DCHECK(ContainsOnlyValidKeys(content));
6573 6682
6574 // Add the non-symbol property keys from the interceptor. 6683 // Add the non-symbol property keys from the interceptor.
6575 if (current->HasNamedInterceptor()) { 6684 if (current->HasNamedInterceptor()) {
6576 Handle<JSObject> result; 6685 Handle<JSObject> result;
6577 if (JSObject::GetKeysForNamedInterceptor( 6686 if (JSObject::GetKeysForNamedInterceptor(
6578 current, object).ToHandle(&result)) { 6687 current, object).ToHandle(&result)) {
6579 ASSIGN_RETURN_ON_EXCEPTION( 6688 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS);
6580 isolate, content, FixedArray::AddKeysFromArrayLike(
6581 content, result, FixedArray::NON_SYMBOL_KEYS),
6582 FixedArray);
6583 } 6689 }
6584 DCHECK(ContainsOnlyValidKeys(content)); 6690 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6585 } 6691 }
6586 } 6692 }
6587 return content; 6693
6694 Handle<FixedArray> keys = accumulator.GetKeys();
6695 DCHECK(ContainsOnlyValidKeys(keys));
6696 return keys;
6588 } 6697 }
6589 6698
6590 6699
6591 bool Map::DictionaryElementsInPrototypeChainOnly() { 6700 bool Map::DictionaryElementsInPrototypeChainOnly() {
6592 if (IsDictionaryElementsKind(elements_kind())) { 6701 if (IsDictionaryElementsKind(elements_kind())) {
6593 return false; 6702 return false;
6594 } 6703 }
6595 6704
6596 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { 6705 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6597 // Be conservative, don't walk into proxies. 6706 // Be conservative, don't walk into proxies.
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after
8078 8187
8079 void FixedArray::Shrink(int new_length) { 8188 void FixedArray::Shrink(int new_length) {
8080 DCHECK(0 <= new_length && new_length <= length()); 8189 DCHECK(0 <= new_length && new_length <= length());
8081 if (new_length < length()) { 8190 if (new_length < length()) {
8082 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( 8191 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
8083 this, length() - new_length); 8192 this, length() - new_length);
8084 } 8193 }
8085 } 8194 }
8086 8195
8087 8196
8088 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8089 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
8090 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
8091 ElementsAccessor* accessor = array->GetElementsAccessor();
8092 Handle<FixedArray> result =
8093 accessor->AddElementsToFixedArray(array, content, filter);
8094
8095 #ifdef ENABLE_SLOW_DCHECKS
8096 if (FLAG_enable_slow_asserts) {
8097 DisallowHeapAllocation no_allocation;
8098 for (int i = 0; i < result->length(); i++) {
8099 Object* current = result->get(i);
8100 DCHECK(current->IsNumber() || current->IsName());
8101 }
8102 }
8103 #endif
8104 return result;
8105 }
8106
8107
8108 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8109 Handle<FixedArray> second) {
8110 if (second->length() == 0) return first;
8111 if (first->length() == 0) return second;
8112 Isolate* isolate = first->GetIsolate();
8113 Handle<FixedArray> result =
8114 isolate->factory()->NewFixedArray(first->length() + second->length());
8115 for (int i = 0; i < first->length(); i++) {
8116 result->set(i, first->get(i));
8117 }
8118 int pos = first->length();
8119 for (int j = 0; j < second->length(); j++) {
8120 Object* current = second->get(j);
8121 int i;
8122 for (i = 0; i < first->length(); i++) {
8123 if (current->KeyEquals(first->get(i))) break;
8124 }
8125 if (i == first->length()) {
8126 result->set(pos++, current);
8127 }
8128 }
8129
8130 result->Shrink(pos);
8131 return result;
8132 }
8133
8134
8135 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { 8197 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8136 DisallowHeapAllocation no_gc; 8198 DisallowHeapAllocation no_gc;
8137 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); 8199 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8138 for (int index = 0; index < len; index++) { 8200 for (int index = 0; index < len; index++) {
8139 dest->set(dest_pos+index, get(pos+index), mode); 8201 dest->set(dest_pos+index, get(pos+index), mode);
8140 } 8202 }
8141 } 8203 }
8142 8204
8143 8205
8144 #ifdef DEBUG 8206 #ifdef DEBUG
(...skipping 7109 matching lines...) Expand 10 before | Expand all | Expand 10 after
15254 15316
15255 15317
15256 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { 15318 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
15257 return Lookup(GetIsolate(), key, hash); 15319 return Lookup(GetIsolate(), key, hash);
15258 } 15320 }
15259 15321
15260 15322
15261 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, 15323 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15262 Handle<Object> key, 15324 Handle<Object> key,
15263 Handle<Object> value) { 15325 Handle<Object> value) {
15326 Isolate* isolate = table->GetIsolate();
15264 DCHECK(table->IsKey(*key)); 15327 DCHECK(table->IsKey(*key));
15265 DCHECK(!value->IsTheHole()); 15328 DCHECK(!value->IsTheHole());
15266 15329
15267 Isolate* isolate = table->GetIsolate();
15268 // Make sure the key object has an identity hash code. 15330 // Make sure the key object has an identity hash code.
15269 int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); 15331 int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
15270 15332
15271 return Put(table, key, value, hash); 15333 return Put(table, key, value, hash);
15272 } 15334 }
15273 15335
15274 15336
15275 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, 15337 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15276 Handle<Object> key, 15338 Handle<Object> key,
15277 Handle<Object> value, 15339 Handle<Object> value,
15278 int32_t hash) { 15340 int32_t hash) {
15341 Isolate* isolate = table->GetIsolate();
15279 DCHECK(table->IsKey(*key)); 15342 DCHECK(table->IsKey(*key));
15280 DCHECK(!value->IsTheHole()); 15343 DCHECK(!value->IsTheHole());
15281 15344
15282 Isolate* isolate = table->GetIsolate();
15283
15284 int entry = table->FindEntry(isolate, key, hash); 15345 int entry = table->FindEntry(isolate, key, hash);
15285 15346
15286 // Key is already in table, just overwrite value. 15347 // Key is already in table, just overwrite value.
15287 if (entry != kNotFound) { 15348 if (entry != kNotFound) {
15288 table->set(EntryToIndex(entry) + 1, *value); 15349 table->set(EntryToIndex(entry) + 1, *value);
15289 return table; 15350 return table;
15290 } 15351 }
15291 15352
15292 // Check whether the hash table should be extended. 15353 // Check whether the hash table should be extended.
15293 table = EnsureCapacity(table, 1, key); 15354 table = EnsureCapacity(table, 1, key);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
15447 Allocate(table->GetIsolate(), 15508 Allocate(table->GetIsolate(),
15448 kMinCapacity, 15509 kMinCapacity,
15449 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); 15510 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15450 15511
15451 table->SetNextTable(*new_table); 15512 table->SetNextTable(*new_table);
15452 table->SetNumberOfDeletedElements(kClearedTableSentinel); 15513 table->SetNumberOfDeletedElements(kClearedTableSentinel);
15453 15514
15454 return new_table; 15515 return new_table;
15455 } 15516 }
15456 15517
15518 template <class Derived, class Iterator, int entrysize>
15519 bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
15520 Handle<Derived> table, Handle<Object> key) {
15521 int entry = table->KeyToFirstEntry(*key);
15522 // Walk the chain in the bucket to find the key.
15523 while (entry != kNotFound) {
15524 Object* candidate_key = table->KeyAt(entry);
15525 if (candidate_key->SameValueZero(*key)) return true;
15526 entry = table->NextChainEntry(entry);
15527 }
15528 return false;
15529 }
15530
15531
15532 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
15533 Handle<Object> key) {
15534 int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
15535 int entry = table->HashToEntry(hash);
15536 // Walk the chain of the bucket and try finding the key.
15537 while (entry != kNotFound) {
15538 Object* candidate_key = table->KeyAt(entry);
15539 // Do not add if we have the key already
15540 if (candidate_key->SameValueZero(*key)) return table;
15541 entry = table->NextChainEntry(entry);
15542 }
15543
15544 table = OrderedHashSet::EnsureGrowable(table);
15545 // Read the enxisting bucket values.
Igor Sheludko 2015/09/17 09:55:11 s/enxisting/existing/
15546 int bucket = table->HashToBucket(hash);
15547 int previous_entry = table->HashToEntry(hash);
15548 int nof = table->NumberOfElements();
15549 // Insert a new entry at the end,
15550 int new_entry = nof + table->NumberOfDeletedElements();
15551 int new_index = table->EntryToIndex(new_entry);
15552 table->set(new_index, *key);
15553 table->set(new_index + 1, Smi::FromInt(previous_entry));
15554 // and point the bucket to the new entry.
15555 table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15556 table->SetNumberOfElements(nof + 1);
15557 return table;
15558 }
15559
15457 15560
15458 template<class Derived, class Iterator, int entrysize> 15561 template<class Derived, class Iterator, int entrysize>
15459 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash( 15562 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15460 Handle<Derived> table, int new_capacity) { 15563 Handle<Derived> table, int new_capacity) {
15461 DCHECK(!table->IsObsolete()); 15564 DCHECK(!table->IsObsolete());
15462 15565
15463 Handle<Derived> new_table = 15566 Handle<Derived> new_table =
15464 Allocate(table->GetIsolate(), 15567 Allocate(table->GetIsolate(),
15465 new_capacity, 15568 new_capacity,
15466 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); 15569 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
15509 Handle<OrderedHashSet> table); 15612 Handle<OrderedHashSet> table);
15510 15613
15511 template Handle<OrderedHashSet> 15614 template Handle<OrderedHashSet>
15512 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink( 15615 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15513 Handle<OrderedHashSet> table); 15616 Handle<OrderedHashSet> table);
15514 15617
15515 template Handle<OrderedHashSet> 15618 template Handle<OrderedHashSet>
15516 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear( 15619 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15517 Handle<OrderedHashSet> table); 15620 Handle<OrderedHashSet> table);
15518 15621
15622 template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
15623 Handle<OrderedHashSet> table, Handle<Object> key);
15624
15519 15625
15520 template Handle<OrderedHashMap> 15626 template Handle<OrderedHashMap>
15521 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate( 15627 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15522 Isolate* isolate, int capacity, PretenureFlag pretenure); 15628 Isolate* isolate, int capacity, PretenureFlag pretenure);
15523 15629
15524 template Handle<OrderedHashMap> 15630 template Handle<OrderedHashMap>
15525 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable( 15631 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15526 Handle<OrderedHashMap> table); 15632 Handle<OrderedHashMap> table);
15527 15633
15528 template Handle<OrderedHashMap> 15634 template Handle<OrderedHashMap>
15529 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink( 15635 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15530 Handle<OrderedHashMap> table); 15636 Handle<OrderedHashMap> table);
15531 15637
15532 template Handle<OrderedHashMap> 15638 template Handle<OrderedHashMap>
15533 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear( 15639 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15534 Handle<OrderedHashMap> table); 15640 Handle<OrderedHashMap> table);
15535 15641
15642 template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
15643 Handle<OrderedHashMap> table, Handle<Object> key);
15644
15536 15645
15537 template<class Derived, class TableType> 15646 template<class Derived, class TableType>
15538 void OrderedHashTableIterator<Derived, TableType>::Transition() { 15647 void OrderedHashTableIterator<Derived, TableType>::Transition() {
15539 DisallowHeapAllocation no_allocation; 15648 DisallowHeapAllocation no_allocation;
15540 TableType* table = TableType::cast(this->table()); 15649 TableType* table = TableType::cast(this->table());
15541 if (!table->IsObsolete()) return; 15650 if (!table->IsObsolete()) return;
15542 15651
15543 int index = Smi::cast(this->index())->value(); 15652 int index = Smi::cast(this->index())->value();
15544 while (table->IsObsolete()) { 15653 while (table->IsObsolete()) {
15545 TableType* next_table = table->NextTable(); 15654 TableType* next_table = table->NextTable();
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
16352 if (cell->value() != *new_value) { 16461 if (cell->value() != *new_value) {
16353 cell->set_value(*new_value); 16462 cell->set_value(*new_value);
16354 Isolate* isolate = cell->GetIsolate(); 16463 Isolate* isolate = cell->GetIsolate();
16355 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16464 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16356 isolate, DependentCode::kPropertyCellChangedGroup); 16465 isolate, DependentCode::kPropertyCellChangedGroup);
16357 } 16466 }
16358 } 16467 }
16359 16468
16360 } // namespace internal 16469 } // namespace internal
16361 } // namespace v8 16470 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698