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

Side by Side Diff: src/elements.cc

Issue 1315823004: Revert of Moving ArraySplice Builtin to ElementsAccessor (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 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/v8.h" 5 #include "src/v8.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/elements.h" 9 #include "src/elements.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
118 static void CopyObjectToObjectElements(FixedArrayBase* from_base, 119 static void CopyObjectToObjectElements(FixedArrayBase* from_base,
119 ElementsKind from_kind, 120 ElementsKind from_kind,
120 uint32_t from_start, 121 uint32_t from_start,
121 FixedArrayBase* to_base, 122 FixedArrayBase* to_base,
122 ElementsKind to_kind, uint32_t to_start, 123 ElementsKind to_kind, uint32_t to_start,
123 int raw_copy_size) { 124 int raw_copy_size) {
124 DCHECK(to_base->map() != 125 DCHECK(to_base->map() !=
125 from_base->GetIsolate()->heap()->fixed_cow_array_map()); 126 from_base->GetIsolate()->heap()->fixed_cow_array_map());
126 DisallowHeapAllocation no_allocation; 127 DisallowHeapAllocation no_allocation;
127 int copy_size = raw_copy_size; 128 int copy_size = raw_copy_size;
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 push_size, direction); 579 push_size, direction);
579 } 580 }
580 581
581 static uint32_t PushImpl(Handle<JSArray> receiver, 582 static uint32_t PushImpl(Handle<JSArray> receiver,
582 Handle<FixedArrayBase> elms_obj, Object** objects, 583 Handle<FixedArrayBase> elms_obj, Object** objects,
583 uint32_t push_size, int direction) { 584 uint32_t push_size, int direction) {
584 UNREACHABLE(); 585 UNREACHABLE();
585 return 0; 586 return 0;
586 } 587 }
587 588
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
605 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { 589 virtual void SetLength(Handle<JSArray> array, uint32_t length) final {
606 ElementsAccessorSubclass::SetLengthImpl(array, length, 590 ElementsAccessorSubclass::SetLengthImpl(array, length,
607 handle(array->elements())); 591 handle(array->elements()));
608 } 592 }
609 593
610 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, 594 static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
611 Handle<FixedArrayBase> backing_store); 595 Handle<FixedArrayBase> backing_store);
612 596
613 static Handle<FixedArrayBase> ConvertElementsWithCapacity( 597 static Handle<FixedArrayBase> ConvertElementsWithCapacity(
614 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, 598 Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
615 ElementsKind from_kind, uint32_t capacity) { 599 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) {
624 Isolate* isolate = object->GetIsolate(); 600 Isolate* isolate = object->GetIsolate();
625 Handle<FixedArrayBase> new_elements; 601 Handle<FixedArrayBase> elements;
626 if (IsFastDoubleElementsKind(kind())) { 602 if (IsFastDoubleElementsKind(kind())) {
627 new_elements = isolate->factory()->NewFixedDoubleArray(capacity); 603 elements = isolate->factory()->NewFixedDoubleArray(capacity);
628 } else { 604 } else {
629 new_elements = isolate->factory()->NewUninitializedFixedArray(capacity); 605 elements = isolate->factory()->NewUninitializedFixedArray(capacity);
630 } 606 }
631 607
632 int packed_size = kPackedSizeNotKnown; 608 int packed = kPackedSizeNotKnown;
633 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) { 609 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) {
634 packed_size = Smi::cast(JSArray::cast(*object)->length())->value(); 610 packed = Smi::cast(JSArray::cast(*object)->length())->value();
635 } 611 }
636 612
637 ElementsAccessorSubclass::CopyElementsImpl( 613 ElementsAccessorSubclass::CopyElementsImpl(
638 *old_elements, 0, *new_elements, from_kind, 0, packed_size, copy_size); 614 *old_elements, 0, *elements, from_kind, 0, packed,
639 615 ElementsAccessor::kCopyToEndAndInitializeToHole);
640 return new_elements; 616 return elements;
641 } 617 }
642 618
643 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, 619 static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
644 uint32_t capacity) { 620 uint32_t capacity) {
645 ElementsKind from_kind = object->GetElementsKind(); 621 ElementsKind from_kind = object->GetElementsKind();
646 if (IsFastSmiOrObjectElementsKind(from_kind)) { 622 if (IsFastSmiOrObjectElementsKind(from_kind)) {
647 // Array optimizations rely on the prototype lookups of Array objects 623 // Array optimizations rely on the prototype lookups of Array objects
648 // always returning undefined. If there is a store to the initial 624 // always returning undefined. If there is a store to the initial
649 // prototype object, make sure all of these optimizations are invalidated. 625 // prototype object, make sure all of these optimizations are invalidated.
650 object->GetIsolate()->UpdateArrayProtectorOnSetLength(object); 626 object->GetIsolate()->UpdateArrayProtectorOnSetLength(object);
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 uint32_t new_length = len + push_size; 1172 uint32_t new_length = len + push_size;
1197 Handle<FixedArrayBase> new_elms; 1173 Handle<FixedArrayBase> new_elms;
1198 1174
1199 if (new_length > elms_len) { 1175 if (new_length > elms_len) {
1200 // New backing storage is needed. 1176 // New backing storage is needed.
1201 uint32_t capacity = new_length + (new_length >> 1) + 16; 1177 uint32_t capacity = new_length + (new_length >> 1) + 16;
1202 new_elms = FastElementsAccessorSubclass::ConvertElementsWithCapacity( 1178 new_elms = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
1203 receiver, backing_store, KindTraits::Kind, capacity); 1179 receiver, backing_store, KindTraits::Kind, capacity);
1204 } else { 1180 } else {
1205 // push_size is > 0 and new_length <= elms_len, so backing_store cannot be 1181 // push_size is > 0 and new_length <= elms_len, so backing_store cannot be
1206 // the empty_fixed_array. 1182 // the
1183 // empty_fixed_array.
1207 new_elms = backing_store; 1184 new_elms = backing_store;
1208 } 1185 }
1209 1186
1210 // Add the provided values. 1187 // Add the provided values.
1211 DisallowHeapAllocation no_gc; 1188 DisallowHeapAllocation no_gc;
1212 DCHECK(direction == ElementsAccessor::kDirectionForward || 1189 DCHECK(direction == ElementsAccessor::kDirectionForward ||
1213 direction == ElementsAccessor::kDirectionReverse); 1190 direction == ElementsAccessor::kDirectionReverse);
1214 STATIC_ASSERT(ElementsAccessor::kDirectionForward == 1); 1191 STATIC_ASSERT(ElementsAccessor::kDirectionForward == 1);
1215 STATIC_ASSERT(ElementsAccessor::kDirectionReverse == -1); 1192 STATIC_ASSERT(ElementsAccessor::kDirectionReverse == -1);
1216 for (uint32_t index = 0; index < push_size; index++) { 1193 for (uint32_t index = 0; index < push_size; index++) {
1217 int offset = direction * index; 1194 int offset = direction * index;
1218 Object* object = objects[offset]; 1195 Object* object = objects[offset];
1219 FastElementsAccessorSubclass::SetImpl(*new_elms, index + len, object); 1196 FastElementsAccessorSubclass::SetImpl(*new_elms, index + len, object);
1220 } 1197 }
1221 if (!new_elms.is_identical_to(backing_store)) { 1198 if (!new_elms.is_identical_to(backing_store)) {
1222 receiver->set_elements(*new_elms); 1199 receiver->set_elements(*new_elms);
1223 } 1200 }
1224 DCHECK(*new_elms == receiver->elements()); 1201 DCHECK(*new_elms == receiver->elements());
1225 // Set the length. 1202 // Set the length.
1226 receiver->set_length(Smi::FromInt(new_length)); 1203 receiver->set_length(Smi::FromInt(new_length));
1227 return new_length; 1204 return new_length;
1228 } 1205 }
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 if (IsFastDoubleElementsKind(KindTraits::Kind)) {
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 } else {
1280 // FastSmiOrObjectElementsKind
1281 Handle<FixedArray> elms = Handle<FixedArray>::cast(backing_store);
1282 DisallowHeapAllocation no_gc;
1283 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
1284 for (uint32_t index = start; index < start + add_count; index++) {
1285 elms->set(index, args[3 + index - start], mode);
1286 }
1287 }
1288
1289 if (elms_changed) {
1290 receiver->set_elements(*backing_store);
1291 }
1292 receiver->set_length(Smi::FromInt(new_length));
1293 return deleted_elements;
1294 }
1295
1296 private:
1297 static bool SpliceShrinkStep(Handle<FixedArrayBase>& backing_store,
1298 Heap* heap, uint32_t start,
1299 uint32_t delete_count, uint32_t add_count,
1300 uint32_t len, uint32_t new_length) {
1301 const int move_left_count = len - delete_count - start;
1302 const int move_left_dst_index = start + add_count;
1303 const bool left_trim_array = heap->CanMoveObjectStart(*backing_store) &&
1304 (move_left_dst_index < move_left_count);
1305 if (left_trim_array) {
1306 const int delta = delete_count - add_count;
1307 // shift from before the insertion point to the right
1308 FastElementsAccessorSubclass::MoveElements(heap, backing_store, delta, 0,
1309 start, 0, 0);
1310 backing_store = handle(heap->LeftTrimFixedArray(*backing_store, delta));
1311 return true;
1312 } else {
1313 // No left-trim needed or possible (in this case we left-move and store
1314 // the hole)
1315 FastElementsAccessorSubclass::MoveElements(
1316 heap, backing_store, move_left_dst_index, start + delete_count,
1317 move_left_count, new_length, len);
1318 }
1319 return false;
1320 }
1321
1322
1323 static bool SpliceGrowStep(Handle<JSArray> receiver,
1324 Handle<FixedArrayBase>& backing_store,
1325 Isolate* isolate, Heap* heap, uint32_t start,
1326 uint32_t delete_count, uint32_t add_count,
1327 uint32_t len, uint32_t new_length) {
1328 // Currently fixed arrays cannot grow too big, so
1329 // we should never hit this case.
1330 DCHECK((add_count - delete_count) <= (Smi::kMaxValue - len));
1331 // Check if backing_store needs to grow.
1332 if (new_length > static_cast<uint32_t>(backing_store->length())) {
1333 // New backing storage is needed.
1334 int capacity = new_length + (new_length >> 1) + 16;
1335 // partially copy all elements up to start
1336 Handle<FixedArrayBase> new_elms =
1337 FastElementsAccessorSubclass::ConvertElementsWithCapacity(
1338 receiver, backing_store, KindTraits::Kind, capacity, start);
1339 // Copy the trailing elements after start + delete_count
1340 FastElementsAccessorSubclass::CopyElementsImpl(
1341 *backing_store, start + delete_count, *new_elms, KindTraits::Kind,
1342 start + add_count, kPackedSizeNotKnown,
1343 ElementsAccessor::kCopyToEndAndInitializeToHole);
1344
1345 backing_store = new_elms;
1346 return true;
1347 } else {
1348 DisallowHeapAllocation no_gc;
1349 FastElementsAccessorSubclass::MoveElements(
1350 heap, backing_store, start + add_count, start + delete_count,
1351 (len - delete_count - start), 0, 0);
1352 }
1353 return false;
1354 }
1355 }; 1206 };
1356 1207
1357 1208
1358 template<typename FastElementsAccessorSubclass, 1209 template<typename FastElementsAccessorSubclass,
1359 typename KindTraits> 1210 typename KindTraits>
1360 class FastSmiOrObjectElementsAccessor 1211 class FastSmiOrObjectElementsAccessor
1361 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { 1212 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1362 public: 1213 public:
1363 explicit FastSmiOrObjectElementsAccessor(const char* name) 1214 explicit FastSmiOrObjectElementsAccessor(const char* name)
1364 : FastElementsAccessor<FastElementsAccessorSubclass, 1215 : FastElementsAccessor<FastElementsAccessorSubclass,
1365 KindTraits>(name) {} 1216 KindTraits>(name) {}
1366 1217
1367 static Object* GetRaw(FixedArray* backing_store, uint32_t entry) { 1218 static Object* GetRaw(FixedArray* backing_store, uint32_t entry) {
1368 uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl( 1219 uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl(
1369 backing_store, entry); 1220 backing_store, entry);
1370 return backing_store->get(index); 1221 return backing_store->get(index);
1371 } 1222 }
1372 1223
1373 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1374 int dst_index, int src_index, int len,
1375 int hole_start, int hole_end) {
1376 if (len == 0) return;
1377 Handle<FixedArray> dst_elms = Handle<FixedArray>::cast(backing_store);
1378 DisallowHeapAllocation no_gc;
1379 heap->MoveElements(*dst_elms, dst_index, src_index, len);
1380 if (hole_start != hole_end) {
1381 dst_elms->FillWithHoles(hole_start, hole_end);
1382 }
1383 }
1384
1385 // NOTE: this method violates the handlified function signature convention: 1224 // NOTE: this method violates the handlified function signature convention:
1386 // raw pointer parameters in the function that allocates. 1225 // raw pointer parameters in the function that allocates.
1387 // See ElementsAccessor::CopyElements() for details. 1226 // See ElementsAccessor::CopyElements() for details.
1388 // This method could actually allocate if copying from double elements to 1227 // This method could actually allocate if copying from double elements to
1389 // object elements. 1228 // object elements.
1390 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 1229 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1391 FixedArrayBase* to, ElementsKind from_kind, 1230 FixedArrayBase* to, ElementsKind from_kind,
1392 uint32_t to_start, int packed_size, 1231 uint32_t to_start, int packed_size,
1393 int copy_size) { 1232 int copy_size) {
1394 DisallowHeapAllocation no_gc; 1233 DisallowHeapAllocation no_gc;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 1314
1476 template<typename FastElementsAccessorSubclass, 1315 template<typename FastElementsAccessorSubclass,
1477 typename KindTraits> 1316 typename KindTraits>
1478 class FastDoubleElementsAccessor 1317 class FastDoubleElementsAccessor
1479 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { 1318 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
1480 public: 1319 public:
1481 explicit FastDoubleElementsAccessor(const char* name) 1320 explicit FastDoubleElementsAccessor(const char* name)
1482 : FastElementsAccessor<FastElementsAccessorSubclass, 1321 : FastElementsAccessor<FastElementsAccessorSubclass,
1483 KindTraits>(name) {} 1322 KindTraits>(name) {}
1484 1323
1485 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1486 int dst_index, int src_index, int len,
1487 int hole_start, int hole_end) {
1488 if (len == 0) return;
1489 Handle<FixedDoubleArray> dst_elms =
1490 Handle<FixedDoubleArray>::cast(backing_store);
1491 MemMove(dst_elms->data_start() + dst_index,
1492 dst_elms->data_start() + src_index, len * kDoubleSize);
1493 if (hole_start != hole_end) {
1494 dst_elms->FillWithHoles(hole_start, hole_end);
1495 }
1496 }
1497
1498 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, 1324 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
1499 FixedArrayBase* to, ElementsKind from_kind, 1325 FixedArrayBase* to, ElementsKind from_kind,
1500 uint32_t to_start, int packed_size, 1326 uint32_t to_start, int packed_size,
1501 int copy_size) { 1327 int copy_size) {
1502 DisallowHeapAllocation no_allocation; 1328 DisallowHeapAllocation no_allocation;
1503 switch (from_kind) { 1329 switch (from_kind) {
1504 case FAST_SMI_ELEMENTS: 1330 case FAST_SMI_ELEMENTS:
1505 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, 1331 CopyPackedSmiToDoubleElements(from, from_start, to, to_start,
1506 packed_size, copy_size); 1332 packed_size, copy_size);
1507 break; 1333 break;
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; 1974 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
2149 ELEMENTS_LIST(ACCESSOR_DELETE) 1975 ELEMENTS_LIST(ACCESSOR_DELETE)
2150 #undef ACCESSOR_DELETE 1976 #undef ACCESSOR_DELETE
2151 elements_accessors_ = NULL; 1977 elements_accessors_ = NULL;
2152 } 1978 }
2153 1979
2154 1980
2155 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; 1981 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL;
2156 } // namespace internal 1982 } // namespace internal
2157 } // namespace v8 1983 } // 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