OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |