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 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 |