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 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 template <typename ElementsAccessorSubclass, | 549 template <typename ElementsAccessorSubclass, |
550 typename ElementsTraitsParam> | 550 typename ElementsTraitsParam> |
551 class ElementsAccessorBase : public ElementsAccessor { | 551 class ElementsAccessorBase : public ElementsAccessor { |
552 protected: | 552 protected: |
553 explicit ElementsAccessorBase(const char* name) | 553 explicit ElementsAccessorBase(const char* name) |
554 : ElementsAccessor(name) { } | 554 : ElementsAccessor(name) { } |
555 | 555 |
556 typedef ElementsTraitsParam ElementsTraits; | 556 typedef ElementsTraitsParam ElementsTraits; |
557 typedef typename ElementsTraitsParam::BackingStore BackingStore; | 557 typedef typename ElementsTraitsParam::BackingStore BackingStore; |
558 | 558 |
559 ElementsKind kind() const final { return ElementsTraits::Kind; } | 559 static ElementsKind kind() { return ElementsTraits::Kind; } |
560 | 560 |
561 static void ValidateContents(Handle<JSObject> holder, int length) { | 561 static void ValidateContents(Handle<JSObject> holder, int length) { |
562 } | 562 } |
563 | 563 |
564 static void ValidateImpl(Handle<JSObject> holder) { | 564 static void ValidateImpl(Handle<JSObject> holder) { |
565 Handle<FixedArrayBase> fixed_array_base(holder->elements()); | 565 Handle<FixedArrayBase> fixed_array_base(holder->elements()); |
566 if (!fixed_array_base->IsHeapObject()) return; | 566 if (!fixed_array_base->IsHeapObject()) return; |
567 // Arrays that have been shifted in place can't be verified. | 567 // Arrays that have been shifted in place can't be verified. |
568 if (fixed_array_base->IsFiller()) return; | 568 if (fixed_array_base->IsFiller()) return; |
569 int length = 0; | 569 int length = 0; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 } | 637 } |
638 | 638 |
639 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { | 639 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
640 ElementsAccessorSubclass::SetLengthImpl(array, length, | 640 ElementsAccessorSubclass::SetLengthImpl(array, length, |
641 handle(array->elements())); | 641 handle(array->elements())); |
642 } | 642 } |
643 | 643 |
644 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 644 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
645 Handle<FixedArrayBase> backing_store); | 645 Handle<FixedArrayBase> backing_store); |
646 | 646 |
647 static void GrowCapacityAndConvertImpl(Handle<JSObject> obj, | 647 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
| 648 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
| 649 ElementsKind from_kind, uint32_t capacity) { |
| 650 Isolate* isolate = object->GetIsolate(); |
| 651 Handle<FixedArrayBase> elements; |
| 652 if (IsFastDoubleElementsKind(kind())) { |
| 653 elements = isolate->factory()->NewFixedDoubleArray(capacity); |
| 654 } else { |
| 655 elements = isolate->factory()->NewUninitializedFixedArray(capacity); |
| 656 } |
| 657 |
| 658 int packed = kPackedSizeNotKnown; |
| 659 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) { |
| 660 packed = Smi::cast(JSArray::cast(*object)->length())->value(); |
| 661 } |
| 662 |
| 663 ElementsAccessorSubclass::CopyElementsImpl( |
| 664 *old_elements, 0, *elements, from_kind, 0, packed, |
| 665 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 666 return elements; |
| 667 } |
| 668 |
| 669 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
648 uint32_t capacity) { | 670 uint32_t capacity) { |
649 UNIMPLEMENTED(); | 671 ElementsKind from_kind = object->GetElementsKind(); |
| 672 if (IsFastSmiOrObjectElementsKind(from_kind)) { |
| 673 // Array optimizations rely on the prototype lookups of Array objects |
| 674 // always returning undefined. If there is a store to the initial |
| 675 // prototype object, make sure all of these optimizations are invalidated. |
| 676 object->GetIsolate()->UpdateArrayProtectorOnSetLength(object); |
| 677 } |
| 678 Handle<FixedArrayBase> old_elements(object->elements()); |
| 679 // This method should only be called if there's a reason to update the |
| 680 // elements. |
| 681 DCHECK(IsFastDoubleElementsKind(from_kind) != |
| 682 IsFastDoubleElementsKind(kind()) || |
| 683 IsDictionaryElementsKind(from_kind) || |
| 684 static_cast<uint32_t>(old_elements->length()) < capacity); |
| 685 Handle<FixedArrayBase> elements = |
| 686 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
| 687 |
| 688 ElementsKind to_kind = kind(); |
| 689 if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind); |
| 690 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, to_kind); |
| 691 JSObject::SetMapAndElements(object, new_map, elements); |
| 692 |
| 693 // Transition through the allocation site as well if present. |
| 694 JSObject::UpdateAllocationSite(object, to_kind); |
| 695 |
| 696 if (FLAG_trace_elements_transitions) { |
| 697 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements, |
| 698 to_kind, elements); |
| 699 } |
650 } | 700 } |
651 | 701 |
652 virtual void GrowCapacityAndConvert(Handle<JSObject> object, | 702 virtual void GrowCapacityAndConvert(Handle<JSObject> object, |
653 uint32_t capacity) final { | 703 uint32_t capacity) final { |
654 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity); | 704 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity); |
655 } | 705 } |
656 | 706 |
657 virtual void Delete(Handle<JSObject> obj, uint32_t key, | 707 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
658 LanguageMode language_mode) override = 0; | 708 LanguageMode language_mode) override = 0; |
659 | 709 |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 break; | 1078 break; |
1029 } | 1079 } |
1030 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1080 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1031 case EXTERNAL_##TYPE##_ELEMENTS: \ | 1081 case EXTERNAL_##TYPE##_ELEMENTS: \ |
1032 case TYPE##_ELEMENTS: \ | 1082 case TYPE##_ELEMENTS: \ |
1033 UNREACHABLE(); | 1083 UNREACHABLE(); |
1034 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1084 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1035 #undef TYPED_ARRAY_CASE | 1085 #undef TYPED_ARRAY_CASE |
1036 } | 1086 } |
1037 } | 1087 } |
1038 | |
1039 | |
1040 static void GrowCapacityAndConvertImpl(Handle<JSObject> obj, | |
1041 uint32_t capacity) { | |
1042 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = | |
1043 obj->HasFastSmiElements() | |
1044 ? JSObject::kAllowSmiElements | |
1045 : JSObject::kDontAllowSmiElements; | |
1046 JSObject::SetFastElementsCapacity(obj, capacity, set_capacity_mode); | |
1047 } | |
1048 }; | 1088 }; |
1049 | 1089 |
1050 | 1090 |
1051 class FastPackedSmiElementsAccessor | 1091 class FastPackedSmiElementsAccessor |
1052 : public FastSmiOrObjectElementsAccessor< | 1092 : public FastSmiOrObjectElementsAccessor< |
1053 FastPackedSmiElementsAccessor, | 1093 FastPackedSmiElementsAccessor, |
1054 ElementsKindTraits<FAST_SMI_ELEMENTS> > { | 1094 ElementsKindTraits<FAST_SMI_ELEMENTS> > { |
1055 public: | 1095 public: |
1056 explicit FastPackedSmiElementsAccessor(const char* name) | 1096 explicit FastPackedSmiElementsAccessor(const char* name) |
1057 : FastSmiOrObjectElementsAccessor< | 1097 : FastSmiOrObjectElementsAccessor< |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 | 1138 |
1099 template<typename FastElementsAccessorSubclass, | 1139 template<typename FastElementsAccessorSubclass, |
1100 typename KindTraits> | 1140 typename KindTraits> |
1101 class FastDoubleElementsAccessor | 1141 class FastDoubleElementsAccessor |
1102 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { | 1142 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { |
1103 public: | 1143 public: |
1104 explicit FastDoubleElementsAccessor(const char* name) | 1144 explicit FastDoubleElementsAccessor(const char* name) |
1105 : FastElementsAccessor<FastElementsAccessorSubclass, | 1145 : FastElementsAccessor<FastElementsAccessorSubclass, |
1106 KindTraits>(name) {} | 1146 KindTraits>(name) {} |
1107 | 1147 |
1108 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | |
1109 uint32_t capacity) { | |
1110 Handle<FixedArrayBase> elements = | |
1111 object->GetIsolate()->factory()->NewFixedDoubleArray(capacity); | |
1112 ElementsKind from_kind = object->GetElementsKind(); | |
1113 ElementsKind to_kind = IsHoleyElementsKind(from_kind) | |
1114 ? FAST_HOLEY_DOUBLE_ELEMENTS | |
1115 : FAST_DOUBLE_ELEMENTS; | |
1116 | |
1117 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, to_kind); | |
1118 | |
1119 Handle<FixedArrayBase> old_elements(object->elements()); | |
1120 int packed = kPackedSizeNotKnown; | |
1121 if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) { | |
1122 packed = Smi::cast(JSArray::cast(*object)->length())->value(); | |
1123 } | |
1124 CopyElementsImpl(*old_elements, 0, *elements, from_kind, 0, packed, | |
1125 ElementsAccessor::kCopyToEndAndInitializeToHole); | |
1126 | |
1127 JSObject::SetMapAndElements(object, new_map, elements); | |
1128 JSObject::ValidateElements(object); | |
1129 | |
1130 if (FLAG_trace_elements_transitions) { | |
1131 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements, | |
1132 to_kind, elements); | |
1133 } | |
1134 } | |
1135 | |
1136 protected: | 1148 protected: |
1137 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1149 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
1138 FixedArrayBase* to, ElementsKind from_kind, | 1150 FixedArrayBase* to, ElementsKind from_kind, |
1139 uint32_t to_start, int packed_size, | 1151 uint32_t to_start, int packed_size, |
1140 int copy_size) { | 1152 int copy_size) { |
1141 DisallowHeapAllocation no_allocation; | 1153 DisallowHeapAllocation no_allocation; |
1142 switch (from_kind) { | 1154 switch (from_kind) { |
1143 case FAST_SMI_ELEMENTS: | 1155 case FAST_SMI_ELEMENTS: |
1144 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, | 1156 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, |
1145 packed_size, copy_size); | 1157 packed_size, copy_size); |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1488 Context* context = Context::cast(parameter_map->get(0)); | 1500 Context* context = Context::cast(parameter_map->get(0)); |
1489 int context_index = entry->aliased_context_slot(); | 1501 int context_index = entry->aliased_context_slot(); |
1490 DCHECK(!context->get(context_index)->IsTheHole()); | 1502 DCHECK(!context->get(context_index)->IsTheHole()); |
1491 return handle(context->get(context_index), isolate); | 1503 return handle(context->get(context_index), isolate); |
1492 } else { | 1504 } else { |
1493 return result; | 1505 return result; |
1494 } | 1506 } |
1495 } | 1507 } |
1496 } | 1508 } |
1497 | 1509 |
| 1510 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
| 1511 uint32_t capacity) { |
| 1512 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1513 Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1))); |
| 1514 ElementsKind from_kind = old_elements->IsDictionary() ? DICTIONARY_ELEMENTS |
| 1515 : FAST_HOLEY_ELEMENTS; |
| 1516 // This method should only be called if there's a reason to update the |
| 1517 // elements. |
| 1518 DCHECK(IsDictionaryElementsKind(from_kind) || |
| 1519 static_cast<uint32_t>(old_elements->length()) < capacity); |
| 1520 Handle<FixedArrayBase> elements = |
| 1521 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
| 1522 parameter_map->set(1, *elements); |
| 1523 JSObject::ValidateElements(object); |
| 1524 } |
| 1525 |
1498 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | 1526 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { |
1499 FixedArray* parameter_map = FixedArray::cast(store); | 1527 FixedArray* parameter_map = FixedArray::cast(store); |
1500 Object* probe = GetParameterMapArg(parameter_map, key); | 1528 Object* probe = GetParameterMapArg(parameter_map, key); |
1501 if (!probe->IsTheHole()) { | 1529 if (!probe->IsTheHole()) { |
1502 Context* context = Context::cast(parameter_map->get(0)); | 1530 Context* context = Context::cast(parameter_map->get(0)); |
1503 int context_index = Smi::cast(probe)->value(); | 1531 int context_index = Smi::cast(probe)->value(); |
1504 DCHECK(!context->get(context_index)->IsTheHole()); | 1532 DCHECK(!context->get(context_index)->IsTheHole()); |
1505 context->set(context_index, value); | 1533 context->set(context_index, value); |
1506 } else { | 1534 } else { |
1507 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1535 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 // the class for the most generalized ElementsKind subclass. | 1578 // the class for the most generalized ElementsKind subclass. |
1551 FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); | 1579 FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); |
1552 } | 1580 } |
1553 } | 1581 } |
1554 } | 1582 } |
1555 | 1583 |
1556 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1584 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
1557 FixedArrayBase* to, ElementsKind from_kind, | 1585 FixedArrayBase* to, ElementsKind from_kind, |
1558 uint32_t to_start, int packed_size, | 1586 uint32_t to_start, int packed_size, |
1559 int copy_size) { | 1587 int copy_size) { |
1560 UNREACHABLE(); | 1588 DCHECK(!to->IsDictionary()); |
| 1589 if (from_kind == DICTIONARY_ELEMENTS) { |
| 1590 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, |
| 1591 to_start, copy_size); |
| 1592 } else { |
| 1593 DCHECK_EQ(FAST_HOLEY_ELEMENTS, from_kind); |
| 1594 CopyObjectToObjectElements(from, from_kind, from_start, to, |
| 1595 FAST_HOLEY_ELEMENTS, to_start, copy_size); |
| 1596 } |
1561 } | 1597 } |
1562 | 1598 |
1563 static uint32_t GetCapacityImpl(JSObject* holder, | 1599 static uint32_t GetCapacityImpl(JSObject* holder, |
1564 FixedArrayBase* backing_store) { | 1600 FixedArrayBase* backing_store) { |
1565 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1601 FixedArray* parameter_map = FixedArray::cast(backing_store); |
1566 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1602 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1567 return parameter_map->length() - 2 + | 1603 return parameter_map->length() - 2 + |
1568 ForArray(arguments)->GetCapacity(holder, arguments); | 1604 ForArray(arguments)->GetCapacity(holder, arguments); |
1569 } | 1605 } |
1570 | 1606 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1788 break; | 1824 break; |
1789 } | 1825 } |
1790 | 1826 |
1791 array->set_elements(*elms); | 1827 array->set_elements(*elms); |
1792 array->set_length(Smi::FromInt(number_of_elements)); | 1828 array->set_length(Smi::FromInt(number_of_elements)); |
1793 return array; | 1829 return array; |
1794 } | 1830 } |
1795 | 1831 |
1796 } // namespace internal | 1832 } // namespace internal |
1797 } // namespace v8 | 1833 } // namespace v8 |
OLD | NEW |