Index: src/elements.cc |
diff --git a/src/elements.cc b/src/elements.cc |
index 28700b8f0abe31e90e32a0f2c6be65d787c915dd..f882ce8c6455c538871b3186537fed62e85f4ea1 100644 |
--- a/src/elements.cc |
+++ b/src/elements.cc |
@@ -677,11 +677,12 @@ class ElementsAccessorBase : public ElementsAccessor { |
} |
void SetLength(Handle<JSArray> array, uint32_t length) final { |
- ElementsAccessorSubclass::SetLengthImpl(array, length, |
+ ElementsAccessorSubclass::SetLengthImpl(array->GetIsolate(), array, length, |
handle(array->elements())); |
} |
- static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
+ static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, |
+ uint32_t length, |
Handle<FixedArrayBase> backing_store) { |
DCHECK(!array->SetLengthWouldNormalize(length)); |
DCHECK(IsFastElementsKind(array->GetElementsKind())); |
@@ -698,6 +699,7 @@ class ElementsAccessorBase : public ElementsAccessor { |
// Check whether the backing store should be shrunk. |
uint32_t capacity = backing_store->length(); |
+ old_length = Min(old_length, capacity); |
if (length == 0) { |
array->initialize_elements(); |
} else if (length <= capacity) { |
@@ -706,7 +708,7 @@ class ElementsAccessorBase : public ElementsAccessor { |
} |
if (2 * length <= capacity) { |
// If more than half the elements won't be used, trim the array. |
- array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
+ isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
*backing_store, capacity - length); |
} else { |
// Otherwise, fill the unused tail with holes. |
@@ -972,11 +974,11 @@ class DictionaryElementsAccessor |
: ElementsAccessorBase<DictionaryElementsAccessor, |
ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
- static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
+ static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, |
+ uint32_t length, |
Handle<FixedArrayBase> backing_store) { |
Handle<SeededNumberDictionary> dict = |
Handle<SeededNumberDictionary>::cast(backing_store); |
- Isolate* isolate = array->GetIsolate(); |
int capacity = dict->Capacity(); |
uint32_t old_length = 0; |
CHECK(array->length()->ToArrayLength(&old_length)); |
@@ -1352,9 +1354,10 @@ class FastElementsAccessor |
receiver, backing_store, args, unshift_size, AT_START); |
} |
- static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store, |
- int dst_index, int src_index, int len, |
- int hole_start, int hole_end) { |
+ static void MoveElements(Isolate* isolate, Handle<JSArray> receiver, |
+ Handle<FixedArrayBase> backing_store, int dst_index, |
+ int src_index, int len, int hole_start, |
+ int hole_end) { |
UNREACHABLE(); |
} |
@@ -1403,13 +1406,13 @@ class FastElementsAccessor |
// Delete and move elements to make space for add_count new elements. |
if (add_count < delete_count) { |
- FastElementsAccessorSubclass::SpliceShrinkStep(backing_store, heap, start, |
- delete_count, add_count, |
- length, new_length); |
+ FastElementsAccessorSubclass::SpliceShrinkStep( |
+ isolate, receiver, backing_store, start, delete_count, add_count, |
+ length, new_length); |
} else if (add_count > delete_count) { |
backing_store = FastElementsAccessorSubclass::SpliceGrowStep( |
- receiver, backing_store, isolate, heap, start, delete_count, |
- add_count, length, new_length); |
+ isolate, receiver, backing_store, start, delete_count, add_count, |
+ length, new_length); |
} |
// Copy over the arguments. |
@@ -1423,29 +1426,33 @@ class FastElementsAccessor |
} |
private: |
- static void SpliceShrinkStep(Handle<FixedArrayBase> backing_store, Heap* heap, |
+ // SpliceShrinkStep might modify the backing_store. |
+ static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver, |
+ Handle<FixedArrayBase> backing_store, |
uint32_t start, uint32_t delete_count, |
uint32_t add_count, uint32_t len, |
uint32_t new_length) { |
const int move_left_count = len - delete_count - start; |
const int move_left_dst_index = start + add_count; |
FastElementsAccessorSubclass::MoveElements( |
- heap, backing_store, move_left_dst_index, start + delete_count, |
- move_left_count, new_length, len); |
+ isolate, receiver, backing_store, move_left_dst_index, |
+ start + delete_count, move_left_count, new_length, len); |
} |
- |
+ // SpliceGrowStep might modify the backing_store. |
static Handle<FixedArrayBase> SpliceGrowStep( |
- Handle<JSArray> receiver, Handle<FixedArrayBase> backing_store, |
- Isolate* isolate, Heap* heap, uint32_t start, uint32_t delete_count, |
- uint32_t add_count, uint32_t length, uint32_t new_length) { |
+ Isolate* isolate, Handle<JSArray> receiver, |
+ Handle<FixedArrayBase> backing_store, uint32_t start, |
+ uint32_t delete_count, uint32_t add_count, uint32_t length, |
+ uint32_t new_length) { |
// Check we do not overflow the new_length. |
DCHECK((add_count - delete_count) <= (Smi::kMaxValue - length)); |
// Check if backing_store is big enough. |
if (new_length <= static_cast<uint32_t>(backing_store->length())) { |
FastElementsAccessorSubclass::MoveElements( |
- heap, backing_store, start + add_count, start + delete_count, |
- (length - delete_count - start), 0, 0); |
+ isolate, receiver, backing_store, start + add_count, |
+ start + delete_count, (length - delete_count - start), 0, 0); |
+ // MoveElements updates the backing_store in-place. |
return backing_store; |
} |
// New backing storage is needed. |
@@ -1466,20 +1473,19 @@ class FastElementsAccessor |
static Handle<Object> RemoveElement(Handle<JSArray> receiver, |
Handle<FixedArrayBase> backing_store, |
Where remove_position) { |
+ Isolate* isolate = receiver->GetIsolate(); |
uint32_t length = |
static_cast<uint32_t>(Smi::cast(receiver->length())->value()); |
- Isolate* isolate = receiver->GetIsolate(); |
DCHECK(length > 0); |
int new_length = length - 1; |
int remove_index = remove_position == AT_START ? 0 : new_length; |
Handle<Object> result = |
FastElementsAccessorSubclass::GetImpl(backing_store, remove_index); |
if (remove_position == AT_START) { |
- Heap* heap = isolate->heap(); |
- FastElementsAccessorSubclass::MoveElements(heap, backing_store, 0, 1, |
- new_length, 0, 0); |
+ FastElementsAccessorSubclass::MoveElements( |
+ isolate, receiver, backing_store, 0, 1, new_length, 0, 0); |
} |
- FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, |
+ FastElementsAccessorSubclass::SetLengthImpl(isolate, receiver, new_length, |
backing_store); |
if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { |
@@ -1513,8 +1519,8 @@ class FastElementsAccessor |
// If the backing store has enough capacity and we add elements to the |
// start we have to shift the existing objects. |
Isolate* isolate = receiver->GetIsolate(); |
- FastElementsAccessorSubclass::MoveElements(isolate->heap(), backing_store, |
- add_size, 0, length, 0, 0); |
+ FastElementsAccessorSubclass::MoveElements( |
+ isolate, receiver, backing_store, add_size, 0, length, 0, 0); |
} |
int insertion_index = remove_position == AT_START ? 0 : length; |
@@ -1567,11 +1573,22 @@ class FastSmiOrObjectElementsAccessor |
return backing_store->get(index); |
} |
- static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store, |
- int dst_index, int src_index, int len, |
- int hole_start, int hole_end) { |
+ static void MoveElements(Isolate* isolate, Handle<JSArray> receiver, |
+ Handle<FixedArrayBase> backing_store, int dst_index, |
+ int src_index, int len, int hole_start, |
+ int hole_end) { |
+ Heap* heap = isolate->heap(); |
Handle<FixedArray> dst_elms = Handle<FixedArray>::cast(backing_store); |
- if (len != 0) { |
+ if (heap->CanMoveObjectStart(*dst_elms) && dst_index == 0) { |
+ // Update all the copies of this backing_store handle. |
+ *dst_elms.location() = |
+ FixedArray::cast(heap->LeftTrimFixedArray(*dst_elms, src_index)); |
+ receiver->set_elements(*dst_elms); |
+ // Adjust the hole offset as the array has been shrunk. |
+ hole_end -= src_index; |
+ DCHECK_LE(hole_start, backing_store->length()); |
+ DCHECK_LE(hole_end, backing_store->length()); |
+ } else if (len != 0) { |
DisallowHeapAllocation no_gc; |
heap->MoveElements(*dst_elms, dst_index, src_index, len); |
} |
@@ -1690,12 +1707,23 @@ class FastDoubleElementsAccessor |
FixedDoubleArray::cast(backing_store)->set(entry, value->Number()); |
} |
- static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store, |
- int dst_index, int src_index, int len, |
- int hole_start, int hole_end) { |
+ static void MoveElements(Isolate* isolate, Handle<JSArray> receiver, |
+ Handle<FixedArrayBase> backing_store, int dst_index, |
+ int src_index, int len, int hole_start, |
+ int hole_end) { |
+ Heap* heap = isolate->heap(); |
Handle<FixedDoubleArray> dst_elms = |
Handle<FixedDoubleArray>::cast(backing_store); |
- if (len != 0) { |
+ if (heap->CanMoveObjectStart(*dst_elms) && dst_index == 0) { |
+ // Update all the copies of this backing_store handle. |
+ *dst_elms.location() = FixedDoubleArray::cast( |
+ heap->LeftTrimFixedArray(*dst_elms, src_index)); |
+ receiver->set_elements(*dst_elms); |
+ // Adjust the hole offset as the array has been shrunk. |
+ hole_end -= src_index; |
+ DCHECK_LE(hole_start, backing_store->length()); |
+ DCHECK_LE(hole_end, backing_store->length()); |
+ } else if (len != 0) { |
MemMove(dst_elms->data_start() + dst_index, |
dst_elms->data_start() + src_index, len * kDoubleSize); |
} |
@@ -1801,7 +1829,8 @@ class TypedElementsAccessor |
return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); |
} |
- static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
+ static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, |
+ uint32_t length, |
Handle<FixedArrayBase> backing_store) { |
// External arrays do not support changing their length. |
UNREACHABLE(); |
@@ -1915,7 +1944,8 @@ class SloppyArgumentsElementsAccessor |
} |
} |
- static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
+ static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, |
+ uint32_t length, |
Handle<FixedArrayBase> parameter_map) { |
// Sloppy arguments objects are not arrays. |
UNREACHABLE(); |