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 <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 7484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7495 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 7495 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
7496 } | 7496 } |
7497 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 7497 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
7498 dictionary->CopyEnumKeysTo(*storage); | 7498 dictionary->CopyEnumKeysTo(*storage); |
7499 return storage; | 7499 return storage; |
7500 } | 7500 } |
7501 } | 7501 } |
7502 | 7502 |
7503 | 7503 |
7504 KeyAccumulator::~KeyAccumulator() { | 7504 KeyAccumulator::~KeyAccumulator() { |
7505 for (int i = 0; i < elements_.length(); i++) { | 7505 for (uint32_t i = 0; i < elements_.size(); i++) { |
Igor Sheludko
2015/10/22 21:42:57
I guess it should be size_t or you will have compi
Camillo Bruni
2015/10/23 08:56:35
right
| |
7506 delete elements_[i]; | 7506 delete elements_[i]; |
7507 } | 7507 } |
7508 } | 7508 } |
7509 | 7509 |
7510 | 7510 |
7511 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | 7511 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
7512 if (length_ == 0) { | 7512 if (length_ == 0) { |
7513 return isolate_->factory()->empty_fixed_array(); | 7513 return isolate_->factory()->empty_fixed_array(); |
7514 } | 7514 } |
7515 // Make sure we have all the lengths collected. | 7515 // Make sure we have all the lengths collected. |
7516 NextPrototype(); | 7516 NextPrototype(); |
7517 | 7517 |
7518 // Assemble the result array by first adding the element keys and then | 7518 // Assemble the result array by first adding the element keys and then |
7519 // the property keys. We use the total number of keys per level in | 7519 // the property keys. We use the total number of keys per level in |
7520 // |protoLengths_| and the available element keys in the corresponding bucket | 7520 // |protoLengths_| and the available element keys in the corresponding bucket |
7521 // in |elements_| to deduce the number of keys to take from the |properties_| | 7521 // in |elements_| to deduce the number of keys to take from the |properties_| |
7522 // set. | 7522 // set. |
7523 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); | 7523 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); |
7524 int index = 0; | 7524 int index = 0; |
7525 int properties_index = 0; | 7525 int properties_index = 0; |
7526 for (int level = 0; level < levelLengths_.length(); level++) { | 7526 for (uint32_t level = 0; level < levelLengths_.size(); level++) { |
Igor Sheludko
2015/10/22 21:42:57
Ditto.
| |
7527 int num_total = levelLengths_[level]; | 7527 int num_total = levelLengths_[level]; |
7528 int num_elements = 0; | 7528 int num_elements = 0; |
7529 if (num_total < 0) { | 7529 if (num_total < 0) { |
7530 // If the total is negative, the current level contains properties from a | 7530 // If the total is negative, the current level contains properties from a |
7531 // proxy, hence we skip the integer keys in |elements_| since proxies | 7531 // proxy, hence we skip the integer keys in |elements_| since proxies |
7532 // define the complete ordering. | 7532 // define the complete ordering. |
7533 num_total = -num_total; | 7533 num_total = -num_total; |
7534 } else if (level < elements_.length()) { | 7534 } else if (level < elements_.size()) { |
7535 List<uint32_t>* elements = elements_[level]; | 7535 std::vector<uint32_t>* elements = elements_[level]; |
7536 num_elements = elements->length(); | 7536 num_elements = static_cast<int>(elements->size()); |
7537 for (int i = 0; i < num_elements; i++) { | 7537 for (int i = 0; i < num_elements; i++) { |
7538 Handle<Object> key; | 7538 Handle<Object> key; |
7539 if (convert == KEEP_NUMBERS) { | 7539 if (convert == KEEP_NUMBERS) { |
7540 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); | 7540 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); |
7541 } else { | 7541 } else { |
7542 key = isolate_->factory()->Uint32ToString(elements->at(i)); | 7542 key = isolate_->factory()->Uint32ToString(elements->at(i)); |
7543 } | 7543 } |
7544 result->set(index, *key); | 7544 result->set(index, *key); |
7545 index++; | 7545 index++; |
7546 } | 7546 } |
7547 } | 7547 } |
7548 // Add the property keys for this prototype level. | 7548 // Add the property keys for this prototype level. |
7549 int num_properties = num_total - num_elements; | 7549 int num_properties = num_total - num_elements; |
7550 for (int i = 0; i < num_properties; i++) { | 7550 for (int i = 0; i < num_properties; i++) { |
7551 Object* key = properties_->KeyAt(properties_index); | 7551 Object* key = properties_->KeyAt(properties_index); |
7552 result->set(index, key); | 7552 result->set(index, key); |
7553 index++; | 7553 index++; |
7554 properties_index++; | 7554 properties_index++; |
7555 } | 7555 } |
7556 } | 7556 } |
7557 DCHECK_EQ(index, length_); | 7557 DCHECK_EQ(index, length_); |
7558 return result; | 7558 return result; |
7559 } | 7559 } |
7560 | 7560 |
7561 | 7561 |
7562 namespace { | 7562 namespace { |
7563 | 7563 |
7564 class FindKey { | 7564 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { |
7565 public: | 7565 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); |
7566 explicit FindKey(uint32_t key) : key_(key) {} | |
7567 int operator()(uint32_t* entry) { | |
7568 if (*entry == key_) return 0; | |
7569 return *entry < key_ ? -1 : 1; | |
7570 } | |
7571 | |
7572 private: | |
7573 uint32_t key_; | |
7574 }; | |
7575 | |
7576 | |
7577 bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) { | |
7578 int index = SortedListBSearch(*sub_elements, FindKey(key)); | |
7579 return index != -1; | |
7580 } | 7566 } |
7581 | 7567 |
7582 } // namespace | 7568 } // namespace |
7583 | 7569 |
7584 | 7570 |
7585 bool KeyAccumulator::AddKey(uint32_t key) { | 7571 bool KeyAccumulator::AddKey(uint32_t key) { |
7586 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | 7572 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). |
7573 // We mark proxy-levels with a negative length | |
7587 DCHECK_LE(0, levelLength_); | 7574 DCHECK_LE(0, levelLength_); |
7588 int lookup_limit = elements_.length(); | 7575 // Binary search over all but the last level. The last one might not be |
7589 for (int i = 0; i < lookup_limit; i++) { | 7576 // sorted yet. |
7590 if (AccumulatorHasKey(elements_[i], key)) return false; | 7577 for (uint32_t i = 1; i < elements_.size(); i++) { |
Igor Sheludko
2015/10/22 21:42:57
Ditto.
| |
7578 if (AccumulatorHasKey(elements_[i - 1], key)) return false; | |
7591 } | 7579 } |
7592 elements_[lookup_limit - 1]->Add(key); | 7580 if (elementKeysAddCheckLimit_ == INCLUDE_CURRENT_LEVEL) { |
7581 // the last level may have not been sorted yet, hence we have to do | |
7582 // a linear search here if required. | |
7583 auto last_level = elements_.back(); | |
7584 if (std::find(last_level->begin(), last_level->end(), key) != | |
7585 last_level->end()) { | |
7586 return false; | |
7587 } | |
7588 } | |
7589 elements_.back()->push_back(key); | |
7593 length_++; | 7590 length_++; |
7594 levelLength_++; | 7591 levelLength_++; |
7595 return true; | 7592 return true; |
7596 } | 7593 } |
7597 | 7594 |
7598 | 7595 |
7599 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { | 7596 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { |
7600 return AddKey(handle(key, isolate_), convert); | 7597 return AddKey(handle(key, isolate_), convert); |
7601 } | 7598 } |
7602 | 7599 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7676 // elements and properties, which breaks the normal assumption for the | 7673 // elements and properties, which breaks the normal assumption for the |
7677 // KeyAccumulator. | 7674 // KeyAccumulator. |
7678 AddKeys(array_like, PROXY_MAGIC); | 7675 AddKeys(array_like, PROXY_MAGIC); |
7679 // Invert the current length to indicate a present proxy, so we can ignore | 7676 // Invert the current length to indicate a present proxy, so we can ignore |
7680 // element keys for this level. Otherwise we would not fully respect the order | 7677 // element keys for this level. Otherwise we would not fully respect the order |
7681 // given by the proxy. | 7678 // given by the proxy. |
7682 levelLength_ = -levelLength_; | 7679 levelLength_ = -levelLength_; |
7683 } | 7680 } |
7684 | 7681 |
7685 | 7682 |
7686 namespace { | 7683 void KeyAccumulator::AddKeysFromInterceptor(Handle<JSObject> array_like) { |
7687 | 7684 // The accumulator might introduce duplicates for the current level, |
7688 // Used for sorting indices in a List<uint32_t>. | 7685 // hence we set INCLUDE_CURRENT_LEVEL |
Igor Sheludko
2015/10/22 21:42:57
DCHECK_EQ(EXCLUDE_CURRENT_LEVEL, elementKeysAddChe
| |
7689 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { | 7686 elementKeysAddCheckLimit_ = INCLUDE_CURRENT_LEVEL; |
Igor Sheludko
2015/10/22 21:42:57
WDYT about adding all the elements without checkin
Camillo Bruni
2015/10/26 09:53:48
ah right, makes sense :)
| |
7690 uint32_t a = *ap; | 7687 AddKeys(array_like, CONVERT_TO_ARRAY_INDEX); |
7691 uint32_t b = *bp; | 7688 elementKeysAddCheckLimit_ = EXCLUDE_CURRENT_LEVEL; |
7692 return (a == b) ? 0 : (a < b) ? -1 : 1; | |
7693 } | 7689 } |
7694 | 7690 |
7695 | 7691 |
7696 } // namespace | |
7697 | |
7698 | |
7699 void KeyAccumulator::SortCurrentElementsList() { | 7692 void KeyAccumulator::SortCurrentElementsList() { |
7700 if (elements_.length() == 0) return; | 7693 if (elements_.empty()) return; |
7701 List<uint32_t>* element_keys = elements_[elements_.length() - 1]; | 7694 std::vector<uint32_t>* element_keys = elements_.back(); |
7702 element_keys->Sort(&compareUInt32); | 7695 std::sort(element_keys->begin(), element_keys->end()); |
7703 } | 7696 } |
7704 | 7697 |
7705 | 7698 |
7706 void KeyAccumulator::NextPrototype() { | 7699 void KeyAccumulator::NextPrototype() { |
7707 // Store the protoLength on the first call of this method. | 7700 // Store the protoLength on the first call of this method. |
7708 if (!elements_.is_empty()) { | 7701 if (!elements_.empty()) { |
7709 levelLengths_.Add(levelLength_); | 7702 levelLengths_.push_back(levelLength_); |
7710 } | 7703 } |
7711 elements_.Add(new List<uint32_t>()); | 7704 elements_.push_back(new std::vector<uint32_t>()); |
7712 levelLength_ = 0; | 7705 levelLength_ = 0; |
7713 } | 7706 } |
7714 | 7707 |
7715 | 7708 |
7716 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 7709 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
7717 KeyCollectionType type, | 7710 KeyCollectionType type, |
7718 KeyFilter filter, | 7711 KeyFilter filter, |
7719 GetKeysConversion getConversion) { | 7712 GetKeysConversion getConversion) { |
7720 USE(ContainsOnlyValidKeys); | 7713 USE(ContainsOnlyValidKeys); |
7721 Isolate* isolate = object->GetIsolate(); | 7714 Isolate* isolate = object->GetIsolate(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7760 } | 7753 } |
7761 | 7754 |
7762 JSObject::CollectOwnElementKeys(current, &accumulator, | 7755 JSObject::CollectOwnElementKeys(current, &accumulator, |
7763 static_cast<PropertyAttributes>(DONT_ENUM)); | 7756 static_cast<PropertyAttributes>(DONT_ENUM)); |
7764 | 7757 |
7765 // Add the element keys from the interceptor. | 7758 // Add the element keys from the interceptor. |
7766 if (current->HasIndexedInterceptor()) { | 7759 if (current->HasIndexedInterceptor()) { |
7767 Handle<JSObject> result; | 7760 Handle<JSObject> result; |
7768 if (JSObject::GetKeysForIndexedInterceptor(current, object) | 7761 if (JSObject::GetKeysForIndexedInterceptor(current, object) |
7769 .ToHandle(&result)) { | 7762 .ToHandle(&result)) { |
7770 accumulator.AddKeys(result, CONVERT_TO_ARRAY_INDEX); | 7763 accumulator.AddKeysFromInterceptor(result); |
7771 } | 7764 } |
7772 } | 7765 } |
7773 | 7766 |
7774 if (filter == SKIP_SYMBOLS) { | 7767 if (filter == SKIP_SYMBOLS) { |
7775 // We can cache the computed property keys if access checks are | 7768 // We can cache the computed property keys if access checks are |
7776 // not needed and no interceptors are involved. | 7769 // not needed and no interceptors are involved. |
7777 // | 7770 // |
7778 // We do not use the cache if the object has elements and | 7771 // We do not use the cache if the object has elements and |
7779 // therefore it does not make sense to cache the property names | 7772 // therefore it does not make sense to cache the property names |
7780 // for arguments objects. Arguments objects will always have | 7773 // for arguments objects. Arguments objects will always have |
(...skipping 10031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17812 if (cell->value() != *new_value) { | 17805 if (cell->value() != *new_value) { |
17813 cell->set_value(*new_value); | 17806 cell->set_value(*new_value); |
17814 Isolate* isolate = cell->GetIsolate(); | 17807 Isolate* isolate = cell->GetIsolate(); |
17815 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17808 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17816 isolate, DependentCode::kPropertyCellChangedGroup); | 17809 isolate, DependentCode::kPropertyCellChangedGroup); |
17817 } | 17810 } |
17818 } | 17811 } |
17819 | 17812 |
17820 } // namespace internal | 17813 } // namespace internal |
17821 } // namespace v8 | 17814 } // namespace v8 |
OLD | NEW |