| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 6c257ac63f3424b4dd531d1c936e0ff12e38bebd..398466509ce490b2f35cbe9f9740cc3301a6d168 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -445,6 +445,26 @@ static void TraceTopFrame(Isolate* isolate) {
|
| JavaScriptFrame::PrintTop(isolate, stdout, false, true);
|
| }
|
|
|
| +static void SortIndices(
|
| + Handle<FixedArray> indices, uint32_t sort_size,
|
| + WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER) {
|
| + struct {
|
| + bool operator()(Object* a, Object* b) {
|
| + if (!a->IsUndefined()) {
|
| + if (b->IsUndefined()) return true;
|
| + return a->Number() < b->Number();
|
| + }
|
| + return b->IsUndefined();
|
| + }
|
| + } cmp;
|
| + Object** start =
|
| + reinterpret_cast<Object**>(indices->GetFirstElementAddress());
|
| + std::sort(start, start + sort_size, cmp);
|
| + if (write_barrier_mode != SKIP_WRITE_BARRIER) {
|
| + FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices,
|
| + 0, sort_size);
|
| + }
|
| +}
|
|
|
| // Base class for element handler implementations. Contains the
|
| // the common logic for objects with different ElementsKinds.
|
| @@ -709,8 +729,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| JSObject::ValidateElements(array);
|
| }
|
|
|
| - static uint32_t GetIterationLength(JSObject* receiver,
|
| - FixedArrayBase* elements) {
|
| + static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
|
| if (receiver->IsJSArray()) {
|
| DCHECK(JSArray::cast(receiver)->length()->IsSmi());
|
| return static_cast<uint32_t>(
|
| @@ -719,6 +738,11 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| return Subclass::GetCapacityImpl(receiver, elements);
|
| }
|
|
|
| + static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
|
| + FixedArrayBase* elements) {
|
| + return Subclass::GetMaxIndex(receiver, elements);
|
| + }
|
| +
|
| static Handle<FixedArrayBase> ConvertElementsWithCapacity(
|
| Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
|
| ElementsKind from_kind, uint32_t capacity) {
|
| @@ -863,7 +887,6 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| PropertyFilter filter) {
|
| int count = 0;
|
| KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
|
| - accumulator.NextPrototype();
|
| Subclass::CollectElementIndicesImpl(
|
| object, handle(object->elements(), isolate), &accumulator);
|
| Handle<FixedArray> keys = accumulator.GetKeys();
|
| @@ -909,11 +932,12 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| KeyAccumulator* keys) {
|
| DCHECK_NE(DICTIONARY_ELEMENTS, kind());
|
| // Non-dictionary elements can't have all-can-read accessors.
|
| - uint32_t length = GetIterationLength(*object, *backing_store);
|
| + uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
|
| PropertyFilter filter = keys->filter();
|
| + Factory* factory = keys->isolate()->factory();
|
| for (uint32_t i = 0; i < length; i++) {
|
| if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
|
| - keys->AddKey(i);
|
| + keys->AddKey(factory->NewNumberFromUint(i));
|
| }
|
| }
|
| }
|
| @@ -923,7 +947,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
|
| PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
|
| uint32_t insertion_index = 0) {
|
| - uint32_t length = Subclass::GetIterationLength(*object, *backing_store);
|
| + uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
|
| for (uint32_t i = 0; i < length; i++) {
|
| if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
|
| if (convert == CONVERT_TO_STRING) {
|
| @@ -968,18 +992,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
|
|
| // Sort the indices list if necessary.
|
| if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
|
| - struct {
|
| - bool operator()(Object* a, Object* b) {
|
| - if (!a->IsUndefined()) {
|
| - if (b->IsUndefined()) return true;
|
| - return a->Number() < b->Number();
|
| - }
|
| - return !b->IsUndefined();
|
| - }
|
| - } cmp;
|
| - Object** start =
|
| - reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress());
|
| - std::sort(start, start + nof_indices, cmp);
|
| + SortIndices(combined_keys, nof_indices, SKIP_WRITE_BARRIER);
|
| uint32_t array_length = 0;
|
| // Indices from dictionary elements should only be converted after
|
| // sorting.
|
| @@ -1044,7 +1057,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| ? index
|
| : kMaxUInt32;
|
| } else {
|
| - uint32_t length = GetIterationLength(holder, backing_store);
|
| + uint32_t length = Subclass::GetMaxIndex(holder, backing_store);
|
| return index < length ? index : kMaxUInt32;
|
| }
|
| }
|
| @@ -1081,17 +1094,15 @@ class DictionaryElementsAccessor
|
| : ElementsAccessorBase<DictionaryElementsAccessor,
|
| ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
|
|
|
| - static uint32_t GetIterationLength(JSObject* receiver,
|
| - FixedArrayBase* elements) {
|
| - uint32_t length;
|
| - if (receiver->IsJSArray()) {
|
| - // Special-case GetIterationLength for dictionary elements since the
|
| - // length of the array might be a HeapNumber.
|
| - JSArray::cast(receiver)->length()->ToArrayLength(&length);
|
| - } else {
|
| - length = GetCapacityImpl(receiver, elements);
|
| - }
|
| - return length;
|
| + static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
|
| + // We cannot properly estimate this for dictionaries.
|
| + UNREACHABLE();
|
| + }
|
| +
|
| + static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
|
| + FixedArrayBase* backing_store) {
|
| + SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
|
| + return dict->NumberOfElements();
|
| }
|
|
|
| static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
|
| @@ -1313,21 +1324,28 @@ class DictionaryElementsAccessor
|
| Handle<FixedArrayBase> backing_store,
|
| KeyAccumulator* keys) {
|
| if (keys->filter() & SKIP_STRINGS) return;
|
| - Isolate* isolate = keys->isolate();
|
| - Handle<Object> undefined = isolate->factory()->undefined_value();
|
| - Handle<Object> the_hole = isolate->factory()->the_hole_value();
|
| + Factory* factory = keys->isolate()->factory();
|
| + Handle<Object> undefined = factory->undefined_value();
|
| + Handle<Object> the_hole = factory->the_hole_value();
|
| Handle<SeededNumberDictionary> dictionary =
|
| Handle<SeededNumberDictionary>::cast(backing_store);
|
| int capacity = dictionary->Capacity();
|
| + Handle<FixedArray> elements =
|
| + factory->NewFixedArray(GetMaxNumberOfEntries(*object, *backing_store));
|
| + int insertion_index = 0;
|
| PropertyFilter filter = keys->filter();
|
| for (int i = 0; i < capacity; i++) {
|
| uint32_t key =
|
| GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
|
| if (key == kMaxUInt32) continue;
|
| - keys->AddKey(key);
|
| + Handle<Object> key_handle = factory->NewNumberFromUint(key);
|
| + elements->set(insertion_index, *key_handle);
|
| + insertion_index++;
|
| + }
|
| + SortIndices(elements, insertion_index);
|
| + for (int i = 0; i < insertion_index; i++) {
|
| + keys->AddKey(elements->get(i));
|
| }
|
| -
|
| - keys->SortCurrentElementsList();
|
| }
|
|
|
| static Handle<FixedArray> DirectCollectElementIndicesImpl(
|
| @@ -1552,8 +1570,8 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
|
| KeyAccumulator* accumulator,
|
| AddKeyConversion convert) {
|
| Handle<FixedArrayBase> elements(receiver->elements(),
|
| - receiver->GetIsolate());
|
| - uint32_t length = Subclass::GetIterationLength(*receiver, *elements);
|
| + accumulator->isolate());
|
| + uint32_t length = Subclass::GetMaxNumberOfEntries(*receiver, *elements);
|
| for (uint32_t i = 0; i < length; i++) {
|
| if (IsFastPackedElementsKind(KindTraits::Kind) ||
|
| HasEntryImpl(*elements, i)) {
|
| @@ -2386,18 +2404,16 @@ class SloppyArgumentsElementsAccessor
|
| static void CollectElementIndicesImpl(Handle<JSObject> object,
|
| Handle<FixedArrayBase> backing_store,
|
| KeyAccumulator* keys) {
|
| - FixedArray* parameter_map = FixedArray::cast(*backing_store);
|
| - uint32_t length = parameter_map->length() - 2;
|
| - for (uint32_t i = 0; i < length; ++i) {
|
| - if (!parameter_map->get(i + 2)->IsTheHole()) {
|
| - keys->AddKey(i);
|
| - }
|
| - }
|
| -
|
| - Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
|
| - ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys);
|
| - if (Subclass::kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
|
| - keys->SortCurrentElementsList();
|
| + Isolate* isolate = keys->isolate();
|
| + uint32_t nof_indices = 0;
|
| + Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
|
| + GetCapacityImpl(*object, *backing_store));
|
| + DirectCollectElementIndicesImpl(isolate, object, backing_store,
|
| + KEEP_NUMBERS, ENUMERABLE_STRINGS, indices,
|
| + &nof_indices);
|
| + SortIndices(indices, nof_indices);
|
| + for (uint32_t i = 0; i < nof_indices; i++) {
|
| + keys->AddKey(indices->get(i));
|
| }
|
| }
|
|
|
| @@ -2745,8 +2761,9 @@ class StringWrapperElementsAccessor
|
| Handle<FixedArrayBase> backing_store,
|
| KeyAccumulator* keys) {
|
| uint32_t length = GetString(*object)->length();
|
| + Factory* factory = keys->isolate()->factory();
|
| for (uint32_t i = 0; i < length; i++) {
|
| - keys->AddKey(i);
|
| + keys->AddKey(factory->NewNumberFromUint(i));
|
| }
|
| BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store,
|
| keys);
|
|
|