Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: src/objects.cc

Issue 1409073005: [runtime] use std::vector in KeyAccumulator (Closed)
Patch Set: sparse array keys fix 2 Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 7507 matching lines...) Expand 10 before | Expand all | Expand 10 after
7518 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 7518 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
7519 } 7519 }
7520 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 7520 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
7521 dictionary->CopyEnumKeysTo(*storage); 7521 dictionary->CopyEnumKeysTo(*storage);
7522 return storage; 7522 return storage;
7523 } 7523 }
7524 } 7524 }
7525 7525
7526 7526
7527 KeyAccumulator::~KeyAccumulator() { 7527 KeyAccumulator::~KeyAccumulator() {
7528 for (int i = 0; i < elements_.length(); i++) { 7528 for (size_t i = 0; i < elements_.size(); i++) {
7529 delete elements_[i]; 7529 delete elements_[i];
7530 } 7530 }
7531 } 7531 }
7532 7532
7533 7533
7534 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { 7534 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
7535 if (length_ == 0) { 7535 if (length_ == 0) {
7536 return isolate_->factory()->empty_fixed_array(); 7536 return isolate_->factory()->empty_fixed_array();
7537 } 7537 }
7538 // Make sure we have all the lengths collected. 7538 // Make sure we have all the lengths collected.
7539 NextPrototype(); 7539 NextPrototype();
7540 7540
7541 // Assemble the result array by first adding the element keys and then 7541 // Assemble the result array by first adding the element keys and then
7542 // the property keys. We use the total number of keys per level in 7542 // the property keys. We use the total number of keys per level in
7543 // |protoLengths_| and the available element keys in the corresponding bucket 7543 // |protoLengths_| and the available element keys in the corresponding bucket
7544 // in |elements_| to deduce the number of keys to take from the |properties_| 7544 // in |elements_| to deduce the number of keys to take from the |properties_|
7545 // set. 7545 // set.
7546 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); 7546 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_);
7547 int index = 0; 7547 int index = 0;
7548 int properties_index = 0; 7548 int properties_index = 0;
7549 for (int level = 0; level < levelLengths_.length(); level++) { 7549 for (size_t level = 0; level < levelLengths_.size(); level++) {
7550 int num_total = levelLengths_[level]; 7550 int num_total = levelLengths_[level];
7551 int num_elements = 0; 7551 int num_elements = 0;
7552 if (num_total < 0) { 7552 if (num_total < 0) {
7553 // If the total is negative, the current level contains properties from a 7553 // If the total is negative, the current level contains properties from a
7554 // proxy, hence we skip the integer keys in |elements_| since proxies 7554 // proxy, hence we skip the integer keys in |elements_| since proxies
7555 // define the complete ordering. 7555 // define the complete ordering.
7556 num_total = -num_total; 7556 num_total = -num_total;
7557 } else if (level < elements_.length()) { 7557 } else if (level < elements_.size()) {
7558 List<uint32_t>* elements = elements_[level]; 7558 std::vector<uint32_t>* elements = elements_[level];
7559 num_elements = elements->length(); 7559 num_elements = static_cast<int>(elements->size());
7560 for (int i = 0; i < num_elements; i++) { 7560 for (int i = 0; i < num_elements; i++) {
7561 Handle<Object> key; 7561 Handle<Object> key;
7562 if (convert == KEEP_NUMBERS) { 7562 if (convert == KEEP_NUMBERS) {
7563 key = isolate_->factory()->NewNumberFromUint(elements->at(i)); 7563 key = isolate_->factory()->NewNumberFromUint(elements->at(i));
7564 } else { 7564 } else {
7565 key = isolate_->factory()->Uint32ToString(elements->at(i)); 7565 key = isolate_->factory()->Uint32ToString(elements->at(i));
7566 } 7566 }
7567 result->set(index, *key); 7567 result->set(index, *key);
7568 index++; 7568 index++;
7569 } 7569 }
7570 } 7570 }
7571 // Add the property keys for this prototype level. 7571 // Add the property keys for this prototype level.
7572 int num_properties = num_total - num_elements; 7572 int num_properties = num_total - num_elements;
7573 for (int i = 0; i < num_properties; i++) { 7573 for (int i = 0; i < num_properties; i++) {
7574 Object* key = properties_->KeyAt(properties_index); 7574 Object* key = properties_->KeyAt(properties_index);
7575 result->set(index, key); 7575 result->set(index, key);
7576 index++; 7576 index++;
7577 properties_index++; 7577 properties_index++;
7578 } 7578 }
7579 } 7579 }
7580
7580 DCHECK_EQ(index, length_); 7581 DCHECK_EQ(index, length_);
7581 return result; 7582 return result;
7582 } 7583 }
7583 7584
7584 7585
7585 namespace { 7586 namespace {
7586 7587
7587 class FindKey { 7588 bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) {
7588 public: 7589 return std::binary_search(sub_elements->begin(), sub_elements->end(), key);
7589 explicit FindKey(uint32_t key) : key_(key) {}
7590 int operator()(uint32_t* entry) {
7591 if (*entry == key_) return 0;
7592 return *entry < key_ ? -1 : 1;
7593 }
7594
7595 private:
7596 uint32_t key_;
7597 };
7598
7599
7600 bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) {
7601 int index = SortedListBSearch(*sub_elements, FindKey(key));
7602 return index != -1;
7603 } 7590 }
7604 7591
7605 } // namespace 7592 } // namespace
7606 7593
7607 7594
7608 bool KeyAccumulator::AddKey(uint32_t key) { 7595 bool KeyAccumulator::AddKey(uint32_t key) {
7609 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). 7596 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy).
7597 // We mark proxy-levels with a negative length
7610 DCHECK_LE(0, levelLength_); 7598 DCHECK_LE(0, levelLength_);
7611 int lookup_limit = elements_.length(); 7599 // Binary search over all but the last level. The last one might not be
7612 for (int i = 0; i < lookup_limit; i++) { 7600 // sorted yet.
7613 if (AccumulatorHasKey(elements_[i], key)) return false; 7601 for (size_t i = 1; i < elements_.size(); i++) {
7602 if (AccumulatorHasKey(elements_[i - 1], key)) return false;
7614 } 7603 }
7615 elements_[lookup_limit - 1]->Add(key); 7604 elements_.back()->push_back(key);
7616 length_++; 7605 length_++;
7617 levelLength_++; 7606 levelLength_++;
7618 return true; 7607 return true;
7619 } 7608 }
7620 7609
7621 7610
7622 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) { 7611 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
7623 return AddKey(handle(key, isolate_), convert); 7612 return AddKey(handle(key, isolate_), convert);
7624 } 7613 }
7625 7614
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
7699 // elements and properties, which breaks the normal assumption for the 7688 // elements and properties, which breaks the normal assumption for the
7700 // KeyAccumulator. 7689 // KeyAccumulator.
7701 AddKeys(array_like, PROXY_MAGIC); 7690 AddKeys(array_like, PROXY_MAGIC);
7702 // Invert the current length to indicate a present proxy, so we can ignore 7691 // Invert the current length to indicate a present proxy, so we can ignore
7703 // element keys for this level. Otherwise we would not fully respect the order 7692 // element keys for this level. Otherwise we would not fully respect the order
7704 // given by the proxy. 7693 // given by the proxy.
7705 levelLength_ = -levelLength_; 7694 levelLength_ = -levelLength_;
7706 } 7695 }
7707 7696
7708 7697
7709 namespace { 7698 void KeyAccumulator::AddElementKeysFromInterceptor(
7710 7699 Handle<JSObject> array_like) {
7711 // Used for sorting indices in a List<uint32_t>. 7700 AddKeys(array_like, CONVERT_TO_ARRAY_INDEX);
7712 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { 7701 SortRemoveDuplicates();
7713 uint32_t a = *ap;
7714 uint32_t b = *bp;
7715 return (a == b) ? 0 : (a < b) ? -1 : 1;
7716 } 7702 }
7717 7703
7718 7704
7719 } // namespace 7705 void KeyAccumulator::SortRemoveDuplicates() {
7706 // The accumulator might introduce duplicates for the current level, since
7707 // these keys get added after the object's element keys.
7708 auto last_level = elements_.back();
7709 size_t nof_removed_keys = last_level->size();
7710 std::sort(last_level->begin(), last_level->end());
7711 last_level->erase(std::unique(last_level->begin(), last_level->end()),
7712 last_level->end());
7713 // Adjust total length / level length by the number of removed duplicates
7714 nof_removed_keys -= last_level->size();
7715 levelLength_ -= static_cast<int>(nof_removed_keys);
7716 length_ -= static_cast<int>(nof_removed_keys);
7717 }
7720 7718
7721 7719
7722 void KeyAccumulator::SortCurrentElementsList() { 7720 void KeyAccumulator::SortCurrentElementsList() {
7723 if (elements_.length() == 0) return; 7721 if (elements_.empty()) return;
7724 List<uint32_t>* element_keys = elements_[elements_.length() - 1]; 7722 auto element_keys = elements_.back();
7725 element_keys->Sort(&compareUInt32); 7723 std::sort(element_keys->begin(), element_keys->end());
7726 } 7724 }
7727 7725
7728 7726
7729 void KeyAccumulator::NextPrototype() { 7727 void KeyAccumulator::NextPrototype() {
7730 // Store the protoLength on the first call of this method. 7728 // Store the protoLength on the first call of this method.
7731 if (!elements_.is_empty()) { 7729 if (!elements_.empty()) {
7732 levelLengths_.Add(levelLength_); 7730 levelLengths_.push_back(levelLength_);
7733 } 7731 }
7734 elements_.Add(new List<uint32_t>()); 7732 elements_.push_back(new std::vector<uint32_t>());
7735 levelLength_ = 0; 7733 levelLength_ = 0;
7736 } 7734 }
7737 7735
7738 7736
7739 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 7737 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
7740 KeyCollectionType type, 7738 KeyCollectionType type,
7741 KeyFilter filter, 7739 KeyFilter filter,
7742 GetKeysConversion getConversion) { 7740 GetKeysConversion getConversion) {
7743 USE(ContainsOnlyValidKeys); 7741 USE(ContainsOnlyValidKeys);
7744 Isolate* isolate = object->GetIsolate(); 7742 Isolate* isolate = object->GetIsolate();
7745 KeyAccumulator accumulator(isolate, filter); 7743 KeyAccumulator accumulator(isolate, filter);
7746 Handle<JSFunction> arguments_function( 7744 Handle<JSFunction> arguments_function(
7747 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 7745 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
7748
7749 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 7746 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
7750 ? PrototypeIterator::END_AT_NON_HIDDEN 7747 ? PrototypeIterator::END_AT_NON_HIDDEN
7751 : PrototypeIterator::END_AT_NULL; 7748 : PrototypeIterator::END_AT_NULL;
7752 // Only collect keys if access is permitted. 7749 // Only collect keys if access is permitted.
7753 for (PrototypeIterator iter(isolate, object, 7750 for (PrototypeIterator iter(isolate, object,
7754 PrototypeIterator::START_AT_RECEIVER); 7751 PrototypeIterator::START_AT_RECEIVER);
7755 !iter.IsAtEnd(end); iter.Advance()) { 7752 !iter.IsAtEnd(end); iter.Advance()) {
7756 accumulator.NextPrototype(); 7753 accumulator.NextPrototype();
7757 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 7754 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
7758 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 7755 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
(...skipping 24 matching lines...) Expand all
7783 } 7780 }
7784 7781
7785 JSObject::CollectOwnElementKeys(current, &accumulator, 7782 JSObject::CollectOwnElementKeys(current, &accumulator,
7786 static_cast<PropertyAttributes>(DONT_ENUM)); 7783 static_cast<PropertyAttributes>(DONT_ENUM));
7787 7784
7788 // Add the element keys from the interceptor. 7785 // Add the element keys from the interceptor.
7789 if (current->HasIndexedInterceptor()) { 7786 if (current->HasIndexedInterceptor()) {
7790 Handle<JSObject> result; 7787 Handle<JSObject> result;
7791 if (JSObject::GetKeysForIndexedInterceptor(current, object) 7788 if (JSObject::GetKeysForIndexedInterceptor(current, object)
7792 .ToHandle(&result)) { 7789 .ToHandle(&result)) {
7793 accumulator.AddKeys(result, CONVERT_TO_ARRAY_INDEX); 7790 accumulator.AddElementKeysFromInterceptor(result);
7794 } 7791 }
7795 } 7792 }
7796 7793
7797 if (filter == SKIP_SYMBOLS) { 7794 if (filter == SKIP_SYMBOLS) {
7798 // We can cache the computed property keys if access checks are 7795 // We can cache the computed property keys if access checks are
7799 // not needed and no interceptors are involved. 7796 // not needed and no interceptors are involved.
7800 // 7797 //
7801 // We do not use the cache if the object has elements and 7798 // We do not use the cache if the object has elements and
7802 // therefore it does not make sense to cache the property names 7799 // therefore it does not make sense to cache the property names
7803 // for arguments objects. Arguments objects will always have 7800 // for arguments objects. Arguments objects will always have
(...skipping 10043 matching lines...) Expand 10 before | Expand all | Expand 10 after
17847 if (cell->value() != *new_value) { 17844 if (cell->value() != *new_value) {
17848 cell->set_value(*new_value); 17845 cell->set_value(*new_value);
17849 Isolate* isolate = cell->GetIsolate(); 17846 Isolate* isolate = cell->GetIsolate();
17850 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17847 cell->dependent_code()->DeoptimizeDependentCodeGroup(
17851 isolate, DependentCode::kPropertyCellChangedGroup); 17848 isolate, DependentCode::kPropertyCellChangedGroup);
17852 } 17849 }
17853 } 17850 }
17854 17851
17855 } // namespace internal 17852 } // namespace internal
17856 } // namespace v8 17853 } // namespace v8
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698