@@ -691,11 +691,12 @@ class ElementsAccessorBase : public ElementsAccessor {
691
691
}
692
692
693
693
virtual void SetLength (Handle<JSArray> array, uint32_t length) final {
694
- ElementsAccessorSubclass::SetLengthImpl (array, length,
694
+ ElementsAccessorSubclass::SetLengthImpl (array-> GetIsolate (), array , length,
695
695
handle (array->elements ()));
696
696
}
697
697
698
- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
698
+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
699
+ uint32_t length,
699
700
Handle<FixedArrayBase> backing_store) {
700
701
DCHECK (!array->SetLengthWouldNormalize (length));
701
702
DCHECK (IsFastElementsKind (array->GetElementsKind ()));
@@ -712,6 +713,7 @@ class ElementsAccessorBase : public ElementsAccessor {
712
713
713
714
// Check whether the backing store should be shrunk.
714
715
uint32_t capacity = backing_store->length ();
716
+ old_length = Min (old_length, capacity);
715
717
if (length == 0 ) {
716
718
array->initialize_elements ();
717
719
} else if (length <= capacity) {
@@ -720,7 +722,7 @@ class ElementsAccessorBase : public ElementsAccessor {
720
722
}
721
723
if (2 * length <= capacity) {
722
724
// 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>(
724
726
*backing_store, capacity - length);
725
727
} else {
726
728
// Otherwise, fill the unused tail with holes.
@@ -954,11 +956,11 @@ class DictionaryElementsAccessor
954
956
: ElementsAccessorBase<DictionaryElementsAccessor,
955
957
ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
956
958
957
- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
959
+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
960
+ uint32_t length,
958
961
Handle<FixedArrayBase> backing_store) {
959
962
Handle<SeededNumberDictionary> dict =
960
963
Handle<SeededNumberDictionary>::cast (backing_store);
961
- Isolate* isolate = array->GetIsolate ();
962
964
int capacity = dict->Capacity ();
963
965
uint32_t old_length = 0 ;
964
966
CHECK (array->length ()->ToArrayLength (&old_length));
@@ -1181,13 +1183,18 @@ class FastElementsAccessor
1181
1183
}
1182
1184
int num_used = 0 ;
1183
1185
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
+ }
1190
1196
}
1197
+ JSObject::NormalizeElements (obj);
1191
1198
}
1192
1199
}
1193
1200
@@ -1293,9 +1300,10 @@ class FastElementsAccessor
1293
1300
receiver, backing_store, args, unshift_size, AT_START);
1294
1301
}
1295
1302
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) {
1299
1307
UNREACHABLE ();
1300
1308
}
1301
1309
@@ -1344,13 +1352,13 @@ class FastElementsAccessor
1344
1352
1345
1353
// Delete and move elements to make space for add_count new elements.
1346
1354
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);
1350
1358
} else if (add_count > delete_count) {
1351
1359
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);
1354
1362
}
1355
1363
1356
1364
// Copy over the arguments.
@@ -1364,29 +1372,33 @@ class FastElementsAccessor
1364
1372
}
1365
1373
1366
1374
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,
1368
1378
uint32_t start, uint32_t delete_count,
1369
1379
uint32_t add_count, uint32_t len,
1370
1380
uint32_t new_length) {
1371
1381
const int move_left_count = len - delete_count - start;
1372
1382
const int move_left_dst_index = start + add_count;
1373
1383
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);
1376
1386
}
1377
1387
1378
-
1388
+ // SpliceGrowStep might modify the backing_store.
1379
1389
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) {
1383
1394
// Check we do not overflow the new_length.
1384
1395
DCHECK ((add_count - delete_count) <= (Smi::kMaxValue - length));
1385
1396
// Check if backing_store is big enough.
1386
1397
if (new_length <= static_cast <uint32_t >(backing_store->length ())) {
1387
1398
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.
1390
1402
return backing_store;
1391
1403
}
1392
1404
// New backing storage is needed.
@@ -1407,20 +1419,19 @@ class FastElementsAccessor
1407
1419
static Handle<Object> RemoveElement (Handle<JSArray> receiver,
1408
1420
Handle<FixedArrayBase> backing_store,
1409
1421
Where remove_position) {
1422
+ Isolate* isolate = receiver->GetIsolate ();
1410
1423
uint32_t length =
1411
1424
static_cast <uint32_t >(Smi::cast (receiver->length ())->value ());
1412
- Isolate* isolate = receiver->GetIsolate ();
1413
1425
DCHECK (length > 0 );
1414
1426
int new_length = length - 1 ;
1415
1427
int remove_index = remove_position == AT_START ? 0 : new_length;
1416
1428
Handle<Object> result =
1417
1429
FastElementsAccessorSubclass::GetImpl (backing_store, remove_index);
1418
1430
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 );
1422
1433
}
1423
- FastElementsAccessorSubclass::SetLengthImpl (receiver, new_length,
1434
+ FastElementsAccessorSubclass::SetLengthImpl (isolate, receiver, new_length,
1424
1435
backing_store);
1425
1436
1426
1437
if (IsHoleyElementsKind (KindTraits::Kind) && result->IsTheHole ()) {
@@ -1454,8 +1465,8 @@ class FastElementsAccessor
1454
1465
// If the backing store has enough capacity and we add elements to the
1455
1466
// start we have to shift the existing objects.
1456
1467
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 );
1459
1470
}
1460
1471
1461
1472
int insertion_index = remove_position == AT_START ? 0 : length;
@@ -1508,11 +1519,22 @@ class FastSmiOrObjectElementsAccessor
1508
1519
return backing_store->get (index);
1509
1520
}
1510
1521
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 ();
1514
1527
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 ) {
1516
1538
DisallowHeapAllocation no_gc;
1517
1539
heap->MoveElements (*dst_elms, dst_index, src_index, len);
1518
1540
}
@@ -1631,12 +1653,23 @@ class FastDoubleElementsAccessor
1631
1653
FixedDoubleArray::cast (backing_store)->set (entry, value->Number ());
1632
1654
}
1633
1655
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 ();
1637
1661
Handle<FixedDoubleArray> dst_elms =
1638
1662
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 ) {
1640
1673
MemMove (dst_elms->data_start () + dst_index,
1641
1674
dst_elms->data_start () + src_index, len * kDoubleSize );
1642
1675
}
@@ -1742,7 +1775,8 @@ class TypedElementsAccessor
1742
1775
return PropertyDetails (DONT_DELETE, DATA, 0 , PropertyCellType::kNoCell );
1743
1776
}
1744
1777
1745
- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
1778
+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
1779
+ uint32_t length,
1746
1780
Handle<FixedArrayBase> backing_store) {
1747
1781
// External arrays do not support changing their length.
1748
1782
UNREACHABLE ();
@@ -1856,7 +1890,8 @@ class SloppyArgumentsElementsAccessor
1856
1890
}
1857
1891
}
1858
1892
1859
- static void SetLengthImpl (Handle<JSArray> array, uint32_t length,
1893
+ static void SetLengthImpl (Isolate* isolate, Handle<JSArray> array,
1894
+ uint32_t length,
1860
1895
Handle<FixedArrayBase> parameter_map) {
1861
1896
// Sloppy arguments objects are not arrays.
1862
1897
UNREACHABLE ();
0 commit comments