Chromium Code Reviews| 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 |