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/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 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 DisallowHeapAllocation no_gc; | 541 DisallowHeapAllocation no_gc; |
542 ElementsAccessorSubclass::ValidateImpl(holder); | 542 ElementsAccessorSubclass::ValidateImpl(holder); |
543 } | 543 } |
544 | 544 |
545 virtual bool HasElement(Handle<JSObject> holder, uint32_t index, | 545 virtual bool HasElement(Handle<JSObject> holder, uint32_t index, |
546 Handle<FixedArrayBase> backing_store) final { | 546 Handle<FixedArrayBase> backing_store) final { |
547 return ElementsAccessorSubclass::GetEntryForIndexImpl( | 547 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
548 *holder, *backing_store, index) != kMaxUInt32; | 548 *holder, *backing_store, index) != kMaxUInt32; |
549 } | 549 } |
550 | 550 |
551 virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t index, | 551 virtual Handle<Object> Get(Handle<FixedArrayBase> backing_store, |
552 Handle<FixedArrayBase> backing_store) final { | 552 uint32_t entry) final { |
553 if (!IsExternalArrayElementsKind(ElementsTraits::Kind) && | 553 return ElementsAccessorSubclass::GetImpl(backing_store, entry); |
554 FLAG_trace_js_array_abuse) { | |
555 CheckArrayAbuse(holder, "elements read", index); | |
556 } | |
557 | |
558 if (IsExternalArrayElementsKind(ElementsTraits::Kind) && | |
559 FLAG_trace_external_array_abuse) { | |
560 CheckArrayAbuse(holder, "external elements read", index); | |
561 } | |
562 | |
563 return ElementsAccessorSubclass::GetImpl(holder, index, backing_store); | |
564 } | 554 } |
565 | 555 |
566 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, | 556 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, |
567 Handle<FixedArrayBase> backing_store) { | 557 uint32_t entry) { |
568 if (index < | 558 uint32_t index = GetIndexForEntryImpl(*backing_store, entry); |
569 ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { | 559 return BackingStore::get(Handle<BackingStore>::cast(backing_store), index); |
570 return BackingStore::get(Handle<BackingStore>::cast(backing_store), | |
571 index); | |
572 } else { | |
573 return backing_store->GetIsolate()->factory()->the_hole_value(); | |
574 } | |
575 } | 560 } |
576 | 561 |
577 virtual void Set(FixedArrayBase* backing_store, uint32_t entry, | 562 virtual void Set(FixedArrayBase* backing_store, uint32_t entry, |
578 Object* value) final { | 563 Object* value) final { |
579 ElementsAccessorSubclass::SetImpl(backing_store, entry, value); | 564 ElementsAccessorSubclass::SetImpl(backing_store, entry, value); |
580 } | 565 } |
581 | 566 |
582 static void SetImpl(FixedArrayBase* backing_store, uint32_t entry, | 567 static void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
583 Object* value) { | 568 Object* value) { |
584 BackingStore::cast(backing_store)->SetValue(entry, value); | 569 BackingStore::cast(backing_store)->SetValue(entry, value); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 // We cannot optimize if 'this' is empty, as other may have holes. | 736 // We cannot optimize if 'this' is empty, as other may have holes. |
752 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); | 737 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); |
753 if (len1 == 0) return to; | 738 if (len1 == 0) return to; |
754 | 739 |
755 Isolate* isolate = from->GetIsolate(); | 740 Isolate* isolate = from->GetIsolate(); |
756 | 741 |
757 // Compute how many elements are not in other. | 742 // Compute how many elements are not in other. |
758 uint32_t extra = 0; | 743 uint32_t extra = 0; |
759 for (uint32_t y = 0; y < len1; y++) { | 744 for (uint32_t y = 0; y < len1; y++) { |
760 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { | 745 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { |
761 uint32_t index = | 746 Handle<Object> value = ElementsAccessorSubclass::GetImpl(from, y); |
762 ElementsAccessorSubclass::GetIndexForEntryImpl(*from, y); | |
763 Handle<Object> value = | |
764 ElementsAccessorSubclass::GetImpl(receiver, index, from); | |
765 | 747 |
766 DCHECK(!value->IsTheHole()); | 748 DCHECK(!value->IsTheHole()); |
767 DCHECK(!value->IsAccessorPair()); | 749 DCHECK(!value->IsAccessorPair()); |
768 DCHECK(!value->IsExecutableAccessorInfo()); | 750 DCHECK(!value->IsExecutableAccessorInfo()); |
769 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 751 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
770 continue; | 752 continue; |
771 } | 753 } |
772 if (!HasIndex(to, value)) { | 754 if (!HasIndex(to, value)) { |
773 extra++; | 755 extra++; |
774 } | 756 } |
(...skipping 12 matching lines...) Expand all Loading... |
787 for (int i = 0; i < len0; i++) { | 769 for (int i = 0; i < len0; i++) { |
788 Object* e = to->get(i); | 770 Object* e = to->get(i); |
789 DCHECK(e->IsString() || e->IsNumber()); | 771 DCHECK(e->IsString() || e->IsNumber()); |
790 result->set(i, e, mode); | 772 result->set(i, e, mode); |
791 } | 773 } |
792 } | 774 } |
793 // Fill in the extra values. | 775 // Fill in the extra values. |
794 uint32_t entry = 0; | 776 uint32_t entry = 0; |
795 for (uint32_t y = 0; y < len1; y++) { | 777 for (uint32_t y = 0; y < len1; y++) { |
796 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { | 778 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { |
797 uint32_t index = | 779 Handle<Object> value = ElementsAccessorSubclass::GetImpl(from, y); |
798 ElementsAccessorSubclass::GetIndexForEntryImpl(*from, y); | |
799 Handle<Object> value = | |
800 ElementsAccessorSubclass::GetImpl(receiver, index, from); | |
801 DCHECK(!value->IsAccessorPair()); | 780 DCHECK(!value->IsAccessorPair()); |
802 DCHECK(!value->IsExecutableAccessorInfo()); | 781 DCHECK(!value->IsExecutableAccessorInfo()); |
803 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 782 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
804 continue; | 783 continue; |
805 } | 784 } |
806 if (!value->IsTheHole() && !HasIndex(to, value)) { | 785 if (!value->IsTheHole() && !HasIndex(to, value)) { |
807 result->set(len0 + entry, *value); | 786 result->set(len0 + entry, *value); |
808 entry++; | 787 entry++; |
809 } | 788 } |
810 } | 789 } |
(...skipping 16 matching lines...) Expand all Loading... |
827 } | 806 } |
828 | 807 |
829 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 808 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
830 uint32_t entry) { | 809 uint32_t entry) { |
831 return entry; | 810 return entry; |
832 } | 811 } |
833 | 812 |
834 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 813 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
835 FixedArrayBase* backing_store, | 814 FixedArrayBase* backing_store, |
836 uint32_t index) { | 815 uint32_t index) { |
837 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, | 816 if (IsHoleyElementsKind(kind())) { |
838 backing_store) && | 817 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
839 !BackingStore::cast(backing_store)->is_the_hole(index) | 818 backing_store) && |
840 ? index | 819 !BackingStore::cast(backing_store)->is_the_hole(index) |
841 : kMaxUInt32; | 820 ? index |
| 821 : kMaxUInt32; |
| 822 } else { |
| 823 Smi* smi_length = Smi::cast(JSArray::cast(holder)->length()); |
| 824 uint32_t length = static_cast<uint32_t>(smi_length->value()); |
| 825 return index < length ? index : kMaxUInt32; |
| 826 } |
842 } | 827 } |
843 | 828 |
844 virtual uint32_t GetEntryForIndex(JSObject* holder, | 829 virtual uint32_t GetEntryForIndex(JSObject* holder, |
845 FixedArrayBase* backing_store, | 830 FixedArrayBase* backing_store, |
846 uint32_t index) final { | 831 uint32_t index) final { |
847 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, | 832 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, |
848 index); | 833 index); |
849 } | 834 } |
850 | 835 |
851 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 836 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 SeededNumberDictionary::cast(obj->elements())); | 923 SeededNumberDictionary::cast(obj->elements())); |
939 uint32_t index = GetIndexForEntryImpl(*dict, entry); | 924 uint32_t index = GetIndexForEntryImpl(*dict, entry); |
940 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry); | 925 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry); |
941 USE(result); | 926 USE(result); |
942 DCHECK(result->IsTrue()); | 927 DCHECK(result->IsTrue()); |
943 Handle<FixedArray> new_elements = | 928 Handle<FixedArray> new_elements = |
944 SeededNumberDictionary::Shrink(dict, index); | 929 SeededNumberDictionary::Shrink(dict, index); |
945 obj->set_elements(*new_elements); | 930 obj->set_elements(*new_elements); |
946 } | 931 } |
947 | 932 |
948 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, | 933 static Handle<Object> GetImpl(Handle<FixedArrayBase> store, uint32_t entry) { |
949 Handle<FixedArrayBase> store) { | |
950 Handle<SeededNumberDictionary> backing_store = | 934 Handle<SeededNumberDictionary> backing_store = |
951 Handle<SeededNumberDictionary>::cast(store); | 935 Handle<SeededNumberDictionary>::cast(store); |
952 Isolate* isolate = backing_store->GetIsolate(); | 936 Isolate* isolate = backing_store->GetIsolate(); |
953 int entry = backing_store->FindEntry(index); | 937 return handle(backing_store->ValueAt(entry), isolate); |
954 if (entry != SeededNumberDictionary::kNotFound) { | |
955 return handle(backing_store->ValueAt(entry), isolate); | |
956 } | |
957 return isolate->factory()->the_hole_value(); | |
958 } | 938 } |
959 | 939 |
960 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { | 940 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { |
961 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); | 941 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
962 dictionary->ValueAtPut(entry, value); | 942 dictionary->ValueAtPut(entry, value); |
963 } | 943 } |
964 | 944 |
965 static void ReconfigureImpl(Handle<JSObject> object, | 945 static void ReconfigureImpl(Handle<JSObject> object, |
966 Handle<FixedArrayBase> store, uint32_t entry, | 946 Handle<FixedArrayBase> store, uint32_t entry, |
967 Handle<Object> value, | 947 Handle<Object> value, |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 1346 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, |
1367 ElementsKindTraits<Kind> > { | 1347 ElementsKindTraits<Kind> > { |
1368 public: | 1348 public: |
1369 explicit TypedElementsAccessor(const char* name) | 1349 explicit TypedElementsAccessor(const char* name) |
1370 : ElementsAccessorBase<AccessorClass, | 1350 : ElementsAccessorBase<AccessorClass, |
1371 ElementsKindTraits<Kind> >(name) {} | 1351 ElementsKindTraits<Kind> >(name) {} |
1372 | 1352 |
1373 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1353 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
1374 typedef TypedElementsAccessor<Kind> AccessorClass; | 1354 typedef TypedElementsAccessor<Kind> AccessorClass; |
1375 | 1355 |
1376 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, | 1356 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, |
1377 Handle<FixedArrayBase> backing_store) { | 1357 uint32_t entry) { |
1378 if (index < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { | 1358 uint32_t index = GetIndexForEntryImpl(*backing_store, entry); |
1379 return BackingStore::get(Handle<BackingStore>::cast(backing_store), | 1359 return BackingStore::get(Handle<BackingStore>::cast(backing_store), index); |
1380 index); | |
1381 } else { | |
1382 return backing_store->GetIsolate()->factory()->undefined_value(); | |
1383 } | |
1384 } | 1360 } |
1385 | 1361 |
1386 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1362 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1387 uint32_t entry) { | 1363 uint32_t entry) { |
1388 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); | 1364 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); |
1389 } | 1365 } |
1390 | 1366 |
1391 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1367 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1392 Handle<FixedArrayBase> backing_store) { | 1368 Handle<FixedArrayBase> backing_store) { |
1393 // External arrays do not support changing their length. | 1369 // External arrays do not support changing their length. |
1394 UNREACHABLE(); | 1370 UNREACHABLE(); |
1395 } | 1371 } |
1396 | 1372 |
1397 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { | 1373 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
1398 UNREACHABLE(); | 1374 UNREACHABLE(); |
1399 } | 1375 } |
1400 | 1376 |
| 1377 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
| 1378 uint32_t entry) { |
| 1379 return entry; |
| 1380 } |
| 1381 |
1401 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1382 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
1402 FixedArrayBase* backing_store, | 1383 FixedArrayBase* backing_store, |
1403 uint32_t index) { | 1384 uint32_t index) { |
1404 return index < AccessorClass::GetCapacityImpl(holder, backing_store) | 1385 return index < AccessorClass::GetCapacityImpl(holder, backing_store) |
1405 ? index | 1386 ? index |
1406 : kMaxUInt32; | 1387 : kMaxUInt32; |
1407 } | 1388 } |
1408 | 1389 |
1409 static uint32_t GetCapacityImpl(JSObject* holder, | 1390 static uint32_t GetCapacityImpl(JSObject* holder, |
1410 FixedArrayBase* backing_store) { | 1391 FixedArrayBase* backing_store) { |
(...skipping 21 matching lines...) Expand all Loading... |
1432 | 1413 |
1433 | 1414 |
1434 template <typename SloppyArgumentsElementsAccessorSubclass, | 1415 template <typename SloppyArgumentsElementsAccessorSubclass, |
1435 typename ArgumentsAccessor, typename KindTraits> | 1416 typename ArgumentsAccessor, typename KindTraits> |
1436 class SloppyArgumentsElementsAccessor | 1417 class SloppyArgumentsElementsAccessor |
1437 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1418 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1438 KindTraits> { | 1419 KindTraits> { |
1439 public: | 1420 public: |
1440 explicit SloppyArgumentsElementsAccessor(const char* name) | 1421 explicit SloppyArgumentsElementsAccessor(const char* name) |
1441 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1422 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1442 KindTraits>(name) {} | 1423 KindTraits>(name) { |
| 1424 USE(KindTraits::Kind); |
| 1425 } |
1443 | 1426 |
1444 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, | 1427 static Handle<Object> GetImpl(Handle<FixedArrayBase> parameters, |
1445 Handle<FixedArrayBase> parameters) { | 1428 uint32_t entry) { |
1446 Isolate* isolate = obj->GetIsolate(); | 1429 Isolate* isolate = parameters->GetIsolate(); |
1447 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1430 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
1448 Handle<Object> probe(GetParameterMapArg(*parameter_map, index), isolate); | 1431 uint32_t length = parameter_map->length() - 2; |
1449 if (!probe->IsTheHole()) { | 1432 if (entry < length) { |
1450 DisallowHeapAllocation no_gc; | 1433 DisallowHeapAllocation no_gc; |
| 1434 Object* probe = parameter_map->get(entry + 2); |
1451 Context* context = Context::cast(parameter_map->get(0)); | 1435 Context* context = Context::cast(parameter_map->get(0)); |
1452 int context_entry = Handle<Smi>::cast(probe)->value(); | 1436 int context_entry = Smi::cast(probe)->value(); |
1453 DCHECK(!context->get(context_entry)->IsTheHole()); | 1437 DCHECK(!context->get(context_entry)->IsTheHole()); |
1454 return handle(context->get(context_entry), isolate); | 1438 return handle(context->get(context_entry), isolate); |
1455 } else { | 1439 } else { |
1456 // Object is not mapped, defer to the arguments. | 1440 // Object is not mapped, defer to the arguments. |
1457 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), | 1441 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), |
1458 isolate); | 1442 isolate); |
1459 Handle<Object> result = ArgumentsAccessor::GetImpl(obj, index, arguments); | 1443 Handle<Object> result = |
| 1444 ArgumentsAccessor::GetImpl(arguments, entry - length); |
1460 // Elements of the arguments object in slow mode might be slow aliases. | 1445 // Elements of the arguments object in slow mode might be slow aliases. |
1461 if (result->IsAliasedArgumentsEntry()) { | 1446 if (result->IsAliasedArgumentsEntry()) { |
1462 DisallowHeapAllocation no_gc; | 1447 DisallowHeapAllocation no_gc; |
1463 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); | 1448 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); |
1464 Context* context = Context::cast(parameter_map->get(0)); | 1449 Context* context = Context::cast(parameter_map->get(0)); |
1465 int context_entry = entry->aliased_context_slot(); | 1450 int context_entry = entry->aliased_context_slot(); |
1466 DCHECK(!context->get(context_entry)->IsTheHole()); | 1451 DCHECK(!context->get(context_entry)->IsTheHole()); |
1467 return handle(context->get(context_entry), isolate); | 1452 return handle(context->get(context_entry), isolate); |
1468 } else { | |
1469 return result; | |
1470 } | 1453 } |
| 1454 return result; |
1471 } | 1455 } |
1472 } | 1456 } |
1473 | 1457 |
1474 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 1458 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
1475 uint32_t capacity) { | 1459 uint32_t capacity) { |
1476 UNREACHABLE(); | 1460 UNREACHABLE(); |
1477 } | 1461 } |
1478 | 1462 |
1479 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { | 1463 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { |
1480 FixedArray* parameter_map = FixedArray::cast(store); | 1464 FixedArray* parameter_map = FixedArray::cast(store); |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1935 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1919 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
1936 ELEMENTS_LIST(ACCESSOR_DELETE) | 1920 ELEMENTS_LIST(ACCESSOR_DELETE) |
1937 #undef ACCESSOR_DELETE | 1921 #undef ACCESSOR_DELETE |
1938 elements_accessors_ = NULL; | 1922 elements_accessors_ = NULL; |
1939 } | 1923 } |
1940 | 1924 |
1941 | 1925 |
1942 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 1926 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
1943 } // namespace internal | 1927 } // namespace internal |
1944 } // namespace v8 | 1928 } // namespace v8 |
OLD | NEW |