| 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);
|
| }
|
| }
|
|
|
|
|