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

Side by Side Diff: src/objects.cc

Issue 1409073005: [runtime] use std::vector in KeyAccumulator (Closed)
Patch Set: only check all levels when adding elements from iterceptors Created 5 years, 2 months 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
« src/objects.h ('K') | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 7484 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698