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 <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 7544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7555 | 7555 |
| 7556 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | 7556 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
| 7557 if (length_ == 0) { | 7557 if (length_ == 0) { |
| 7558 return isolate_->factory()->empty_fixed_array(); | 7558 return isolate_->factory()->empty_fixed_array(); |
| 7559 } | 7559 } |
| 7560 // Make sure we have all the lengths collected. | 7560 // Make sure we have all the lengths collected. |
| 7561 NextPrototype(); | 7561 NextPrototype(); |
| 7562 | 7562 |
| 7563 // Assemble the result array by first adding the element keys and then | 7563 // Assemble the result array by first adding the element keys and then |
| 7564 // the property keys. We use the total number of keys per level in | 7564 // the property keys. We use the total number of keys per level in |
| 7565 // |protoLengths_| and the available element keys in the corresponding bucket | 7565 // |protoLengths_| and the available element keys in the corresponding bucket |
|
Jakob Kummerow
2015/11/03 15:33:37
nit: outdated comment
| |
| 7566 // in |elements_| to deduce the number of keys to take from the |properties_| | 7566 // in |elements_| to deduce the number of keys to take from the |properties_| |
| 7567 // set. | 7567 // set. |
| 7568 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); | 7568 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); |
| 7569 int index = 0; | 7569 int insertion_index = 0; |
| 7570 int properties_index = 0; | 7570 int string_properties_index = 0; |
| 7571 for (size_t level = 0; level < levelLengths_.size(); level++) { | 7571 int symbol_properties_index = 0; |
| 7572 int num_total = levelLengths_[level]; | 7572 // String and Symbol lengths always come in pairs: |
| 7573 int num_elements = 0; | 7573 size_t max_level = level_lengths_.size() / 2; |
| 7574 if (num_total < 0) { | 7574 for (size_t level = 0; level < max_level; level++) { |
| 7575 // If the total is negative, the current level contains properties from a | 7575 int num_string_properties = level_lengths_[level * 2]; |
| 7576 // proxy, hence we skip the integer keys in |elements_| since proxies | 7576 int num_symbol_properties = level_lengths_[level * 2 + 1]; |
| 7577 // define the complete ordering. | 7577 if (num_string_properties < 0) { |
| 7578 num_total = -num_total; | 7578 // If the num_string_properties is negative, the current level contains |
| 7579 // properties from a proxy, hence we skip the integer keys in |elements_| | |
| 7580 // since proxies define the complete ordering. | |
| 7581 num_string_properties = -num_string_properties; | |
| 7579 } else if (level < elements_.size()) { | 7582 } else if (level < elements_.size()) { |
| 7583 // Add the element indices for this prototype level. | |
| 7580 std::vector<uint32_t>* elements = elements_[level]; | 7584 std::vector<uint32_t>* elements = elements_[level]; |
| 7581 num_elements = static_cast<int>(elements->size()); | 7585 int num_elements = static_cast<int>(elements->size()); |
| 7582 for (int i = 0; i < num_elements; i++) { | 7586 for (int i = 0; i < num_elements; i++) { |
| 7583 Handle<Object> key; | 7587 Handle<Object> key; |
| 7584 if (convert == KEEP_NUMBERS) { | 7588 if (convert == KEEP_NUMBERS) { |
| 7585 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); | 7589 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); |
| 7586 } else { | 7590 } else { |
| 7587 key = isolate_->factory()->Uint32ToString(elements->at(i)); | 7591 key = isolate_->factory()->Uint32ToString(elements->at(i)); |
| 7588 } | 7592 } |
| 7589 result->set(index, *key); | 7593 result->set(insertion_index, *key); |
| 7590 index++; | 7594 insertion_index++; |
| 7591 } | 7595 } |
| 7592 } | 7596 } |
| 7593 // Add the property keys for this prototype level. | 7597 // Add the string property keys for this prototype level. |
| 7594 int num_properties = num_total - num_elements; | 7598 for (int i = 0; i < num_string_properties; i++) { |
| 7595 for (int i = 0; i < num_properties; i++) { | 7599 Object* key = string_properties_->KeyAt(string_properties_index); |
| 7596 Object* key = properties_->KeyAt(properties_index); | 7600 result->set(insertion_index, key); |
| 7597 result->set(index, key); | 7601 insertion_index++; |
| 7598 index++; | 7602 string_properties_index++; |
| 7599 properties_index++; | 7603 } |
| 7604 // Add the symbol property keys for this prototype level. | |
| 7605 for (int i = 0; i < num_symbol_properties; i++) { | |
| 7606 Object* key = symbol_properties_->KeyAt(symbol_properties_index); | |
| 7607 result->set(insertion_index, key); | |
| 7608 insertion_index++; | |
| 7609 symbol_properties_index++; | |
| 7600 } | 7610 } |
| 7601 } | 7611 } |
| 7602 | 7612 |
| 7603 DCHECK_EQ(index, length_); | 7613 DCHECK_EQ(insertion_index, length_); |
| 7604 return result; | 7614 return result; |
| 7605 } | 7615 } |
| 7606 | 7616 |
| 7607 | 7617 |
| 7618 int KeyAccumulator::GetLength() { return length_; } | |
|
Jakob Kummerow
2015/11/03 15:33:37
nit: a simple getter like this should be called ju
| |
| 7619 | |
| 7620 | |
| 7608 namespace { | 7621 namespace { |
| 7609 | 7622 |
| 7610 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { | 7623 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { |
| 7611 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); | 7624 return std::binary_search(sub_elements->begin(), sub_elements->end(), key); |
| 7612 } | 7625 } |
| 7613 | 7626 |
| 7614 } // namespace | 7627 } // namespace |
| 7615 | 7628 |
| 7616 | 7629 |
| 7617 bool KeyAccumulator::AddKey(uint32_t key) { | 7630 bool KeyAccumulator::AddKey(uint32_t key) { |
| 7618 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | 7631 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). |
| 7619 // We mark proxy-levels with a negative length | 7632 // We mark proxy-levels with a negative length |
| 7620 DCHECK_LE(0, levelLength_); | 7633 DCHECK_LE(0, level_string_length_); |
| 7621 // Binary search over all but the last level. The last one might not be | 7634 // Binary search over all but the last level. The last one might not be |
| 7622 // sorted yet. | 7635 // sorted yet. |
| 7623 for (size_t i = 1; i < elements_.size(); i++) { | 7636 for (size_t i = 1; i < elements_.size(); i++) { |
| 7624 if (AccumulatorHasKey(elements_[i - 1], key)) return false; | 7637 if (AccumulatorHasKey(elements_[i - 1], key)) return false; |
| 7625 } | 7638 } |
| 7626 elements_.back()->push_back(key); | 7639 elements_.back()->push_back(key); |
| 7627 length_++; | 7640 length_++; |
| 7628 levelLength_++; | |
| 7629 return true; | 7641 return true; |
| 7630 } | 7642 } |
| 7631 | 7643 |
| 7632 | 7644 |
| 7633 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { | 7645 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { |
| 7634 return AddKey(handle(key, isolate_), convert); | 7646 return AddKey(handle(key, isolate_), convert); |
| 7635 } | 7647 } |
| 7636 | 7648 |
| 7637 | 7649 |
| 7638 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { | 7650 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { |
| 7639 if (filter_ == SKIP_SYMBOLS && key->IsSymbol()) { | 7651 if (key->IsSymbol()) { |
| 7640 return false; | 7652 if (filter_ == SKIP_SYMBOLS) return false; |
| 7653 return AddSymbolKey(key); | |
| 7641 } | 7654 } |
| 7642 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | 7655 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). |
| 7643 DCHECK_LE(0, levelLength_); | 7656 DCHECK_LE(0, level_string_length_); |
| 7644 // In some cases (e.g. proxies) we might get in String-converted ints which | 7657 // In some cases (e.g. proxies) we might get in String-converted ints which |
| 7645 // should be added to the elements list instead of the properties. For | 7658 // should be added to the elements list instead of the properties. For |
| 7646 // proxies we have to convert as well but also respect the original order. | 7659 // proxies we have to convert as well but also respect the original order. |
| 7647 // Therefore we add a converted key to both sides | 7660 // Therefore we add a converted key to both sides |
| 7648 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) { | 7661 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) { |
| 7649 uint32_t index = 0; | 7662 uint32_t index = 0; |
| 7650 int prev_length = length_; | 7663 int prev_length = length_; |
| 7651 int prev_proto = levelLength_; | 7664 int prev_proto = level_string_length_; |
| 7652 bool was_array_index = false; | 7665 bool was_array_index = false; |
| 7653 bool key_was_added = false; | 7666 bool key_was_added = false; |
| 7654 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) || | 7667 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) || |
| 7655 key->ToArrayIndex(&index)) { | 7668 key->ToArrayIndex(&index)) { |
| 7656 key_was_added = AddKey(index); | 7669 key_was_added = AddKey(index); |
| 7657 was_array_index = true; | 7670 was_array_index = true; |
| 7658 if (convert == CONVERT_TO_ARRAY_INDEX) return key_was_added; | 7671 if (convert == CONVERT_TO_ARRAY_INDEX) return key_was_added; |
| 7659 } | 7672 } |
| 7660 if (was_array_index && convert == PROXY_MAGIC) { | 7673 if (was_array_index && convert == PROXY_MAGIC) { |
| 7661 // If we had an array index (number) and it wasn't added, the key | 7674 // If we had an array index (number) and it wasn't added, the key |
| 7662 // already existed before, hence we cannot add it to the properties | 7675 // already existed before, hence we cannot add it to the properties |
| 7663 // keys as it would lead to duplicate entries. | 7676 // keys as it would lead to duplicate entries. |
| 7664 if (!key_was_added) { | 7677 if (!key_was_added) { |
| 7665 return false; | 7678 return false; |
| 7666 } | 7679 } |
| 7667 length_ = prev_length; | 7680 length_ = prev_length; |
| 7668 levelLength_ = prev_proto; | 7681 level_string_length_ = prev_proto; |
| 7669 } | 7682 } |
| 7670 } | 7683 } |
| 7671 if (properties_.is_null()) { | 7684 return AddStringKey(key, convert); |
| 7672 properties_ = OrderedHashSet::Allocate(isolate_, 16); | 7685 } |
| 7686 | |
| 7687 | |
| 7688 bool KeyAccumulator::AddStringKey(Handle<Object> key, | |
| 7689 AddKeyConversion convert) { | |
| 7690 if (string_properties_.is_null()) { | |
| 7691 string_properties_ = OrderedHashSet::Allocate(isolate_, 16); | |
| 7673 } | 7692 } |
| 7674 // TODO(cbruni): remove this conversion once we throw the correct TypeError | 7693 // TODO(cbruni): remove this conversion once we throw the correct TypeError |
| 7675 // for non-string/symbol elements returned by proxies | 7694 // for non-string/symbol elements returned by proxies |
| 7676 if (convert == PROXY_MAGIC && key->IsNumber()) { | 7695 if (convert == PROXY_MAGIC && key->IsNumber()) { |
| 7677 key = isolate_->factory()->NumberToString(key); | 7696 key = isolate_->factory()->NumberToString(key); |
| 7678 } | 7697 } |
| 7679 int prev_size = properties_->NumberOfElements(); | 7698 int prev_size = string_properties_->NumberOfElements(); |
| 7680 properties_ = OrderedHashSet::Add(properties_, key); | 7699 string_properties_ = OrderedHashSet::Add(string_properties_, key); |
| 7681 if (prev_size < properties_->NumberOfElements()) { | 7700 if (prev_size < string_properties_->NumberOfElements()) { |
| 7682 length_++; | 7701 length_++; |
| 7683 levelLength_++; | 7702 level_string_length_++; |
| 7703 return true; | |
| 7704 } else { | |
| 7705 return false; | |
| 7684 } | 7706 } |
| 7685 return true; | |
| 7686 } | 7707 } |
| 7687 | 7708 |
| 7688 | 7709 |
| 7710 bool KeyAccumulator::AddSymbolKey(Handle<Object> key) { | |
| 7711 if (symbol_properties_.is_null()) { | |
| 7712 symbol_properties_ = OrderedHashSet::Allocate(isolate_, 16); | |
| 7713 } | |
| 7714 int prev_size = symbol_properties_->NumberOfElements(); | |
| 7715 symbol_properties_ = OrderedHashSet::Add(symbol_properties_, key); | |
| 7716 if (prev_size < symbol_properties_->NumberOfElements()) { | |
| 7717 length_++; | |
| 7718 level_symbol_length_++; | |
| 7719 return true; | |
| 7720 } else { | |
| 7721 return false; | |
| 7722 } | |
| 7723 } | |
| 7724 | |
| 7725 | |
| 7689 void KeyAccumulator::AddKeys(Handle<FixedArray> array, | 7726 void KeyAccumulator::AddKeys(Handle<FixedArray> array, |
| 7690 AddKeyConversion convert) { | 7727 AddKeyConversion convert) { |
| 7691 int add_length = array->length(); | 7728 int add_length = array->length(); |
| 7692 if (add_length == 0) return; | 7729 if (add_length == 0) return; |
| 7693 for (int i = 0; i < add_length; i++) { | 7730 for (int i = 0; i < add_length; i++) { |
| 7694 Handle<Object> current(array->get(i), isolate_); | 7731 Handle<Object> current(array->get(i), isolate_); |
| 7695 AddKey(current); | 7732 AddKey(current, convert); |
| 7696 } | 7733 } |
| 7697 } | 7734 } |
| 7698 | 7735 |
| 7699 | 7736 |
| 7700 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, | 7737 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, |
| 7701 AddKeyConversion convert) { | 7738 AddKeyConversion convert) { |
| 7702 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); | 7739 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); |
| 7703 ElementsAccessor* accessor = array_like->GetElementsAccessor(); | 7740 ElementsAccessor* accessor = array_like->GetElementsAccessor(); |
| 7704 accessor->AddElementsToKeyAccumulator(array_like, this, convert); | 7741 accessor->AddElementsToKeyAccumulator(array_like, this, convert); |
| 7705 } | 7742 } |
| 7706 | 7743 |
| 7707 | 7744 |
| 7708 void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) { | 7745 void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) { |
| 7709 // Proxies define a complete list of keys with no distinction of | 7746 // Proxies define a complete list of keys with no distinction of |
| 7710 // elements and properties, which breaks the normal assumption for the | 7747 // elements and properties, which breaks the normal assumption for the |
| 7711 // KeyAccumulator. | 7748 // KeyAccumulator. |
| 7712 AddKeys(array_like, PROXY_MAGIC); | 7749 AddKeys(array_like, PROXY_MAGIC); |
| 7713 // Invert the current length to indicate a present proxy, so we can ignore | 7750 // Invert the current length to indicate a present proxy, so we can ignore |
| 7714 // element keys for this level. Otherwise we would not fully respect the order | 7751 // element keys for this level. Otherwise we would not fully respect the order |
| 7715 // given by the proxy. | 7752 // given by the proxy. |
| 7716 levelLength_ = -levelLength_; | 7753 level_string_length_ = -level_string_length_; |
| 7717 } | 7754 } |
| 7718 | 7755 |
| 7719 | 7756 |
| 7720 void KeyAccumulator::AddElementKeysFromInterceptor( | 7757 void KeyAccumulator::AddElementKeysFromInterceptor( |
| 7721 Handle<JSObject> array_like) { | 7758 Handle<JSObject> array_like) { |
| 7722 AddKeys(array_like, CONVERT_TO_ARRAY_INDEX); | 7759 AddKeys(array_like, CONVERT_TO_ARRAY_INDEX); |
| 7723 // The interceptor might introduce duplicates for the current level, since | 7760 // The interceptor might introduce duplicates for the current level, since |
| 7724 // these keys get added after the objects's normal element keys. | 7761 // these keys get added after the objects's normal element keys. |
| 7725 SortCurrentElementsListRemoveDuplicates(); | 7762 SortCurrentElementsListRemoveDuplicates(); |
| 7726 } | 7763 } |
| 7727 | 7764 |
| 7728 | 7765 |
| 7729 void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() { | 7766 void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() { |
| 7730 // Sort and remove duplciated from the current elements level and adjust | 7767 // Sort and remove duplicated from the current elements level and adjust. |
|
Jakob Kummerow
2015/11/03 15:33:37
nit: s/.//, also s/duplicated/duplicate entries/?
| |
| 7731 // the lengths accordingly. | 7768 // the lengths accordingly. |
| 7732 auto last_level = elements_.back(); | 7769 auto last_level = elements_.back(); |
| 7733 size_t nof_removed_keys = last_level->size(); | 7770 size_t nof_removed_keys = last_level->size(); |
| 7734 std::sort(last_level->begin(), last_level->end()); | 7771 std::sort(last_level->begin(), last_level->end()); |
| 7735 last_level->erase(std::unique(last_level->begin(), last_level->end()), | 7772 last_level->erase(std::unique(last_level->begin(), last_level->end()), |
| 7736 last_level->end()); | 7773 last_level->end()); |
| 7737 // Adjust total length / level length by the number of removed duplicates | 7774 // Adjust total length by the number of removed duplicates. |
| 7738 nof_removed_keys -= last_level->size(); | 7775 nof_removed_keys -= last_level->size(); |
| 7739 levelLength_ -= static_cast<int>(nof_removed_keys); | |
| 7740 length_ -= static_cast<int>(nof_removed_keys); | 7776 length_ -= static_cast<int>(nof_removed_keys); |
| 7741 } | 7777 } |
| 7742 | 7778 |
| 7743 | 7779 |
| 7744 void KeyAccumulator::SortCurrentElementsList() { | 7780 void KeyAccumulator::SortCurrentElementsList() { |
| 7745 if (elements_.empty()) return; | 7781 if (elements_.empty()) return; |
| 7746 auto element_keys = elements_.back(); | 7782 auto element_keys = elements_.back(); |
| 7747 std::sort(element_keys->begin(), element_keys->end()); | 7783 std::sort(element_keys->begin(), element_keys->end()); |
| 7748 } | 7784 } |
| 7749 | 7785 |
| 7750 | 7786 |
| 7751 void KeyAccumulator::NextPrototype() { | 7787 void KeyAccumulator::NextPrototype() { |
| 7752 // Store the protoLength on the first call of this method. | 7788 // Store the protoLength on the first call of this method. |
| 7753 if (!elements_.empty()) { | 7789 if (!elements_.empty()) { |
| 7754 levelLengths_.push_back(levelLength_); | 7790 level_lengths_.push_back(level_string_length_); |
| 7791 level_lengths_.push_back(level_symbol_length_); | |
| 7755 } | 7792 } |
| 7756 elements_.push_back(new std::vector<uint32_t>()); | 7793 elements_.push_back(new std::vector<uint32_t>()); |
| 7757 levelLength_ = 0; | 7794 level_string_length_ = 0; |
| 7795 level_symbol_length_ = 0; | |
| 7758 } | 7796 } |
| 7759 | 7797 |
| 7760 | 7798 |
| 7761 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 7799 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
| 7762 KeyCollectionType type, | 7800 KeyCollectionType type, |
| 7763 KeyFilter filter, | 7801 KeyFilter filter, |
| 7764 GetKeysConversion getConversion) { | 7802 GetKeysConversion getConversion) { |
| 7765 USE(ContainsOnlyValidKeys); | 7803 USE(ContainsOnlyValidKeys); |
| 7766 Isolate* isolate = object->GetIsolate(); | 7804 Isolate* isolate = object->GetIsolate(); |
| 7767 KeyAccumulator accumulator(isolate, filter); | 7805 KeyAccumulator accumulator(isolate, filter); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7833 !current->HasNamedInterceptor() && | 7871 !current->HasNamedInterceptor() && |
| 7834 !current->HasIndexedInterceptor()); | 7872 !current->HasIndexedInterceptor()); |
| 7835 // Compute the property keys and cache them if possible. | 7873 // Compute the property keys and cache them if possible. |
| 7836 Handle<FixedArray> enum_keys = | 7874 Handle<FixedArray> enum_keys = |
| 7837 JSObject::GetEnumPropertyKeys(current, cache_enum_length); | 7875 JSObject::GetEnumPropertyKeys(current, cache_enum_length); |
| 7838 accumulator.AddKeys(enum_keys); | 7876 accumulator.AddKeys(enum_keys); |
| 7839 } else { | 7877 } else { |
| 7840 DCHECK(filter == INCLUDE_SYMBOLS); | 7878 DCHECK(filter == INCLUDE_SYMBOLS); |
| 7841 PropertyAttributes attr_filter = | 7879 PropertyAttributes attr_filter = |
| 7842 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); | 7880 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); |
| 7843 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( | 7881 current->CollectOwnPropertyNames(&accumulator, attr_filter); |
| 7844 current->NumberOfOwnProperties(attr_filter)); | |
| 7845 current->GetOwnPropertyNames(*property_keys, 0, attr_filter); | |
| 7846 accumulator.AddKeys(property_keys); | |
| 7847 } | 7882 } |
| 7848 | 7883 |
| 7849 // Add the property keys from the interceptor. | 7884 // Add the property keys from the interceptor. |
| 7850 if (current->HasNamedInterceptor()) { | 7885 if (current->HasNamedInterceptor()) { |
| 7851 Handle<JSObject> result; | 7886 Handle<JSObject> result; |
| 7852 if (JSObject::GetKeysForNamedInterceptor(current, object) | 7887 if (JSObject::GetKeysForNamedInterceptor(current, object) |
| 7853 .ToHandle(&result)) { | 7888 .ToHandle(&result)) { |
| 7854 accumulator.AddKeys(result); | 7889 accumulator.AddKeys(result); |
| 7855 } | 7890 } |
| 7856 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | 7891 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
| (...skipping 7156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15013 } else if (IsJSGlobalObject()) { | 15048 } else if (IsJSGlobalObject()) { |
| 15014 return global_dictionary()->CopyKeysTo(storage, index, filter, | 15049 return global_dictionary()->CopyKeysTo(storage, index, filter, |
| 15015 GlobalDictionary::UNSORTED); | 15050 GlobalDictionary::UNSORTED); |
| 15016 } else { | 15051 } else { |
| 15017 return property_dictionary()->CopyKeysTo(storage, index, filter, | 15052 return property_dictionary()->CopyKeysTo(storage, index, filter, |
| 15018 NameDictionary::UNSORTED); | 15053 NameDictionary::UNSORTED); |
| 15019 } | 15054 } |
| 15020 } | 15055 } |
| 15021 | 15056 |
| 15022 | 15057 |
| 15058 int JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | |
| 15059 PropertyAttributes filter) { | |
| 15060 if (HasFastProperties()) { | |
| 15061 int nof_keys = keys->GetLength(); | |
| 15062 int real_size = map()->NumberOfOwnDescriptors(); | |
| 15063 Handle<DescriptorArray> descs(map()->instance_descriptors()); | |
| 15064 for (int i = 0; i < real_size; i++) { | |
| 15065 if ((descs->GetDetails(i).attributes() & filter) != 0) continue; | |
| 15066 Name* key = descs->GetKey(i); | |
| 15067 if (key->FilterKey(filter)) continue; | |
| 15068 keys->AddKey(key); | |
| 15069 } | |
| 15070 return nof_keys - keys->GetLength(); | |
| 15071 } else if (IsJSGlobalObject()) { | |
| 15072 return global_dictionary()->CollectKeysTo(keys, filter); | |
| 15073 } else { | |
| 15074 return property_dictionary()->CollectKeysTo(keys, filter); | |
| 15075 } | |
| 15076 } | |
| 15077 | |
| 15078 | |
| 15023 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { | 15079 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { |
| 15024 // Fast case for objects with no elements. | 15080 // Fast case for objects with no elements. |
| 15025 if (!IsJSValue() && HasFastElements()) { | 15081 if (!IsJSValue() && HasFastElements()) { |
| 15026 uint32_t length = | 15082 uint32_t length = |
| 15027 IsJSArray() | 15083 IsJSArray() |
| 15028 ? static_cast<uint32_t>( | 15084 ? static_cast<uint32_t>( |
| 15029 Smi::cast(JSArray::cast(this)->length())->value()) | 15085 Smi::cast(JSArray::cast(this)->length())->value()) |
| 15030 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 15086 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
| 15031 if (length == 0) return 0; | 15087 if (length == 0) return 0; |
| 15032 } | 15088 } |
| (...skipping 1751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16784 | 16840 |
| 16785 template <typename Derived, typename Shape, typename Key> | 16841 template <typename Derived, typename Shape, typename Key> |
| 16786 int Dictionary<Derived, Shape, Key>::CopyKeysTo( | 16842 int Dictionary<Derived, Shape, Key>::CopyKeysTo( |
| 16787 FixedArray* storage, int index, PropertyAttributes filter, | 16843 FixedArray* storage, int index, PropertyAttributes filter, |
| 16788 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 16844 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
| 16789 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 16845 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 16790 int start_index = index; | 16846 int start_index = index; |
| 16791 int capacity = this->Capacity(); | 16847 int capacity = this->Capacity(); |
| 16792 for (int i = 0; i < capacity; i++) { | 16848 for (int i = 0; i < capacity; i++) { |
| 16793 Object* k = this->KeyAt(i); | 16849 Object* k = this->KeyAt(i); |
| 16794 if (this->IsKey(k) && !k->FilterKey(filter)) { | 16850 if (!this->IsKey(k) || k->FilterKey(filter)) continue; |
| 16795 if (this->IsDeleted(i)) continue; | 16851 if (this->IsDeleted(i)) continue; |
| 16796 PropertyDetails details = this->DetailsAt(i); | 16852 PropertyDetails details = this->DetailsAt(i); |
| 16797 PropertyAttributes attr = details.attributes(); | 16853 PropertyAttributes attr = details.attributes(); |
| 16798 if ((attr & filter) == 0) storage->set(index++, k); | 16854 if ((attr & filter) != 0) continue; |
| 16799 } | 16855 storage->set(index++, k); |
| 16800 } | 16856 } |
| 16801 if (sort_mode == Dictionary::SORTED) { | 16857 if (sort_mode == Dictionary::SORTED) { |
| 16802 storage->SortPairs(storage, index); | 16858 storage->SortPairs(storage, index); |
| 16803 } | 16859 } |
| 16804 DCHECK(storage->length() >= index); | 16860 DCHECK(storage->length() >= index); |
| 16805 return index - start_index; | 16861 return index - start_index; |
| 16806 } | 16862 } |
| 16807 | 16863 |
| 16808 | 16864 |
| 16865 template <typename Derived, typename Shape, typename Key> | |
| 16866 int Dictionary<Derived, Shape, Key>::CollectKeysTo(KeyAccumulator* keys, | |
| 16867 PropertyAttributes filter) { | |
| 16868 int capacity = this->Capacity(); | |
| 16869 int keyLength = keys->GetLength(); | |
| 16870 for (int i = 0; i < capacity; i++) { | |
| 16871 Object* k = this->KeyAt(i); | |
| 16872 if (!this->IsKey(k) || k->FilterKey(filter)) continue; | |
| 16873 if (this->IsDeleted(i)) continue; | |
| 16874 PropertyDetails details = this->DetailsAt(i); | |
| 16875 PropertyAttributes attr = details.attributes(); | |
| 16876 if ((attr & filter) != 0) continue; | |
| 16877 keys->AddKey(k); | |
| 16878 } | |
| 16879 return keyLength - keys->GetLength(); | |
| 16880 } | |
| 16881 | |
| 16882 | |
| 16809 // Backwards lookup (slow). | 16883 // Backwards lookup (slow). |
| 16810 template<typename Derived, typename Shape, typename Key> | 16884 template<typename Derived, typename Shape, typename Key> |
| 16811 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { | 16885 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
| 16812 int capacity = this->Capacity(); | 16886 int capacity = this->Capacity(); |
| 16813 for (int i = 0; i < capacity; i++) { | 16887 for (int i = 0; i < capacity; i++) { |
| 16814 Object* k = this->KeyAt(i); | 16888 Object* k = this->KeyAt(i); |
| 16815 if (this->IsKey(k)) { | 16889 if (this->IsKey(k)) { |
| 16816 Object* e = this->ValueAt(i); | 16890 Object* e = this->ValueAt(i); |
| 16817 // TODO(dcarney): this should be templatized. | 16891 // TODO(dcarney): this should be templatized. |
| 16818 if (e->IsPropertyCell()) { | 16892 if (e->IsPropertyCell()) { |
| (...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 18009 if (cell->value() != *new_value) { | 18083 if (cell->value() != *new_value) { |
| 18010 cell->set_value(*new_value); | 18084 cell->set_value(*new_value); |
| 18011 Isolate* isolate = cell->GetIsolate(); | 18085 Isolate* isolate = cell->GetIsolate(); |
| 18012 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18086 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 18013 isolate, DependentCode::kPropertyCellChangedGroup); | 18087 isolate, DependentCode::kPropertyCellChangedGroup); |
| 18014 } | 18088 } |
| 18015 } | 18089 } |
| 18016 | 18090 |
| 18017 } // namespace internal | 18091 } // namespace internal |
| 18018 } // namespace v8 | 18092 } // namespace v8 |
| OLD | NEW |