| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index e16ccfc3f1bdaa72a0d69d71d04ecf7e2e08aced..d56067babb38af4411a642ad1ad39057dccd0c3f 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,41 @@ 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());
|
| + DCHECK(len > 0);
|
| + 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();
|
| + DCHECK(len > 0);
|
| + 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;
|
| @@ -1278,9 +1356,7 @@ class FastElementsAccessor
|
| Handle<FixedArrayBase> backing_store,
|
| Arguments* args, uint32_t push_size) {
|
| uint32_t len = Smi::cast(receiver->length())->value();
|
| - if (push_size == 0) {
|
| - return len;
|
| - }
|
| + DCHECK(push_size > 0);
|
| uint32_t elms_len = backing_store->length();
|
| // Currently fixed arrays cannot grow too big, so
|
| // we should never hit this case.
|
| @@ -1314,9 +1390,7 @@ class FastElementsAccessor
|
| Handle<FixedArrayBase> backing_store,
|
| Arguments* args, uint32_t unshift_size) {
|
| uint32_t len = Smi::cast(receiver->length())->value();
|
| - if (unshift_size == 0) {
|
| - return len;
|
| - }
|
| + DCHECK(unshift_size > 0);
|
| uint32_t elms_len = backing_store->length();
|
| // Currently fixed arrays cannot grow too big, so
|
| // we should never hit this case.
|
| @@ -1362,10 +1436,8 @@ class FastElementsAccessor
|
| static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
|
| Handle<FixedArrayBase> backing_store,
|
| uint32_t start, uint32_t end) {
|
| + DCHECK(start < end);
|
| Isolate* isolate = receiver->GetIsolate();
|
| - if (end <= start) {
|
| - return isolate->factory()->NewJSArray(KindTraits::Kind, 0, 0);
|
| - }
|
| int result_len = end - start;
|
| Handle<JSArray> result_array = isolate->factory()->NewJSArray(
|
| KindTraits::Kind, result_len, result_len);
|
| @@ -2122,50 +2194,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
|
|
|
|
|
|
|