@@ -691,11 +691,12 @@ class ElementsAccessorBase : public ElementsAccessor {
691691 }
692692
693693 virtual void SetLength (Handle<JSArray> array, uint32_t length) final {
694- ElementsAccessorSubclass::SetLengthImpl (array, length,
694+ ElementsAccessorSubclass::SetLengthImpl (array-> GetIsolate (), array , length,
695695 handle (array->elements ()));
696696 }
697697
698- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
698+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
699+ uint32_t length,
699700 Handle<FixedArrayBase> backing_store) {
700701 DCHECK (!array->SetLengthWouldNormalize (length));
701702 DCHECK (IsFastElementsKind (array->GetElementsKind ()));
@@ -712,6 +713,7 @@ class ElementsAccessorBase : public ElementsAccessor {
712713
713714 // Check whether the backing store should be shrunk.
714715 uint32_t capacity = backing_store->length ();
716+ old_length = Min (old_length, capacity);
715717 if (length == 0 ) {
716718 array->initialize_elements ();
717719 } else if (length <= capacity) {
@@ -720,7 +722,7 @@ class ElementsAccessorBase : public ElementsAccessor {
720722 }
721723 if (2 * length <= capacity) {
722724 // If more than half the elements won't be used, trim the array.
723- array-> GetHeap ()->RightTrimFixedArray <Heap::CONCURRENT_TO_SWEEPER>(
725+ isolate-> heap ()->RightTrimFixedArray <Heap::CONCURRENT_TO_SWEEPER>(
724726 *backing_store, capacity - length);
725727 } else {
726728 // Otherwise, fill the unused tail with holes.
@@ -954,11 +956,11 @@ class DictionaryElementsAccessor
954956 : ElementsAccessorBase<DictionaryElementsAccessor,
955957 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
956958
957- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
959+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
960+ uint32_t length,
958961 Handle<FixedArrayBase> backing_store) {
959962 Handle<SeededNumberDictionary> dict =
960963 Handle<SeededNumberDictionary>::cast (backing_store);
961- Isolate* isolate = array->GetIsolate ();
962964 int capacity = dict->Capacity ();
963965 uint32_t old_length = 0 ;
964966 CHECK (array->length ()->ToArrayLength (&old_length));
@@ -1181,13 +1183,18 @@ class FastElementsAccessor
11811183 }
11821184 int num_used = 0 ;
11831185 for (int i = 0 ; i < backing_store->length (); ++i) {
1184- if (!backing_store->is_the_hole (i)) ++num_used;
1185- // Bail out early if more than 1/4 is used.
1186- if (4 * num_used > backing_store->length ()) break ;
1187- }
1188- if (4 * num_used <= backing_store->length ()) {
1189- JSObject::NormalizeElements (obj);
1186+ if (!backing_store->is_the_hole (i)) {
1187+ ++num_used;
1188+ // Bail out if a number dictionary wouldn't be able to save at least
1189+ // 75% space.
1190+ if (4 * SeededNumberDictionary::ComputeCapacity (num_used) *
1191+ SeededNumberDictionary::kEntrySize >
1192+ backing_store->length ()) {
1193+ return ;
1194+ }
1195+ }
11901196 }
1197+ JSObject::NormalizeElements (obj);
11911198 }
11921199 }
11931200
@@ -1293,9 +1300,10 @@ class FastElementsAccessor
12931300 receiver, backing_store, args, unshift_size, AT_START);
12941301 }
12951302
1296- static void MoveElements (Heap* heap, Handle<FixedArrayBase> backing_store,
1297- int dst_index, int src_index, int len,
1298- int hole_start, int hole_end) {
1303+ static void MoveElements (Isolate* isolate, Handle<JSArray> receiver,
1304+ Handle<FixedArrayBase> backing_store, int dst_index,
1305+ int src_index, int len, int hole_start,
1306+ int hole_end) {
12991307 UNREACHABLE ();
13001308 }
13011309
@@ -1344,13 +1352,13 @@ class FastElementsAccessor
13441352
13451353 // Delete and move elements to make space for add_count new elements.
13461354 if (add_count < delete_count) {
1347- FastElementsAccessorSubclass::SpliceShrinkStep (backing_store, heap, start,
1348- delete_count, add_count,
1349- length, new_length);
1355+ FastElementsAccessorSubclass::SpliceShrinkStep (
1356+ isolate, receiver, backing_store, start, delete_count, add_count,
1357+ length, new_length);
13501358 } else if (add_count > delete_count) {
13511359 backing_store = FastElementsAccessorSubclass::SpliceGrowStep (
1352- receiver, backing_store, isolate, heap, start, delete_count,
1353- add_count, length, new_length);
1360+ isolate, receiver, backing_store, start, delete_count, add_count ,
1361+ length, new_length);
13541362 }
13551363
13561364 // Copy over the arguments.
@@ -1364,29 +1372,33 @@ class FastElementsAccessor
13641372 }
13651373
13661374 private:
1367- static void SpliceShrinkStep (Handle<FixedArrayBase> backing_store, Heap* heap,
1375+ // SpliceShrinkStep might modify the backing_store.
1376+ static void SpliceShrinkStep (Isolate* isolate, Handle<JSArray> receiver,
1377+ Handle<FixedArrayBase> backing_store,
13681378 uint32_t start, uint32_t delete_count,
13691379 uint32_t add_count, uint32_t len,
13701380 uint32_t new_length) {
13711381 const int move_left_count = len - delete_count - start;
13721382 const int move_left_dst_index = start + add_count;
13731383 FastElementsAccessorSubclass::MoveElements (
1374- heap, backing_store, move_left_dst_index, start + delete_count ,
1375- move_left_count, new_length, len);
1384+ isolate, receiver, backing_store, move_left_dst_index ,
1385+ start + delete_count, move_left_count, new_length, len);
13761386 }
13771387
1378-
1388+ // SpliceGrowStep might modify the backing_store.
13791389 static Handle<FixedArrayBase> SpliceGrowStep (
1380- Handle<JSArray> receiver, Handle<FixedArrayBase> backing_store,
1381- Isolate* isolate, Heap* heap, uint32_t start, uint32_t delete_count,
1382- uint32_t add_count, uint32_t length, uint32_t new_length) {
1390+ Isolate* isolate, Handle<JSArray> receiver,
1391+ Handle<FixedArrayBase> backing_store, uint32_t start,
1392+ uint32_t delete_count, uint32_t add_count, uint32_t length,
1393+ uint32_t new_length) {
13831394 // Check we do not overflow the new_length.
13841395 DCHECK ((add_count - delete_count) <= (Smi::kMaxValue - length));
13851396 // Check if backing_store is big enough.
13861397 if (new_length <= static_cast <uint32_t >(backing_store->length ())) {
13871398 FastElementsAccessorSubclass::MoveElements (
1388- heap, backing_store, start + add_count, start + delete_count,
1389- (length - delete_count - start), 0 , 0 );
1399+ isolate, receiver, backing_store, start + add_count,
1400+ start + delete_count, (length - delete_count - start), 0 , 0 );
1401+ // MoveElements updates the backing_store in-place.
13901402 return backing_store;
13911403 }
13921404 // New backing storage is needed.
@@ -1407,20 +1419,19 @@ class FastElementsAccessor
14071419 static Handle<Object> RemoveElement (Handle<JSArray> receiver,
14081420 Handle<FixedArrayBase> backing_store,
14091421 Where remove_position) {
1422+ Isolate* isolate = receiver->GetIsolate ();
14101423 uint32_t length =
14111424 static_cast <uint32_t >(Smi::cast (receiver->length ())->value ());
1412- Isolate* isolate = receiver->GetIsolate ();
14131425 DCHECK (length > 0 );
14141426 int new_length = length - 1 ;
14151427 int remove_index = remove_position == AT_START ? 0 : new_length;
14161428 Handle<Object> result =
14171429 FastElementsAccessorSubclass::GetImpl (backing_store, remove_index);
14181430 if (remove_position == AT_START) {
1419- Heap* heap = isolate->heap ();
1420- FastElementsAccessorSubclass::MoveElements (heap, backing_store, 0 , 1 ,
1421- new_length, 0 , 0 );
1431+ FastElementsAccessorSubclass::MoveElements (
1432+ isolate, receiver, backing_store, 0 , 1 , new_length, 0 , 0 );
14221433 }
1423- FastElementsAccessorSubclass::SetLengthImpl (receiver, new_length,
1434+ FastElementsAccessorSubclass::SetLengthImpl (isolate, receiver, new_length,
14241435 backing_store);
14251436
14261437 if (IsHoleyElementsKind (KindTraits::Kind) && result->IsTheHole ()) {
@@ -1454,8 +1465,8 @@ class FastElementsAccessor
14541465 // If the backing store has enough capacity and we add elements to the
14551466 // start we have to shift the existing objects.
14561467 Isolate* isolate = receiver->GetIsolate ();
1457- FastElementsAccessorSubclass::MoveElements (isolate-> heap (), backing_store,
1458- add_size, 0 , length, 0 , 0 );
1468+ FastElementsAccessorSubclass::MoveElements (
1469+ isolate, receiver, backing_store, add_size, 0 , length, 0 , 0 );
14591470 }
14601471
14611472 int insertion_index = remove_position == AT_START ? 0 : length;
@@ -1508,11 +1519,22 @@ class FastSmiOrObjectElementsAccessor
15081519 return backing_store->get (index);
15091520 }
15101521
1511- static void MoveElements (Heap* heap, Handle<FixedArrayBase> backing_store,
1512- int dst_index, int src_index, int len,
1513- int hole_start, int hole_end) {
1522+ static void MoveElements (Isolate* isolate, Handle<JSArray> receiver,
1523+ Handle<FixedArrayBase> backing_store, int dst_index,
1524+ int src_index, int len, int hole_start,
1525+ int hole_end) {
1526+ Heap* heap = isolate->heap ();
15141527 Handle<FixedArray> dst_elms = Handle<FixedArray>::cast (backing_store);
1515- if (len != 0 ) {
1528+ if (heap->CanMoveObjectStart (*dst_elms) && dst_index == 0 ) {
1529+ // Update all the copies of this backing_store handle.
1530+ *dst_elms.location () =
1531+ FixedArray::cast (heap->LeftTrimFixedArray (*dst_elms, src_index));
1532+ receiver->set_elements (*dst_elms);
1533+ // Adjust the hole offset as the array has been shrunk.
1534+ hole_end -= src_index;
1535+ DCHECK_LE (hole_start, backing_store->length ());
1536+ DCHECK_LE (hole_end, backing_store->length ());
1537+ } else if (len != 0 ) {
15161538 DisallowHeapAllocation no_gc;
15171539 heap->MoveElements (*dst_elms, dst_index, src_index, len);
15181540 }
@@ -1631,12 +1653,23 @@ class FastDoubleElementsAccessor
16311653 FixedDoubleArray::cast (backing_store)->set (entry, value->Number ());
16321654 }
16331655
1634- static void MoveElements (Heap* heap, Handle<FixedArrayBase> backing_store,
1635- int dst_index, int src_index, int len,
1636- int hole_start, int hole_end) {
1656+ static void MoveElements (Isolate* isolate, Handle<JSArray> receiver,
1657+ Handle<FixedArrayBase> backing_store, int dst_index,
1658+ int src_index, int len, int hole_start,
1659+ int hole_end) {
1660+ Heap* heap = isolate->heap ();
16371661 Handle<FixedDoubleArray> dst_elms =
16381662 Handle<FixedDoubleArray>::cast (backing_store);
1639- if (len != 0 ) {
1663+ if (heap->CanMoveObjectStart (*dst_elms) && dst_index == 0 ) {
1664+ // Update all the copies of this backing_store handle.
1665+ *dst_elms.location () = FixedDoubleArray::cast (
1666+ heap->LeftTrimFixedArray (*dst_elms, src_index));
1667+ receiver->set_elements (*dst_elms);
1668+ // Adjust the hole offset as the array has been shrunk.
1669+ hole_end -= src_index;
1670+ DCHECK_LE (hole_start, backing_store->length ());
1671+ DCHECK_LE (hole_end, backing_store->length ());
1672+ } else if (len != 0 ) {
16401673 MemMove (dst_elms->data_start () + dst_index,
16411674 dst_elms->data_start () + src_index, len * kDoubleSize );
16421675 }
@@ -1742,7 +1775,8 @@ class TypedElementsAccessor
17421775 return PropertyDetails (DONT_DELETE, DATA, 0 , PropertyCellType::kNoCell );
17431776 }
17441777
1745- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
1778+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
1779+ uint32_t length,
17461780 Handle<FixedArrayBase> backing_store) {
17471781 // External arrays do not support changing their length.
17481782 UNREACHABLE ();
@@ -1856,7 +1890,8 @@ class SloppyArgumentsElementsAccessor
18561890 }
18571891 }
18581892
1859- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
1893+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
1894+ uint32_t length,
18601895 Handle<FixedArrayBase> parameter_map) {
18611896 // Sloppy arguments objects are not arrays.
18621897 UNREACHABLE ();
0 commit comments