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 |