OLD | NEW |
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 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 new_capacity); | 595 new_capacity); |
596 } | 596 } |
597 | 597 |
598 static void AddImpl(Handle<JSObject> object, uint32_t index, | 598 static void AddImpl(Handle<JSObject> object, uint32_t index, |
599 Handle<Object> value, PropertyAttributes attributes, | 599 Handle<Object> value, PropertyAttributes attributes, |
600 uint32_t new_capacity) { | 600 uint32_t new_capacity) { |
601 UNREACHABLE(); | 601 UNREACHABLE(); |
602 } | 602 } |
603 | 603 |
604 virtual uint32_t Push(Handle<JSArray> receiver, | 604 virtual uint32_t Push(Handle<JSArray> receiver, |
605 Handle<FixedArrayBase> backing_store, Object** objects, | 605 Handle<FixedArrayBase> backing_store, Arguments* args, |
606 uint32_t push_size, int direction) final { | 606 uint32_t push_size) final { |
607 return ElementsAccessorSubclass::PushImpl(receiver, backing_store, objects, | 607 return ElementsAccessorSubclass::PushImpl(receiver, backing_store, args, |
608 push_size, direction); | 608 push_size); |
609 } | 609 } |
610 | 610 |
611 static uint32_t PushImpl(Handle<JSArray> receiver, | 611 static uint32_t PushImpl(Handle<JSArray> receiver, |
612 Handle<FixedArrayBase> elms_obj, Object** objects, | 612 Handle<FixedArrayBase> elms_obj, Arguments* args, |
613 uint32_t push_size, int direction) { | 613 uint32_t push_sized) { |
614 UNREACHABLE(); | 614 UNREACHABLE(); |
615 return 0; | 615 return 0; |
616 } | 616 } |
617 | 617 |
618 virtual uint32_t Unshift(Handle<JSArray> receiver, | 618 virtual uint32_t Unshift(Handle<JSArray> receiver, |
619 Handle<FixedArrayBase> backing_store, | 619 Handle<FixedArrayBase> backing_store, |
620 Arguments* args, uint32_t unshift_size) final { | 620 Arguments* args, uint32_t unshift_size) final { |
621 return ElementsAccessorSubclass::UnshiftImpl(receiver, backing_store, args, | 621 return ElementsAccessorSubclass::UnshiftImpl(receiver, backing_store, args, |
622 unshift_size); | 622 unshift_size); |
623 } | 623 } |
(...skipping 15 matching lines...) Expand all Loading... |
639 static Handle<JSArray> SliceImpl(Handle<JSObject> receiver, | 639 static Handle<JSArray> SliceImpl(Handle<JSObject> receiver, |
640 Handle<FixedArrayBase> backing_store, | 640 Handle<FixedArrayBase> backing_store, |
641 uint32_t start, uint32_t end) { | 641 uint32_t start, uint32_t end) { |
642 UNREACHABLE(); | 642 UNREACHABLE(); |
643 return Handle<JSArray>(); | 643 return Handle<JSArray>(); |
644 } | 644 } |
645 | 645 |
646 virtual Handle<JSArray> Splice(Handle<JSArray> receiver, | 646 virtual Handle<JSArray> Splice(Handle<JSArray> receiver, |
647 Handle<FixedArrayBase> backing_store, | 647 Handle<FixedArrayBase> backing_store, |
648 uint32_t start, uint32_t delete_count, | 648 uint32_t start, uint32_t delete_count, |
649 Arguments args, uint32_t add_count) final { | 649 Arguments* args, uint32_t add_count) final { |
650 return ElementsAccessorSubclass::SpliceImpl(receiver, backing_store, start, | 650 return ElementsAccessorSubclass::SpliceImpl(receiver, backing_store, start, |
651 delete_count, args, add_count); | 651 delete_count, args, add_count); |
652 } | 652 } |
653 | 653 |
654 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver, | 654 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver, |
655 Handle<FixedArrayBase> backing_store, | 655 Handle<FixedArrayBase> backing_store, |
656 uint32_t start, uint32_t delete_count, | 656 uint32_t start, uint32_t delete_count, |
657 Arguments args, uint32_t add_count) { | 657 Arguments* args, uint32_t add_count) { |
658 UNREACHABLE(); | 658 UNREACHABLE(); |
659 return Handle<JSArray>(); | 659 return Handle<JSArray>(); |
660 } | 660 } |
661 | 661 |
662 virtual Handle<Object> Pop(Handle<JSArray> receiver, | 662 virtual Handle<Object> Pop(Handle<JSArray> receiver, |
663 Handle<FixedArrayBase> backing_store) final { | 663 Handle<FixedArrayBase> backing_store) final { |
664 return ElementsAccessorSubclass::PopImpl(receiver, backing_store); | 664 return ElementsAccessorSubclass::PopImpl(receiver, backing_store); |
665 } | 665 } |
666 | 666 |
667 static Handle<Object> PopImpl(Handle<JSArray> receiver, | 667 static Handle<Object> PopImpl(Handle<JSArray> receiver, |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 backing_store); | 1269 backing_store); |
1270 | 1270 |
1271 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { | 1271 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { |
1272 result = receiver->GetIsolate()->factory()->undefined_value(); | 1272 result = receiver->GetIsolate()->factory()->undefined_value(); |
1273 } | 1273 } |
1274 return result; | 1274 return result; |
1275 } | 1275 } |
1276 | 1276 |
1277 static uint32_t PushImpl(Handle<JSArray> receiver, | 1277 static uint32_t PushImpl(Handle<JSArray> receiver, |
1278 Handle<FixedArrayBase> backing_store, | 1278 Handle<FixedArrayBase> backing_store, |
1279 Object** objects, uint32_t push_size, | 1279 Arguments* args, uint32_t push_size) { |
1280 int direction) { | |
1281 uint32_t len = Smi::cast(receiver->length())->value(); | 1280 uint32_t len = Smi::cast(receiver->length())->value(); |
1282 if (push_size == 0) { | 1281 if (push_size == 0) { |
1283 return len; | 1282 return len; |
1284 } | 1283 } |
1285 uint32_t elms_len = backing_store->length(); | 1284 uint32_t elms_len = backing_store->length(); |
1286 // Currently fixed arrays cannot grow too big, so | 1285 // Currently fixed arrays cannot grow too big, so |
1287 // we should never hit this case. | 1286 // we should never hit this case. |
1288 DCHECK(push_size <= static_cast<uint32_t>(Smi::kMaxValue - len)); | 1287 DCHECK(push_size <= static_cast<uint32_t>(Smi::kMaxValue - len)); |
1289 uint32_t new_length = len + push_size; | 1288 uint32_t new_length = len + push_size; |
1290 Handle<FixedArrayBase> new_elms; | |
1291 | 1289 |
1292 if (new_length > elms_len) { | 1290 if (new_length > elms_len) { |
1293 // New backing storage is needed. | 1291 // New backing storage is needed. |
1294 uint32_t capacity = new_length + (new_length >> 1) + 16; | 1292 uint32_t capacity = new_length + (new_length >> 1) + 16; |
1295 new_elms = FastElementsAccessorSubclass::ConvertElementsWithCapacity( | 1293 backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity( |
1296 receiver, backing_store, KindTraits::Kind, capacity); | 1294 receiver, backing_store, KindTraits::Kind, capacity); |
1297 } else { | 1295 receiver->set_elements(*backing_store); |
1298 // push_size is > 0 and new_length <= elms_len, so backing_store cannot be | |
1299 // the empty_fixed_array. | |
1300 new_elms = backing_store; | |
1301 } | 1296 } |
1302 | 1297 |
1303 // Add the provided values. | 1298 // Add the provided values. |
1304 DisallowHeapAllocation no_gc; | 1299 DisallowHeapAllocation no_gc; |
1305 DCHECK(direction == ElementsAccessor::kDirectionForward || | 1300 FixedArrayBase* raw_backing_store = *backing_store; |
1306 direction == ElementsAccessor::kDirectionReverse); | 1301 WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc); |
1307 STATIC_ASSERT(ElementsAccessor::kDirectionForward == 1); | |
1308 STATIC_ASSERT(ElementsAccessor::kDirectionReverse == -1); | |
1309 for (uint32_t index = 0; index < push_size; index++) { | 1302 for (uint32_t index = 0; index < push_size; index++) { |
1310 int offset = direction * index; | 1303 Object* object = (*args)[index + 1]; |
1311 Object* object = objects[offset]; | 1304 FastElementsAccessorSubclass::SetImpl(raw_backing_store, index + len, |
1312 FastElementsAccessorSubclass::SetImpl(*new_elms, index + len, object); | 1305 object, mode); |
1313 } | 1306 } |
1314 if (!new_elms.is_identical_to(backing_store)) { | 1307 DCHECK(*backing_store == receiver->elements()); |
1315 receiver->set_elements(*new_elms); | |
1316 } | |
1317 DCHECK(*new_elms == receiver->elements()); | |
1318 // Set the length. | 1308 // Set the length. |
1319 receiver->set_length(Smi::FromInt(new_length)); | 1309 receiver->set_length(Smi::FromInt(new_length)); |
1320 return new_length; | 1310 return new_length; |
1321 } | 1311 } |
1322 | 1312 |
1323 static uint32_t UnshiftImpl(Handle<JSArray> receiver, | 1313 static uint32_t UnshiftImpl(Handle<JSArray> receiver, |
1324 Handle<FixedArrayBase> backing_store, | 1314 Handle<FixedArrayBase> backing_store, |
1325 Arguments* args, uint32_t unshift_size) { | 1315 Arguments* args, uint32_t unshift_size) { |
1326 uint32_t len = Smi::cast(receiver->length())->value(); | 1316 uint32_t len = Smi::cast(receiver->length())->value(); |
1327 if (unshift_size == 0) { | 1317 if (unshift_size == 0) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 DisallowHeapAllocation no_gc; | 1372 DisallowHeapAllocation no_gc; |
1383 FastElementsAccessorSubclass::CopyElementsImpl( | 1373 FastElementsAccessorSubclass::CopyElementsImpl( |
1384 *backing_store, start, result_array->elements(), KindTraits::Kind, 0, | 1374 *backing_store, start, result_array->elements(), KindTraits::Kind, 0, |
1385 kPackedSizeNotKnown, result_len); | 1375 kPackedSizeNotKnown, result_len); |
1386 return result_array; | 1376 return result_array; |
1387 } | 1377 } |
1388 | 1378 |
1389 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver, | 1379 static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver, |
1390 Handle<FixedArrayBase> backing_store, | 1380 Handle<FixedArrayBase> backing_store, |
1391 uint32_t start, uint32_t delete_count, | 1381 uint32_t start, uint32_t delete_count, |
1392 Arguments args, uint32_t add_count) { | 1382 Arguments* args, uint32_t add_count) { |
1393 Isolate* isolate = receiver->GetIsolate(); | 1383 Isolate* isolate = receiver->GetIsolate(); |
1394 Heap* heap = isolate->heap(); | 1384 Heap* heap = isolate->heap(); |
1395 uint32_t len = Smi::cast(receiver->length())->value(); | 1385 uint32_t len = Smi::cast(receiver->length())->value(); |
1396 uint32_t new_length = len - delete_count + add_count; | 1386 uint32_t new_length = len - delete_count + add_count; |
1397 | 1387 |
1398 if (new_length == 0) { | 1388 if (new_length == 0) { |
1399 receiver->set_elements(heap->empty_fixed_array()); | 1389 receiver->set_elements(heap->empty_fixed_array()); |
1400 receiver->set_length(Smi::FromInt(0)); | 1390 receiver->set_length(Smi::FromInt(0)); |
1401 return isolate->factory()->NewJSArrayWithElements( | 1391 return isolate->factory()->NewJSArrayWithElements( |
1402 backing_store, KindTraits::Kind, delete_count); | 1392 backing_store, KindTraits::Kind, delete_count); |
(...skipping 15 matching lines...) Expand all Loading... |
1418 elms_changed = SpliceShrinkStep(backing_store, heap, start, delete_count, | 1408 elms_changed = SpliceShrinkStep(backing_store, heap, start, delete_count, |
1419 add_count, len, new_length); | 1409 add_count, len, new_length); |
1420 } else if (add_count > delete_count) { | 1410 } else if (add_count > delete_count) { |
1421 elms_changed = | 1411 elms_changed = |
1422 SpliceGrowStep(receiver, backing_store, isolate, heap, start, | 1412 SpliceGrowStep(receiver, backing_store, isolate, heap, start, |
1423 delete_count, add_count, len, new_length); | 1413 delete_count, add_count, len, new_length); |
1424 } | 1414 } |
1425 | 1415 |
1426 // Copy new Elements from args | 1416 // Copy new Elements from args |
1427 DisallowHeapAllocation no_gc; | 1417 DisallowHeapAllocation no_gc; |
1428 for (uint32_t index = start; index < start + add_count; index++) { | 1418 FixedArrayBase* raw_backing_store = *backing_store; |
1429 Object* arg = args[3 + index - start]; | 1419 WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc); |
1430 FastElementsAccessorSubclass::SetImpl(*backing_store, index, arg); | 1420 for (uint32_t index = 0; index < add_count; index++) { |
| 1421 Object* object = (*args)[3 + index]; |
| 1422 FastElementsAccessorSubclass::SetImpl(raw_backing_store, index + start, |
| 1423 object, mode); |
1431 } | 1424 } |
1432 | 1425 |
1433 if (elms_changed) { | 1426 if (elms_changed) { |
1434 receiver->set_elements(*backing_store); | 1427 receiver->set_elements(*backing_store); |
1435 } | 1428 } |
1436 receiver->set_length(Smi::FromInt(new_length)); | 1429 receiver->set_length(Smi::FromInt(new_length)); |
1437 return deleted_elements; | 1430 return deleted_elements; |
1438 } | 1431 } |
1439 | 1432 |
1440 private: | 1433 private: |
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2324 if (elements_accessors_ == NULL) return; | 2317 if (elements_accessors_ == NULL) return; |
2325 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 2318 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
2326 ELEMENTS_LIST(ACCESSOR_DELETE) | 2319 ELEMENTS_LIST(ACCESSOR_DELETE) |
2327 #undef ACCESSOR_DELETE | 2320 #undef ACCESSOR_DELETE |
2328 elements_accessors_ = NULL; | 2321 elements_accessors_ = NULL; |
2329 } | 2322 } |
2330 | 2323 |
2331 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2324 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2332 } // namespace internal | 2325 } // namespace internal |
2333 } // namespace v8 | 2326 } // namespace v8 |
OLD | NEW |