Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 433dda7d6f98daa1aac991c04413c4d3d4501bc8..327bbc2fe439de93ec7d68169cc9908538a6bf87 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -7525,7 +7525,7 @@ Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object, |
KeyAccumulator::~KeyAccumulator() { |
- for (int i = 0; i < elements_.length(); i++) { |
+ for (size_t i = 0; i < elements_.size(); i++) { |
delete elements_[i]; |
} |
} |
@@ -7546,7 +7546,7 @@ Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); |
int index = 0; |
int properties_index = 0; |
- for (int level = 0; level < levelLengths_.length(); level++) { |
+ for (size_t level = 0; level < levelLengths_.size(); level++) { |
int num_total = levelLengths_[level]; |
int num_elements = 0; |
if (num_total < 0) { |
@@ -7554,9 +7554,9 @@ Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
// proxy, hence we skip the integer keys in |elements_| since proxies |
// define the complete ordering. |
num_total = -num_total; |
- } else if (level < elements_.length()) { |
- List<uint32_t>* elements = elements_[level]; |
- num_elements = elements->length(); |
+ } else if (level < elements_.size()) { |
+ std::vector<uint32_t>* elements = elements_[level]; |
+ num_elements = static_cast<int>(elements->size()); |
for (int i = 0; i < num_elements; i++) { |
Handle<Object> key; |
if (convert == KEEP_NUMBERS) { |
@@ -7577,6 +7577,7 @@ Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
properties_index++; |
} |
} |
+ |
DCHECK_EQ(index, length_); |
return result; |
} |
@@ -7584,22 +7585,8 @@ Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
namespace { |
-class FindKey { |
- public: |
- explicit FindKey(uint32_t key) : key_(key) {} |
- int operator()(uint32_t* entry) { |
- if (*entry == key_) return 0; |
- return *entry < key_ ? -1 : 1; |
- } |
- |
- private: |
- uint32_t key_; |
-}; |
- |
- |
-bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) { |
- int index = SortedListBSearch(*sub_elements, FindKey(key)); |
- return index != -1; |
+bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) { |
+ return std::binary_search(sub_elements->begin(), sub_elements->end(), key); |
} |
} // namespace |
@@ -7607,12 +7594,14 @@ bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) { |
bool KeyAccumulator::AddKey(uint32_t key) { |
// Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). |
+ // We mark proxy-levels with a negative length |
DCHECK_LE(0, levelLength_); |
- int lookup_limit = elements_.length(); |
- for (int i = 0; i < lookup_limit; i++) { |
- if (AccumulatorHasKey(elements_[i], key)) return false; |
+ // Binary search over all but the last level. The last one might not be |
+ // sorted yet. |
+ for (size_t i = 1; i < elements_.size(); i++) { |
+ if (AccumulatorHasKey(elements_[i - 1], key)) return false; |
} |
- elements_[lookup_limit - 1]->Add(key); |
+ elements_.back()->push_back(key); |
length_++; |
levelLength_++; |
return true; |
@@ -7706,32 +7695,43 @@ void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) { |
} |
-namespace { |
- |
-// Used for sorting indices in a List<uint32_t>. |
-int compareUInt32(const uint32_t* ap, const uint32_t* bp) { |
- uint32_t a = *ap; |
- uint32_t b = *bp; |
- return (a == b) ? 0 : (a < b) ? -1 : 1; |
+void KeyAccumulator::AddElementKeysFromInterceptor( |
+ Handle<JSObject> array_like) { |
+ AddKeys(array_like, CONVERT_TO_ARRAY_INDEX); |
+ // The interceptor might introduce duplicates for the current level, since |
+ // these keys get added after the objects's normal element keys. |
+ SortCurrentElementsListRemoveDuplicates(); |
} |
-} // namespace |
+void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() { |
+ // Sort and remove duplciated from the current elements level and adjust |
+ // the lengths accordingly. |
+ auto last_level = elements_.back(); |
+ size_t nof_removed_keys = last_level->size(); |
+ std::sort(last_level->begin(), last_level->end()); |
+ last_level->erase(std::unique(last_level->begin(), last_level->end()), |
+ last_level->end()); |
+ // Adjust total length / level length by the number of removed duplicates |
+ nof_removed_keys -= last_level->size(); |
+ levelLength_ -= static_cast<int>(nof_removed_keys); |
+ length_ -= static_cast<int>(nof_removed_keys); |
+} |
void KeyAccumulator::SortCurrentElementsList() { |
- if (elements_.length() == 0) return; |
- List<uint32_t>* element_keys = elements_[elements_.length() - 1]; |
- element_keys->Sort(&compareUInt32); |
+ if (elements_.empty()) return; |
+ auto element_keys = elements_.back(); |
+ std::sort(element_keys->begin(), element_keys->end()); |
} |
void KeyAccumulator::NextPrototype() { |
// Store the protoLength on the first call of this method. |
- if (!elements_.is_empty()) { |
- levelLengths_.Add(levelLength_); |
+ if (!elements_.empty()) { |
+ levelLengths_.push_back(levelLength_); |
} |
- elements_.Add(new List<uint32_t>()); |
+ elements_.push_back(new std::vector<uint32_t>()); |
levelLength_ = 0; |
} |
@@ -7745,7 +7745,6 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
KeyAccumulator accumulator(isolate, filter); |
Handle<JSFunction> arguments_function( |
JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
- |
PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
? PrototypeIterator::END_AT_NON_HIDDEN |
: PrototypeIterator::END_AT_NULL; |
@@ -7790,7 +7789,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
Handle<JSObject> result; |
if (JSObject::GetKeysForIndexedInterceptor(current, object) |
.ToHandle(&result)) { |
- accumulator.AddKeys(result, CONVERT_TO_ARRAY_INDEX); |
+ accumulator.AddElementKeysFromInterceptor(result); |
} |
} |