Chromium Code Reviews| Index: src/elements.cc |
| diff --git a/src/elements.cc b/src/elements.cc |
| index e83e4ec2c42f59defeb7b8c11d7f19e021107ae1..91bbfa93d6aa8f966531c4b2b0c4a3f2fbf0733f 100644 |
| --- a/src/elements.cc |
| +++ b/src/elements.cc |
| @@ -670,13 +670,64 @@ class ElementsAccessorBase : public ElementsAccessor { |
| return Handle<Object>(); |
| } |
| + virtual Handle<Object> Shift(Handle<JSArray> receiver, |
| + Handle<FixedArrayBase> backing_store) final { |
| + return ElementsAccessorSubclass::ShiftImpl(receiver, backing_store); |
| + } |
| + |
| + static Handle<Object> ShiftImpl(Handle<JSArray> receiver, |
| + Handle<FixedArrayBase> backing_store) { |
| + UNREACHABLE(); |
| + return Handle<Object>(); |
| + } |
| + |
| virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
| ElementsAccessorSubclass::SetLengthImpl(array, length, |
| handle(array->elements())); |
| } |
| static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| - Handle<FixedArrayBase> backing_store); |
| + Handle<FixedArrayBase> backing_store) { |
| + DCHECK(!array->SetLengthWouldNormalize(length)); |
| + DCHECK(IsFastElementsKind(array->GetElementsKind())); |
| + uint32_t old_length = 0; |
| + CHECK(array->length()->ToArrayIndex(&old_length)); |
| + |
| + if (old_length < length) { |
| + ElementsKind kind = array->GetElementsKind(); |
| + if (!IsFastHoleyElementsKind(kind)) { |
| + kind = GetHoleyElementsKind(kind); |
| + JSObject::TransitionElementsKind(array, kind); |
| + } |
| + } |
| + |
| + // Check whether the backing store should be shrunk. |
| + uint32_t capacity = backing_store->length(); |
| + if (length == 0) { |
| + array->initialize_elements(); |
| + } else if (length <= capacity) { |
| + if (array->HasFastSmiOrObjectElements()) { |
| + backing_store = JSObject::EnsureWritableFastElements(array); |
| + } |
| + if (2 * length <= capacity) { |
| + // If more than half the elements won't be used, trim the array. |
| + array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
| + *backing_store, capacity - length); |
| + } else { |
| + // Otherwise, fill the unused tail with holes. |
| + for (uint32_t i = length; i < old_length; i++) { |
| + BackingStore::cast(*backing_store)->set_the_hole(i); |
| + } |
| + } |
| + } else { |
| + // Check whether the backing store should be expanded. |
| + capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
| + ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
| + } |
| + |
| + array->set_length(Smi::FromInt(length)); |
| + JSObject::ValidateElements(array); |
| + } |
| static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
| Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
| @@ -1261,14 +1312,45 @@ class FastElementsAccessor |
| static Handle<Object> PopImpl(Handle<JSArray> receiver, |
| Handle<FixedArrayBase> backing_store) { |
| - uint32_t new_length = |
| - static_cast<uint32_t>(Smi::cast(receiver->length())->value()) - 1; |
| + uint32_t len = |
| + static_cast<uint32_t>(Smi::cast(receiver->length())->value()); |
| + if (len == 0) { |
|
Igor Sheludko
2015/09/02 12:35:20
ArrayPop already handles this case. Maybe this sho
Camillo Bruni
2015/09/02 13:04:55
Right.
|
| + return receiver->GetIsolate()->factory()->undefined_value(); |
| + } |
| + uint32_t new_length = len - 1; |
| Handle<Object> result = |
| FastElementsAccessorSubclass::GetImpl(backing_store, new_length); |
| FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, |
| backing_store); |
| if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { |
| + return receiver->GetIsolate()->factory()->undefined_value(); |
| + } |
| + return result; |
| + } |
| + |
| + static Handle<Object> ShiftImpl(Handle<JSArray> receiver, |
| + Handle<FixedArrayBase> backing_store) { |
| + uint32_t len = |
| + static_cast<uint32_t>(Smi::cast(receiver->length())->value()); |
| + Isolate* isolate = receiver->GetIsolate(); |
| + if (len == 0) { |
|
Igor Sheludko
2015/09/02 12:35:20
Same here.
Camillo Bruni
2015/09/02 13:04:55
ditto.
|
| + return isolate->factory()->undefined_value(); |
| + } |
| + int new_length = len - 1; |
| + Handle<Object> result = |
| + FastElementsAccessorSubclass::GetImpl(backing_store, 0); |
| + Heap* heap = isolate->heap(); |
| + if (heap->CanMoveObjectStart(*backing_store)) { |
| + receiver->set_elements(heap->LeftTrimFixedArray(*backing_store, 1)); |
| + } else { |
| + FastElementsAccessorSubclass::MoveElements(heap, backing_store, 0, 1, |
| + new_length, 0, 0); |
| + } |
| + FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, |
| + backing_store); |
| + |
| + if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { |
| result = receiver->GetIsolate()->factory()->undefined_value(); |
| } |
| return result; |
| @@ -2122,50 +2204,6 @@ class FastSloppyArgumentsElementsAccessor |
| }; |
| -template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
| -void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: |
| - SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| - Handle<FixedArrayBase> backing_store) { |
| - DCHECK(!array->SetLengthWouldNormalize(length)); |
| - DCHECK(IsFastElementsKind(array->GetElementsKind())); |
| - uint32_t old_length = 0; |
| - CHECK(array->length()->ToArrayIndex(&old_length)); |
| - |
| - if (old_length < length) { |
| - ElementsKind kind = array->GetElementsKind(); |
| - if (!IsFastHoleyElementsKind(kind)) { |
| - kind = GetHoleyElementsKind(kind); |
| - JSObject::TransitionElementsKind(array, kind); |
| - } |
| - } |
| - |
| - // Check whether the backing store should be shrunk. |
| - uint32_t capacity = backing_store->length(); |
| - if (length == 0) { |
| - array->initialize_elements(); |
| - } else if (length <= capacity) { |
| - if (array->HasFastSmiOrObjectElements()) { |
| - backing_store = JSObject::EnsureWritableFastElements(array); |
| - } |
| - if (2 * length <= capacity) { |
| - // If more than half the elements won't be used, trim the array. |
| - array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
| - *backing_store, capacity - length); |
| - } else { |
| - // Otherwise, fill the unused tail with holes. |
| - for (uint32_t i = length; i < old_length; i++) { |
| - BackingStore::cast(*backing_store)->set_the_hole(i); |
| - } |
| - } |
| - } else { |
| - // Check whether the backing store should be expanded. |
| - capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
| - ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
| - } |
| - |
| - array->set_length(Smi::FromInt(length)); |
| - JSObject::ValidateElements(array); |
| -} |
| } // namespace |