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 6462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |