Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2869)

Side by Side Diff: src/elements.cc

Issue 1293683005: Adding ElementsAccessor::Splice (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: simpliftying splice arg copying Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/elements.h ('k') | test/mjsunit/array-natives-elements.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/elements.h" 5 #include "src/elements.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions.h" 8 #include "src/conversions.h"
9 #include "src/factory.h" 9 #include "src/factory.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 return false; 108 return false;
109 } 109 }
110 110
111 111
112 MUST_USE_RESULT 112 MUST_USE_RESULT
113 static MaybeHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) { 113 static MaybeHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) {
114 THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength), 114 THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength),
115 Object); 115 Object);
116 } 116 }
117 117
118
119 static void CopyObjectToObjectElements(FixedArrayBase* from_base, 118 static void CopyObjectToObjectElements(FixedArrayBase* from_base,
120 ElementsKind from_kind, 119 ElementsKind from_kind,
121 uint32_t from_start, 120 uint32_t from_start,
122 FixedArrayBase* to_base, 121 FixedArrayBase* to_base,
123 ElementsKind to_kind, uint32_t to_start, 122 ElementsKind to_kind, uint32_t to_start,
124 int raw_copy_size) { 123 int raw_copy_size) {
125 DCHECK(to_base->map() != 124 DCHECK(to_base->map() !=
126 from_base->GetIsolate()->heap()->fixed_cow_array_map()); 125 from_base->GetIsolate()->heap()->fixed_cow_array_map());
127 DisallowHeapAllocation no_allocation; 126 DisallowHeapAllocation no_allocation;
128 int copy_size = raw_copy_size; 127 int copy_size = raw_copy_size;
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 push_size, direction); 578 push_size, direction);
580 } 579 }
581 580
582 static uint32_t PushImpl(Handle<JSArray> receiver, 581 static uint32_t PushImpl(Handle<JSArray> receiver,
583 Handle<FixedArrayBase> elms_obj, Object** objects, 582 Handle<FixedArrayBase> elms_obj, Object** objects,
584 uint32_t push_size, int direction) { 583 uint32_t push_size, int direction) {
585 UNREACHABLE(); 584 UNREACHABLE();
586 return 0; 585 return 0;
587 } 586 }
588 587
588 virtual Handle<JSArray> Splice(Handle<JSArray> receiver,
589 Handle<FixedArrayBase> backing_store,
590 uint32_t start, uint32_t delete_count,
591 Arguments args, uint32_t add_count) {
592 return ElementsAccessorSubclass::SpliceImpl(receiver, backing_store, start,
593 delete_count, args, add_count);
594 }
595
596 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver,
597 Handle<FixedArrayBase> backing_store,
598 uint32_t start, uint32_t delete_count,
599 Arguments args, uint32_t add_count) {
600 UNREACHABLE();
601 return Handle<JSArray>();
602 }
603
604
589 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { 605 virtual void SetLength(Handle<JSArray> array, uint32_t length) final {
590 ElementsAccessorSubclass::SetLengthImpl(array, length, 606 ElementsAccessorSubclass::SetLengthImpl(array, length,
591 handle(array->elements())); 607 handle(array->elements()));
592 } 608 }
593 609
594 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, 610 static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
595 Handle<FixedArrayBase> backing_store); 611 Handle<FixedArrayBase> backing_store);
596 612
597 static Handle<FixedArrayBase> ConvertElementsWithCapacity( 613 static Handle<FixedArrayBase> ConvertElementsWithCapacity(
598 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, 614 Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
599 ElementsKind from_kind, uint32_t capacity) { 615 ElementsKind from_kind, uint32_t capacity) {
616 return ConvertElementsWithCapacity(
617 object, old_elements, from_kind, capacity,
618 ElementsAccessor::kCopyToEndAndInitializeToHole);
619 }
620
621 static Handle<FixedArrayBase> ConvertElementsWithCapacity(
622 Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
623 ElementsKind from_kind, uint32_t capacity, int copy_size) {
600 Isolate* isolate = object->GetIsolate(); 624 Isolate* isolate = object->GetIsolate();
601 Handle<FixedArrayBase> elements; 625 Handle<FixedArrayBase> new_elements;
602 if (IsFastDoubleElementsKind(kind())) { 626 if (IsFastDoubleElementsKind(kind())) {
603 elements = isolate->factory()->NewFixedDoubleArray(capacity); 627 new_elements = isolate->factory()->NewFixedDoubleArray(capacity);
604 } else { 628 } else {
605 elements = isolate->factory()->NewUninitializedFixedArray(capacity); 629 new_elements = isolate->factory()->NewUninitializedFixedArray(capacity);
606 } 630 }
607 631
608 int packed = kPackedSizeNotKnown; 632 int packed_size = kPackedSizeNotKnown;
609 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) { 633 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) {
610 packed = Smi::cast(JSArray::cast(*object)->length())->value(); 634 packed_size = Smi::cast(JSArray::cast(*object)->length())->value();
611 } 635 }
612 636
613 ElementsAccessorSubclass::CopyElementsImpl( 637 ElementsAccessorSubclass::CopyElementsImpl(
614 *old_elements, 0, *elements, from_kind, 0, packed, 638 *old_elements, 0, *new_elements, from_kind, 0, packed_size, copy_size);
615 ElementsAccessor::kCopyToEndAndInitializeToHole); 639
616 return elements; 640 return new_elements;
617 } 641 }
618 642
619 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, 643 static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
620 uint32_t capacity) { 644 uint32_t capacity) {
621 ElementsKind from_kind = object->GetElementsKind(); 645 ElementsKind from_kind = object->GetElementsKind();
622 if (IsFastSmiOrObjectElementsKind(from_kind)) { 646 if (IsFastSmiOrObjectElementsKind(from_kind)) {
623 // Array optimizations rely on the prototype lookups of Array objects 647 // Array optimizations rely on the prototype lookups of Array objects
624 // always returning undefined. If there is a store to the initial 648 // always returning undefined. If there is a store to the initial
625 // prototype object, make sure all of these optimizations are invalidated. 649 // prototype object, make sure all of these optimizations are invalidated.
626 object->GetIsolate()->UpdateArrayProtectorOnSetLength(object); 650 object->GetIsolate()->UpdateArrayProtectorOnSetLength(object);
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 uint32_t new_length = len + push_size; 1196 uint32_t new_length = len + push_size;
1173 Handle<FixedArrayBase> new_elms; 1197 Handle<FixedArrayBase> new_elms;
1174 1198
1175 if (new_length > elms_len) { 1199 if (new_length > elms_len) {
1176 // New backing storage is needed. 1200 // New backing storage is needed.
1177 uint32_t capacity = new_length + (new_length >> 1) + 16; 1201 uint32_t capacity = new_length + (new_length >> 1) + 16;
1178 new_elms = FastElementsAccessorSubclass::ConvertElementsWithCapacity( 1202 new_elms = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
1179 receiver, backing_store, KindTraits::Kind, capacity); 1203 receiver, backing_store, KindTraits::Kind, capacity);
1180 } else { 1204 } else {
1181 // push_size is > 0 and new_length <= elms_len, so backing_store cannot be 1205 // push_size is > 0 and new_length <= elms_len, so backing_store cannot be
1182 // the 1206 // the empty_fixed_array.
1183 // empty_fixed_array.
1184 new_elms = backing_store; 1207 new_elms = backing_store;
1185 } 1208 }
1186 1209
1187 // Add the provided values. 1210 // Add the provided values.
1188 DisallowHeapAllocation no_gc; 1211 DisallowHeapAllocation no_gc;
1189 DCHECK(direction == ElementsAccessor::kDirectionForward || 1212 DCHECK(direction == ElementsAccessor::kDirectionForward ||
1190 direction == ElementsAccessor::kDirectionReverse); 1213 direction == ElementsAccessor::kDirectionReverse);
1191 STATIC_ASSERT(ElementsAccessor::kDirectionForward == 1); 1214 STATIC_ASSERT(ElementsAccessor::kDirectionForward == 1);
1192 STATIC_ASSERT(ElementsAccessor::kDirectionReverse == -1); 1215 STATIC_ASSERT(ElementsAccessor::kDirectionReverse == -1);
1193 for (uint32_t index = 0; index < push_size; index++) { 1216 for (uint32_t index = 0; index < push_size; index++) {
1194 int offset = direction * index; 1217 int offset = direction * index;
1195 Object* object = objects[offset]; 1218 Object* object = objects[offset];
1196 FastElementsAccessorSubclass::SetImpl(*new_elms, index + len, object); 1219 FastElementsAccessorSubclass::SetImpl(*new_elms, index + len, object);
1197 } 1220 }
1198 if (!new_elms.is_identical_to(backing_store)) { 1221 if (!new_elms.is_identical_to(backing_store)) {
1199 receiver->set_elements(*new_elms); 1222 receiver->set_elements(*new_elms);
1200 } 1223 }
1201 DCHECK(*new_elms == receiver->elements()); 1224 DCHECK(*new_elms == receiver->elements());
1202 // Set the length. 1225 // Set the length.
1203 receiver->set_length(Smi::FromInt(new_length)); 1226 receiver->set_length(Smi::FromInt(new_length));
1204 return new_length; 1227 return new_length;
1205 } 1228 }
1229
1230 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1231 int dst_index, int src_index, int len,
1232 int hole_start, int hole_end) {
1233 UNREACHABLE();
1234 }
1235
1236 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver,
1237 Handle<FixedArrayBase> backing_store,
1238 uint32_t start, uint32_t delete_count,
1239 Arguments args, uint32_t add_count) {
1240 Isolate* isolate = receiver->GetIsolate();
1241 Heap* heap = isolate->heap();
1242 const uint32_t len = Smi::cast(receiver->length())->value();
1243 const uint32_t new_length = len - delete_count + add_count;
1244
1245 if (new_length == 0) {
1246 receiver->set_elements(heap->empty_fixed_array());
1247 receiver->set_length(Smi::FromInt(0));
1248 return isolate->factory()->NewJSArrayWithElements(
1249 backing_store, KindTraits::Kind, delete_count);
1250 }
1251
1252 // construct the result array which holds the deleted elements
1253 Handle<JSArray> deleted_elements = isolate->factory()->NewJSArray(
1254 KindTraits::Kind, delete_count, delete_count);
1255 if (delete_count > 0) {
1256 DisallowHeapAllocation no_gc;
1257 FastElementsAccessorSubclass::CopyElementsImpl(
1258 *backing_store, start, deleted_elements->elements(), KindTraits::Kind,
1259 0, kPackedSizeNotKnown, delete_count);
1260 }
1261
1262 // delete and move elements to make space for add_count new elements
1263 bool elms_changed = false;
1264 if (add_count < delete_count) {
1265 elms_changed = SpliceShrinkStep(backing_store, heap, start, delete_count,
1266 add_count, len, new_length);
1267 } else if (add_count > delete_count) {
1268 elms_changed =
1269 SpliceGrowStep(receiver, backing_store, isolate, heap, start,
1270 delete_count, add_count, len, new_length);
1271 }
1272
1273 // Copy new Elements from args
1274 DisallowHeapAllocation no_gc;
1275 for (uint32_t index = start; index < start + add_count; index++) {
1276 Object* arg = args[3 + index - start];
1277 FastElementsAccessorSubclass::SetImpl(*backing_store, index, arg);
1278 }
1279
1280 if (elms_changed) {
1281 receiver->set_elements(*backing_store);
1282 }
1283 receiver->set_length(Smi::FromInt(new_length));
1284 return deleted_elements;
1285 }
1286
1287 private:
1288 static bool SpliceShrinkStep(Handle<FixedArrayBase>& backing_store,
1289 Heap* heap, uint32_t start,
1290 uint32_t delete_count, uint32_t add_count,
1291 uint32_t len, uint32_t new_length) {
1292 const int move_left_count = len - delete_count - start;
1293 const int move_left_dst_index = start + add_count;
1294 const bool left_trim_array = heap->CanMoveObjectStart(*backing_store) &&
1295 (move_left_dst_index < move_left_count);
1296 if (left_trim_array) {
1297 const int delta = delete_count - add_count;
1298 // shift from before the insertion point to the right
1299 FastElementsAccessorSubclass::MoveElements(heap, backing_store, delta, 0,
1300 start, 0, 0);
1301 backing_store = handle(heap->LeftTrimFixedArray(*backing_store, delta));
1302 return true;
1303 } else {
1304 // No left-trim needed or possible (in this case we left-move and store
1305 // the hole)
1306 FastElementsAccessorSubclass::MoveElements(
1307 heap, backing_store, move_left_dst_index, start + delete_count,
1308 move_left_count, new_length, len);
1309 }
1310 return false;
1311 }
1312
1313
1314 static bool SpliceGrowStep(Handle<JSArray> receiver,
1315 Handle<FixedArrayBase>& backing_store,
1316 Isolate* isolate, Heap* heap, uint32_t start,
1317 uint32_t delete_count, uint32_t add_count,
1318 uint32_t len, uint32_t new_length) {
1319 // Currently fixed arrays cannot grow too big, so
1320 // we should never hit this case.
1321 DCHECK((add_count - delete_count) <= (Smi::kMaxValue - len));
1322 // Check if backing_store needs to grow.
1323 if (new_length > static_cast<uint32_t>(backing_store->length())) {
1324 // New backing storage is needed.
1325 int capacity = new_length + (new_length >> 1) + 16;
1326 // partially copy all elements up to start
1327 Handle<FixedArrayBase> new_elms =
1328 FastElementsAccessorSubclass::ConvertElementsWithCapacity(
1329 receiver, backing_store, KindTraits::Kind, capacity, start);
1330 // Copy the trailing elements after start + delete_count
1331 FastElementsAccessorSubclass::CopyElementsImpl(
1332 *backing_store, start + delete_count, *new_elms, KindTraits::Kind,
1333 start + add_count, kPackedSizeNotKnown,
1334 ElementsAccessor::kCopyToEndAndInitializeToHole);
1335
1336 backing_store = new_elms;
1337 return true;
1338 } else {
1339 DisallowHeapAllocation no_gc;
1340 FastElementsAccessorSubclass::MoveElements(
1341 heap, backing_store, start + add_count, start + delete_count,
1342 (len - delete_count - start), 0, 0);
1343 }
1344 return false;
1345 }
1206 }; 1346 };
1207 1347
1208 1348
1209 template<typename FastElementsAccessorSubclass, 1349 template<typename FastElementsAccessorSubclass,
1210 typename KindTraits> 1350 typename KindTraits>
1211 class FastSmiOrObjectElementsAccessor 1351 class FastSmiOrObjectElementsAccessor
1212 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { 1352 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1213 public: 1353 public:
1214 explicit FastSmiOrObjectElementsAccessor(const char* name) 1354 explicit FastSmiOrObjectElementsAccessor(const char* name)
1215 : FastElementsAccessor<FastElementsAccessorSubclass, 1355 : FastElementsAccessor<FastElementsAccessorSubclass,
1216 KindTraits>(name) {} 1356 KindTraits>(name) {}
1217 1357
1218 static Object* GetRaw(FixedArray* backing_store, uint32_t entry) { 1358 static Object* GetRaw(FixedArray* backing_store, uint32_t entry) {
1219 uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl( 1359 uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl(
1220 backing_store, entry); 1360 backing_store, entry);
1221 return backing_store->get(index); 1361 return backing_store->get(index);
1222 } 1362 }
1223 1363
1364 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1365 int dst_index, int src_index, int len,
1366 int hole_start, int hole_end) {
1367 Handle<FixedArray> dst_elms = Handle<FixedArray>::cast(backing_store);
1368 if (len != 0) {
1369 DisallowHeapAllocation no_gc;
1370 heap->MoveElements(*dst_elms, dst_index, src_index, len);
1371 }
1372 if (hole_start != hole_end) {
1373 dst_elms->FillWithHoles(hole_start, hole_end);
1374 }
1375 }
1376
1224 // NOTE: this method violates the handlified function signature convention: 1377 // NOTE: this method violates the handlified function signature convention:
1225 // raw pointer parameters in the function that allocates. 1378 // raw pointer parameters in the function that allocates.
1226 // See ElementsAccessor::CopyElements() for details. 1379 // See ElementsAccessor::CopyElements() for details.
1227 // This method could actually allocate if copying from double elements to 1380 // This method could actually allocate if copying from double elements to
1228 // object elements. 1381 // object elements.
1229 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 1382 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1230 FixedArrayBase* to, ElementsKind from_kind, 1383 FixedArrayBase* to, ElementsKind from_kind,
1231 uint32_t to_start, int packed_size, 1384 uint32_t to_start, int packed_size,
1232 int copy_size) { 1385 int copy_size) {
1233 DisallowHeapAllocation no_gc; 1386 DisallowHeapAllocation no_gc;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 1467
1315 template<typename FastElementsAccessorSubclass, 1468 template<typename FastElementsAccessorSubclass,
1316 typename KindTraits> 1469 typename KindTraits>
1317 class FastDoubleElementsAccessor 1470 class FastDoubleElementsAccessor
1318 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { 1471 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1319 public: 1472 public:
1320 explicit FastDoubleElementsAccessor(const char* name) 1473 explicit FastDoubleElementsAccessor(const char* name)
1321 : FastElementsAccessor<FastElementsAccessorSubclass, 1474 : FastElementsAccessor<FastElementsAccessorSubclass,
1322 KindTraits>(name) {} 1475 KindTraits>(name) {}
1323 1476
1477 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1478 int dst_index, int src_index, int len,
1479 int hole_start, int hole_end) {
1480 Handle<FixedDoubleArray> dst_elms =
1481 Handle<FixedDoubleArray>::cast(backing_store);
1482 if (len != 0) {
1483 MemMove(dst_elms->data_start() + dst_index,
1484 dst_elms->data_start() + src_index, len * kDoubleSize);
1485 }
1486 if (hole_start != hole_end) {
1487 dst_elms->FillWithHoles(hole_start, hole_end);
1488 }
1489 }
1490
1324 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 1491 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1325 FixedArrayBase* to, ElementsKind from_kind, 1492 FixedArrayBase* to, ElementsKind from_kind,
1326 uint32_t to_start, int packed_size, 1493 uint32_t to_start, int packed_size,
1327 int copy_size) { 1494 int copy_size) {
1328 DisallowHeapAllocation no_allocation; 1495 DisallowHeapAllocation no_allocation;
1329 switch (from_kind) { 1496 switch (from_kind) {
1330 case FAST_SMI_ELEMENTS: 1497 case FAST_SMI_ELEMENTS:
1331 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, 1498 CopyPackedSmiToDoubleElements(from, from_start, to, to_start,
1332 packed_size, copy_size); 1499 packed_size, copy_size);
1333 break; 1500 break;
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
1974 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; 2141 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
1975 ELEMENTS_LIST(ACCESSOR_DELETE) 2142 ELEMENTS_LIST(ACCESSOR_DELETE)
1976 #undef ACCESSOR_DELETE 2143 #undef ACCESSOR_DELETE
1977 elements_accessors_ = NULL; 2144 elements_accessors_ = NULL;
1978 } 2145 }
1979 2146
1980 2147
1981 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; 2148 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL;
1982 } // namespace internal 2149 } // namespace internal
1983 } // namespace v8 2150 } // namespace v8
OLDNEW
« no previous file with comments | « src/elements.h ('k') | test/mjsunit/array-natives-elements.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698