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 29 matching lines...) Expand all Loading... |
40 // - FixedInt8ElementsAccessor | 40 // - FixedInt8ElementsAccessor |
41 // - FixedUint16ElementsAccessor | 41 // - FixedUint16ElementsAccessor |
42 // - FixedInt16ElementsAccessor | 42 // - FixedInt16ElementsAccessor |
43 // - FixedUint32ElementsAccessor | 43 // - FixedUint32ElementsAccessor |
44 // - FixedInt32ElementsAccessor | 44 // - FixedInt32ElementsAccessor |
45 // - FixedFloat32ElementsAccessor | 45 // - FixedFloat32ElementsAccessor |
46 // - FixedFloat64ElementsAccessor | 46 // - FixedFloat64ElementsAccessor |
47 // - FixedUint8ClampedElementsAccessor | 47 // - FixedUint8ClampedElementsAccessor |
48 // - DictionaryElementsAccessor | 48 // - DictionaryElementsAccessor |
49 // - SloppyArgumentsElementsAccessor | 49 // - SloppyArgumentsElementsAccessor |
| 50 // - FastSloppyArgumentsElementsAccessor |
| 51 // - SlowSloppyArgumentsElementsAccessor |
50 | 52 |
51 | 53 |
52 namespace v8 { | 54 namespace v8 { |
53 namespace internal { | 55 namespace internal { |
54 | 56 |
55 | 57 |
56 static const int kPackedSizeNotKnown = -1; | 58 static const int kPackedSizeNotKnown = -1; |
57 | 59 |
58 | 60 |
59 // First argument in list is the accessor class, the second argument is the | 61 // First argument in list is the accessor class, the second argument is the |
60 // accessor ElementsKind, and the third is the backing store class. Use the | 62 // accessor ElementsKind, and the third is the backing store class. Use the |
61 // fast element handler for smi-only arrays. The implementation is currently | 63 // fast element handler for smi-only arrays. The implementation is currently |
62 // identical. Note that the order must match that of the ElementsKind enum for | 64 // identical. Note that the order must match that of the ElementsKind enum for |
63 // the |accessor_array[]| below to work. | 65 // the |accessor_array[]| below to work. |
64 #define ELEMENTS_LIST(V) \ | 66 #define ELEMENTS_LIST(V) \ |
65 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ | 67 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ |
66 V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \ | 68 V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, FixedArray) \ |
67 FixedArray) \ | 69 V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ |
68 V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ | 70 V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \ |
69 V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \ | 71 V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \ |
70 V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \ | 72 V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \ |
71 FixedDoubleArray) \ | 73 FixedDoubleArray) \ |
72 V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \ | 74 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, SeededNumberDictionary) \ |
73 FixedDoubleArray) \ | 75 V(FastSloppyArgumentsElementsAccessor, FAST_SLOPPY_ARGUMENTS_ELEMENTS, \ |
74 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ | 76 FixedArray) \ |
75 SeededNumberDictionary) \ | 77 V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS, \ |
76 V(SloppyArgumentsElementsAccessor, SLOPPY_ARGUMENTS_ELEMENTS, \ | 78 FixedArray) \ |
77 FixedArray) \ | 79 V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, ExternalInt8Array) \ |
78 V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, \ | 80 V(ExternalUint8ElementsAccessor, EXTERNAL_UINT8_ELEMENTS, \ |
79 ExternalInt8Array) \ | 81 ExternalUint8Array) \ |
80 V(ExternalUint8ElementsAccessor, \ | 82 V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \ |
81 EXTERNAL_UINT8_ELEMENTS, ExternalUint8Array) \ | 83 ExternalInt16Array) \ |
82 V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \ | 84 V(ExternalUint16ElementsAccessor, EXTERNAL_UINT16_ELEMENTS, \ |
83 ExternalInt16Array) \ | 85 ExternalUint16Array) \ |
84 V(ExternalUint16ElementsAccessor, \ | 86 V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \ |
85 EXTERNAL_UINT16_ELEMENTS, ExternalUint16Array) \ | 87 ExternalInt32Array) \ |
86 V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \ | 88 V(ExternalUint32ElementsAccessor, EXTERNAL_UINT32_ELEMENTS, \ |
87 ExternalInt32Array) \ | 89 ExternalUint32Array) \ |
88 V(ExternalUint32ElementsAccessor, \ | 90 V(ExternalFloat32ElementsAccessor, EXTERNAL_FLOAT32_ELEMENTS, \ |
89 EXTERNAL_UINT32_ELEMENTS, ExternalUint32Array) \ | 91 ExternalFloat32Array) \ |
90 V(ExternalFloat32ElementsAccessor, \ | 92 V(ExternalFloat64ElementsAccessor, EXTERNAL_FLOAT64_ELEMENTS, \ |
91 EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array) \ | 93 ExternalFloat64Array) \ |
92 V(ExternalFloat64ElementsAccessor, \ | 94 V(ExternalUint8ClampedElementsAccessor, EXTERNAL_UINT8_CLAMPED_ELEMENTS, \ |
93 EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array) \ | 95 ExternalUint8ClampedArray) \ |
94 V(ExternalUint8ClampedElementsAccessor, \ | 96 V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \ |
95 EXTERNAL_UINT8_CLAMPED_ELEMENTS, \ | 97 V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \ |
96 ExternalUint8ClampedArray) \ | 98 V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \ |
97 V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \ | 99 V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \ |
98 V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \ | 100 V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \ |
99 V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \ | 101 V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \ |
100 V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \ | 102 V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \ |
101 V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \ | 103 V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \ |
102 V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \ | 104 V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \ |
103 V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \ | |
104 V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \ | |
105 V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \ | |
106 FixedUint8ClampedArray) | 105 FixedUint8ClampedArray) |
107 | 106 |
108 | 107 |
109 template<ElementsKind Kind> class ElementsKindTraits { | 108 template<ElementsKind Kind> class ElementsKindTraits { |
110 public: | 109 public: |
111 typedef FixedArrayBase BackingStore; | 110 typedef FixedArrayBase BackingStore; |
112 }; | 111 }; |
113 | 112 |
114 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ | 113 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ |
115 template<> class ElementsKindTraits<KindParam> { \ | 114 template<> class ElementsKindTraits<KindParam> { \ |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 // } | 542 // } |
544 // | 543 // |
545 // This is an example of the Curiously Recurring Template Pattern (see | 544 // This is an example of the Curiously Recurring Template Pattern (see |
546 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use | 545 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
547 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and | 546 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
548 // specialization of SomeElementsAccessor methods). | 547 // specialization of SomeElementsAccessor methods). |
549 template <typename ElementsAccessorSubclass, | 548 template <typename ElementsAccessorSubclass, |
550 typename ElementsTraitsParam> | 549 typename ElementsTraitsParam> |
551 class ElementsAccessorBase : public ElementsAccessor { | 550 class ElementsAccessorBase : public ElementsAccessor { |
552 protected: | 551 protected: |
| 552 template <typename SloppyArgumentsElementsAccessorSubclass, |
| 553 typename ArgumentsAccessor, typename KindTraits> |
| 554 friend class SloppyArgumentsElementsAccessor; |
553 explicit ElementsAccessorBase(const char* name) | 555 explicit ElementsAccessorBase(const char* name) |
554 : ElementsAccessor(name) { } | 556 : ElementsAccessor(name) { } |
555 | 557 |
556 typedef ElementsTraitsParam ElementsTraits; | 558 typedef ElementsTraitsParam ElementsTraits; |
557 typedef typename ElementsTraitsParam::BackingStore BackingStore; | 559 typedef typename ElementsTraitsParam::BackingStore BackingStore; |
558 | 560 |
559 static ElementsKind kind() { return ElementsTraits::Kind; } | 561 static ElementsKind kind() { return ElementsTraits::Kind; } |
560 | 562 |
561 static void ValidateContents(Handle<JSObject> holder, int length) { | 563 static void ValidateContents(Handle<JSObject> holder, int length) { |
562 } | 564 } |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, | 917 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, |
916 uint32_t index) final { | 918 uint32_t index) final { |
917 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); | 919 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); |
918 } | 920 } |
919 | 921 |
920 private: | 922 private: |
921 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 923 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
922 }; | 924 }; |
923 | 925 |
924 | 926 |
| 927 class FastSloppyArgumentsElementsAccessor; |
| 928 class FastHoleyObjectElementsAccessor; |
| 929 template <typename SloppyArgumentsElementsAccessorSubclass, |
| 930 typename ArgumentsAccessor, typename KindTraits> |
| 931 class SloppyArgumentsElementsAccessor; |
| 932 |
925 // Super class for all fast element arrays. | 933 // Super class for all fast element arrays. |
926 template<typename FastElementsAccessorSubclass, | 934 template<typename FastElementsAccessorSubclass, |
927 typename KindTraits> | 935 typename KindTraits> |
928 class FastElementsAccessor | 936 class FastElementsAccessor |
929 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 937 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
930 public: | 938 public: |
931 explicit FastElementsAccessor(const char* name) | 939 explicit FastElementsAccessor(const char* name) |
932 : ElementsAccessorBase<FastElementsAccessorSubclass, | 940 : ElementsAccessorBase<FastElementsAccessorSubclass, |
933 KindTraits>(name) {} | 941 KindTraits>(name) {} |
934 | 942 |
935 protected: | 943 protected: |
936 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 944 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
937 friend class SloppyArgumentsElementsAccessor; | 945 friend class SloppyArgumentsElementsAccessor< |
| 946 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| 947 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; |
938 | 948 |
939 typedef typename KindTraits::BackingStore BackingStore; | 949 typedef typename KindTraits::BackingStore BackingStore; |
940 | 950 |
941 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 951 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
942 LanguageMode language_mode) { | 952 LanguageMode language_mode) { |
943 DCHECK(obj->HasFastSmiOrObjectElements() || | 953 DCHECK(obj->HasFastSmiOrObjectElements() || |
944 obj->HasFastDoubleElements() || | 954 obj->HasFastDoubleElements() || |
945 obj->HasFastArgumentsElements()); | 955 obj->HasFastArgumentsElements()); |
946 Isolate* isolate = obj->GetIsolate(); | 956 Isolate* isolate = obj->GetIsolate(); |
947 Heap* heap = obj->GetHeap(); | 957 Heap* heap = obj->GetHeap(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 DCHECK(BackingStore::get(backing_store, i)->IsSmi() || | 1069 DCHECK(BackingStore::get(backing_store, i)->IsSmi() || |
1060 (IsFastHoleyElementsKind(KindTraits::Kind) && | 1070 (IsFastHoleyElementsKind(KindTraits::Kind) && |
1061 backing_store->is_the_hole(i))); | 1071 backing_store->is_the_hole(i))); |
1062 } | 1072 } |
1063 } | 1073 } |
1064 #endif | 1074 #endif |
1065 } | 1075 } |
1066 }; | 1076 }; |
1067 | 1077 |
1068 | 1078 |
1069 static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) { | |
1070 switch (array->map()->instance_type()) { | |
1071 case FIXED_ARRAY_TYPE: | |
1072 if (array->IsDictionary()) { | |
1073 return DICTIONARY_ELEMENTS; | |
1074 } else { | |
1075 return FAST_HOLEY_ELEMENTS; | |
1076 } | |
1077 case FIXED_DOUBLE_ARRAY_TYPE: | |
1078 return FAST_HOLEY_DOUBLE_ELEMENTS; | |
1079 | |
1080 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
1081 case EXTERNAL_##TYPE##_ARRAY_TYPE: \ | |
1082 return EXTERNAL_##TYPE##_ELEMENTS; \ | |
1083 case FIXED_##TYPE##_ARRAY_TYPE: \ | |
1084 return TYPE##_ELEMENTS; | |
1085 | |
1086 TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
1087 #undef TYPED_ARRAY_CASE | |
1088 | |
1089 default: | |
1090 UNREACHABLE(); | |
1091 } | |
1092 return FAST_HOLEY_ELEMENTS; | |
1093 } | |
1094 | |
1095 | |
1096 template<typename FastElementsAccessorSubclass, | 1079 template<typename FastElementsAccessorSubclass, |
1097 typename KindTraits> | 1080 typename KindTraits> |
1098 class FastSmiOrObjectElementsAccessor | 1081 class FastSmiOrObjectElementsAccessor |
1099 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { | 1082 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { |
1100 public: | 1083 public: |
1101 explicit FastSmiOrObjectElementsAccessor(const char* name) | 1084 explicit FastSmiOrObjectElementsAccessor(const char* name) |
1102 : FastElementsAccessor<FastElementsAccessorSubclass, | 1085 : FastElementsAccessor<FastElementsAccessorSubclass, |
1103 KindTraits>(name) {} | 1086 KindTraits>(name) {} |
1104 | 1087 |
1105 // NOTE: this method violates the handlified function signature convention: | 1088 // NOTE: this method violates the handlified function signature convention: |
(...skipping 19 matching lines...) Expand all Loading... |
1125 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 1108 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
1126 AllowHeapAllocation allow_allocation; | 1109 AllowHeapAllocation allow_allocation; |
1127 CopyDoubleToObjectElements( | 1110 CopyDoubleToObjectElements( |
1128 from, from_start, to, to_kind, to_start, copy_size); | 1111 from, from_start, to, to_kind, to_start, copy_size); |
1129 break; | 1112 break; |
1130 } | 1113 } |
1131 case DICTIONARY_ELEMENTS: | 1114 case DICTIONARY_ELEMENTS: |
1132 CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start, | 1115 CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start, |
1133 copy_size); | 1116 copy_size); |
1134 break; | 1117 break; |
1135 case SLOPPY_ARGUMENTS_ELEMENTS: { | 1118 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
1136 // TODO(verwaest): This is a temporary hack to support extending | 1119 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
1137 // SLOPPY_ARGUMENTS_ELEMENTS in GrowCapacityAndConvert. | 1120 UNREACHABLE(); |
1138 // This case should be UNREACHABLE(). | |
1139 FixedArray* parameter_map = FixedArray::cast(from); | |
1140 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | |
1141 ElementsKind from_kind = ElementsKindForArray(arguments); | |
1142 CopyElementsImpl(arguments, from_start, to, from_kind, | |
1143 to_start, packed_size, copy_size); | |
1144 break; | |
1145 } | |
1146 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1121 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1147 case EXTERNAL_##TYPE##_ELEMENTS: \ | 1122 case EXTERNAL_##TYPE##_ELEMENTS: \ |
1148 case TYPE##_ELEMENTS: \ | 1123 case TYPE##_ELEMENTS: \ |
1149 UNREACHABLE(); | 1124 UNREACHABLE(); |
1150 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1125 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1151 #undef TYPED_ARRAY_CASE | 1126 #undef TYPED_ARRAY_CASE |
1152 } | 1127 } |
1153 } | 1128 } |
1154 }; | 1129 }; |
1155 | 1130 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); | 1205 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); |
1231 break; | 1206 break; |
1232 case FAST_ELEMENTS: | 1207 case FAST_ELEMENTS: |
1233 case FAST_HOLEY_ELEMENTS: | 1208 case FAST_HOLEY_ELEMENTS: |
1234 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); | 1209 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); |
1235 break; | 1210 break; |
1236 case DICTIONARY_ELEMENTS: | 1211 case DICTIONARY_ELEMENTS: |
1237 CopyDictionaryToDoubleElements(from, from_start, to, to_start, | 1212 CopyDictionaryToDoubleElements(from, from_start, to, to_start, |
1238 copy_size); | 1213 copy_size); |
1239 break; | 1214 break; |
1240 case SLOPPY_ARGUMENTS_ELEMENTS: | 1215 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 1216 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
1241 UNREACHABLE(); | 1217 UNREACHABLE(); |
1242 | 1218 |
1243 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1219 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1244 case EXTERNAL_##TYPE##_ELEMENTS: \ | 1220 case EXTERNAL_##TYPE##_ELEMENTS: \ |
1245 case TYPE##_ELEMENTS: \ | 1221 case TYPE##_ELEMENTS: \ |
1246 UNREACHABLE(); | 1222 UNREACHABLE(); |
1247 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1223 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1248 #undef TYPED_ARRAY_CASE | 1224 #undef TYPED_ARRAY_CASE |
1249 } | 1225 } |
1250 } | 1226 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 #undef EXTERNAL_ELEMENTS_ACCESSOR | 1324 #undef EXTERNAL_ELEMENTS_ACCESSOR |
1349 | 1325 |
1350 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | 1326 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
1351 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ | 1327 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ |
1352 Fixed##Type##ElementsAccessor; | 1328 Fixed##Type##ElementsAccessor; |
1353 | 1329 |
1354 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 1330 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
1355 #undef FIXED_ELEMENTS_ACCESSOR | 1331 #undef FIXED_ELEMENTS_ACCESSOR |
1356 | 1332 |
1357 | 1333 |
| 1334 class SlowSloppyArgumentsElementsAccessor; |
| 1335 |
1358 | 1336 |
1359 class DictionaryElementsAccessor | 1337 class DictionaryElementsAccessor |
1360 : public ElementsAccessorBase<DictionaryElementsAccessor, | 1338 : public ElementsAccessorBase<DictionaryElementsAccessor, |
1361 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 1339 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
1362 public: | 1340 public: |
1363 explicit DictionaryElementsAccessor(const char* name) | 1341 explicit DictionaryElementsAccessor(const char* name) |
1364 : ElementsAccessorBase<DictionaryElementsAccessor, | 1342 : ElementsAccessorBase<DictionaryElementsAccessor, |
1365 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 1343 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
1366 | 1344 |
1367 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1345 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1410 | 1388 |
1411 // Update the number of elements. | 1389 // Update the number of elements. |
1412 dict->ElementsRemoved(removed_entries); | 1390 dict->ElementsRemoved(removed_entries); |
1413 } | 1391 } |
1414 } | 1392 } |
1415 | 1393 |
1416 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); | 1394 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); |
1417 array->set_length(*length_obj); | 1395 array->set_length(*length_obj); |
1418 } | 1396 } |
1419 | 1397 |
| 1398 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1399 FixedArrayBase* to, ElementsKind from_kind, |
| 1400 uint32_t to_start, int packed_size, |
| 1401 int copy_size) { |
| 1402 UNREACHABLE(); |
| 1403 } |
| 1404 |
| 1405 |
| 1406 protected: |
| 1407 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
| 1408 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
| 1409 friend class SlowSloppyArgumentsElementsAccessor; |
| 1410 friend class SloppyArgumentsElementsAccessor< |
| 1411 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1412 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1413 |
1420 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 1414 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
1421 LanguageMode language_mode) { | 1415 LanguageMode language_mode) { |
1422 Isolate* isolate = obj->GetIsolate(); | 1416 Isolate* isolate = obj->GetIsolate(); |
1423 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), | 1417 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), |
1424 isolate); | 1418 isolate); |
1425 bool is_arguments = | 1419 bool is_arguments = obj->HasSloppyArgumentsElements(); |
1426 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); | |
1427 if (is_arguments) { | 1420 if (is_arguments) { |
1428 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); | 1421 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); |
1429 } | 1422 } |
1430 Handle<SeededNumberDictionary> dictionary = | 1423 Handle<SeededNumberDictionary> dictionary = |
1431 Handle<SeededNumberDictionary>::cast(backing_store); | 1424 Handle<SeededNumberDictionary>::cast(backing_store); |
1432 int entry = dictionary->FindEntry(key); | 1425 int entry = dictionary->FindEntry(key); |
1433 if (entry != SeededNumberDictionary::kNotFound) { | 1426 if (entry != SeededNumberDictionary::kNotFound) { |
1434 Handle<Object> result = | 1427 Handle<Object> result = |
1435 SeededNumberDictionary::DeleteProperty(dictionary, entry); | 1428 SeededNumberDictionary::DeleteProperty(dictionary, entry); |
1436 USE(result); | 1429 USE(result); |
1437 DCHECK(result->IsTrue()); | 1430 DCHECK(result->IsTrue()); |
1438 Handle<FixedArray> new_elements = | 1431 Handle<FixedArray> new_elements = |
1439 SeededNumberDictionary::Shrink(dictionary, key); | 1432 SeededNumberDictionary::Shrink(dictionary, key); |
1440 | 1433 |
1441 if (is_arguments) { | 1434 if (is_arguments) { |
1442 FixedArray::cast(obj->elements())->set(1, *new_elements); | 1435 FixedArray::cast(obj->elements())->set(1, *new_elements); |
1443 } else { | 1436 } else { |
1444 obj->set_elements(*new_elements); | 1437 obj->set_elements(*new_elements); |
1445 } | 1438 } |
1446 } | 1439 } |
1447 } | 1440 } |
1448 | 1441 |
1449 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | |
1450 FixedArrayBase* to, ElementsKind from_kind, | |
1451 uint32_t to_start, int packed_size, | |
1452 int copy_size) { | |
1453 UNREACHABLE(); | |
1454 } | |
1455 | |
1456 | |
1457 protected: | |
1458 friend class ElementsAccessorBase<DictionaryElementsAccessor, | |
1459 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | |
1460 | |
1461 virtual void Delete(Handle<JSObject> obj, uint32_t key, | 1442 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
1462 LanguageMode language_mode) final { | 1443 LanguageMode language_mode) final { |
1463 DeleteCommon(obj, key, language_mode); | 1444 DeleteCommon(obj, key, language_mode); |
1464 } | 1445 } |
1465 | 1446 |
1466 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1447 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
1467 Handle<FixedArrayBase> store) { | 1448 Handle<FixedArrayBase> store) { |
1468 Handle<SeededNumberDictionary> backing_store = | 1449 Handle<SeededNumberDictionary> backing_store = |
1469 Handle<SeededNumberDictionary>::cast(store); | 1450 Handle<SeededNumberDictionary>::cast(store); |
1470 Isolate* isolate = backing_store->GetIsolate(); | 1451 Isolate* isolate = backing_store->GetIsolate(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 : static_cast<uint32_t>(entry); | 1530 : static_cast<uint32_t>(entry); |
1550 } | 1531 } |
1551 | 1532 |
1552 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1533 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1553 uint32_t index) { | 1534 uint32_t index) { |
1554 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); | 1535 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); |
1555 } | 1536 } |
1556 }; | 1537 }; |
1557 | 1538 |
1558 | 1539 |
1559 class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< | 1540 template <typename SloppyArgumentsElementsAccessorSubclass, |
1560 SloppyArgumentsElementsAccessor, | 1541 typename ArgumentsAccessor, typename KindTraits> |
1561 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > { | 1542 class SloppyArgumentsElementsAccessor |
| 1543 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
| 1544 KindTraits> { |
1562 public: | 1545 public: |
1563 explicit SloppyArgumentsElementsAccessor(const char* name) | 1546 explicit SloppyArgumentsElementsAccessor(const char* name) |
1564 : ElementsAccessorBase< | 1547 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1565 SloppyArgumentsElementsAccessor, | 1548 KindTraits>(name) {} |
1566 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1549 |
1567 protected: | 1550 protected: |
1568 friend class ElementsAccessorBase< | 1551 friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1569 SloppyArgumentsElementsAccessor, | 1552 KindTraits>; |
1570 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1571 | 1553 |
1572 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1554 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
1573 Handle<FixedArrayBase> parameters) { | 1555 Handle<FixedArrayBase> parameters) { |
1574 Isolate* isolate = obj->GetIsolate(); | 1556 Isolate* isolate = obj->GetIsolate(); |
1575 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1557 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
1576 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1558 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
1577 if (!probe->IsTheHole()) { | 1559 if (!probe->IsTheHole()) { |
1578 DisallowHeapAllocation no_gc; | 1560 DisallowHeapAllocation no_gc; |
1579 Context* context = Context::cast(parameter_map->get(0)); | 1561 Context* context = Context::cast(parameter_map->get(0)); |
1580 int context_index = Handle<Smi>::cast(probe)->value(); | 1562 int context_index = Handle<Smi>::cast(probe)->value(); |
1581 DCHECK(!context->get(context_index)->IsTheHole()); | 1563 DCHECK(!context->get(context_index)->IsTheHole()); |
1582 return handle(context->get(context_index), isolate); | 1564 return handle(context->get(context_index), isolate); |
1583 } else { | 1565 } else { |
1584 // Object is not mapped, defer to the arguments. | 1566 // Object is not mapped, defer to the arguments. |
1585 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), | 1567 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), |
1586 isolate); | 1568 isolate); |
1587 Handle<Object> result = | 1569 Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments); |
1588 ElementsAccessor::ForArray(arguments)->Get(obj, key, arguments); | |
1589 // Elements of the arguments object in slow mode might be slow aliases. | 1570 // Elements of the arguments object in slow mode might be slow aliases. |
1590 if (result->IsAliasedArgumentsEntry()) { | 1571 if (result->IsAliasedArgumentsEntry()) { |
1591 DisallowHeapAllocation no_gc; | 1572 DisallowHeapAllocation no_gc; |
1592 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); | 1573 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); |
1593 Context* context = Context::cast(parameter_map->get(0)); | 1574 Context* context = Context::cast(parameter_map->get(0)); |
1594 int context_index = entry->aliased_context_slot(); | 1575 int context_index = entry->aliased_context_slot(); |
1595 DCHECK(!context->get(context_index)->IsTheHole()); | 1576 DCHECK(!context->get(context_index)->IsTheHole()); |
1596 return handle(context->get(context_index), isolate); | 1577 return handle(context->get(context_index), isolate); |
1597 } else { | 1578 } else { |
1598 return result; | 1579 return result; |
1599 } | 1580 } |
1600 } | 1581 } |
1601 } | 1582 } |
1602 | 1583 |
| 1584 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 1585 LanguageMode language_mode) final { |
| 1586 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| 1587 if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) { |
| 1588 // TODO(kmillikin): We could check if this was the last aliased |
| 1589 // parameter, and revert to normal elements in that case. That |
| 1590 // would enable GC of the context. |
| 1591 parameter_map->set_the_hole(key + 2); |
| 1592 } else { |
| 1593 ArgumentsAccessor::DeleteCommon(obj, key, language_mode); |
| 1594 } |
| 1595 } |
| 1596 |
1603 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 1597 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
1604 uint32_t capacity) { | 1598 uint32_t capacity) { |
1605 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1599 UNREACHABLE(); |
1606 Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1))); | |
1607 ElementsKind from_kind = old_elements->IsDictionary() ? DICTIONARY_ELEMENTS | |
1608 : FAST_HOLEY_ELEMENTS; | |
1609 // This method should only be called if there's a reason to update the | |
1610 // elements. | |
1611 DCHECK(IsDictionaryElementsKind(from_kind) || | |
1612 static_cast<uint32_t>(old_elements->length()) < capacity); | |
1613 Handle<FixedArrayBase> elements = | |
1614 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); | |
1615 parameter_map->set(1, *elements); | |
1616 JSObject::ValidateElements(object); | |
1617 } | 1600 } |
1618 | 1601 |
1619 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | 1602 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { |
1620 FixedArray* parameter_map = FixedArray::cast(store); | 1603 FixedArray* parameter_map = FixedArray::cast(store); |
1621 Object* probe = GetParameterMapArg(parameter_map, key); | 1604 Object* probe = GetParameterMapArg(parameter_map, key); |
1622 if (!probe->IsTheHole()) { | 1605 if (!probe->IsTheHole()) { |
1623 Context* context = Context::cast(parameter_map->get(0)); | 1606 Context* context = Context::cast(parameter_map->get(0)); |
1624 int context_index = Smi::cast(probe)->value(); | 1607 int context_index = Smi::cast(probe)->value(); |
1625 DCHECK(!context->get(context_index)->IsTheHole()); | 1608 DCHECK(!context->get(context_index)->IsTheHole()); |
1626 context->set(context_index, value); | 1609 context->set(context_index, value); |
1627 } else { | 1610 } else { |
1628 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1611 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1629 ElementsAccessor::ForArray(arguments)->Set(arguments, key, value); | 1612 ArgumentsAccessor::SetImpl(arguments, key, value); |
1630 } | 1613 } |
1631 } | 1614 } |
1632 | 1615 |
1633 static void ReconfigureImpl(Handle<JSObject> object, | |
1634 Handle<FixedArrayBase> store, uint32_t index, | |
1635 Handle<Object> value, | |
1636 PropertyAttributes attributes) { | |
1637 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); | |
1638 uint32_t length = parameter_map->length() - 2; | |
1639 if (index < length) { | |
1640 Object* probe = parameter_map->get(index + 2); | |
1641 DCHECK(!probe->IsTheHole()); | |
1642 Context* context = Context::cast(parameter_map->get(0)); | |
1643 int context_index = Smi::cast(probe)->value(); | |
1644 DCHECK(!context->get(context_index)->IsTheHole()); | |
1645 context->set(context_index, *value); | |
1646 | |
1647 // Redefining attributes of an aliased element destroys fast aliasing. | |
1648 parameter_map->set_the_hole(index + 2); | |
1649 // For elements that are still writable we re-establish slow aliasing. | |
1650 if ((attributes & READ_ONLY) == 0) { | |
1651 Isolate* isolate = store->GetIsolate(); | |
1652 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); | |
1653 } | |
1654 | |
1655 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
1656 Handle<SeededNumberDictionary> arguments = | |
1657 parameter_map->get(1)->IsSeededNumberDictionary() | |
1658 ? handle(SeededNumberDictionary::cast(parameter_map->get(1))) | |
1659 : JSObject::NormalizeElements(object); | |
1660 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, | |
1661 value, details); | |
1662 parameter_map->set(1, *arguments); | |
1663 } else { | |
1664 Handle<FixedArrayBase> arguments( | |
1665 FixedArrayBase::cast(parameter_map->get(1))); | |
1666 ElementsAccessor::ForArray(arguments) | |
1667 ->Reconfigure(object, arguments, index - length, value, attributes); | |
1668 } | |
1669 } | |
1670 | |
1671 static void AddImpl(Handle<JSObject> object, uint32_t key, | |
1672 Handle<Object> value, PropertyAttributes attributes, | |
1673 uint32_t new_capacity) { | |
1674 DCHECK_EQ(NONE, attributes); | |
1675 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | |
1676 Handle<FixedArrayBase> old_elements( | |
1677 FixedArrayBase::cast(parameter_map->get(1))); | |
1678 if (old_elements->IsSeededNumberDictionary() || | |
1679 static_cast<uint32_t>(old_elements->length()) < new_capacity) { | |
1680 GrowCapacityAndConvertImpl(object, new_capacity); | |
1681 } | |
1682 SetImpl(object->elements(), key, *value); | |
1683 } | |
1684 | |
1685 static MaybeHandle<AccessorPair> GetAccessorPairImpl( | 1616 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
1686 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { | 1617 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { |
1687 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1618 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
1688 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), | 1619 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), |
1689 obj->GetIsolate()); | 1620 obj->GetIsolate()); |
1690 if (!probe->IsTheHole()) { | 1621 if (!probe->IsTheHole()) { |
1691 return MaybeHandle<AccessorPair>(); | 1622 return MaybeHandle<AccessorPair>(); |
1692 } else { | 1623 } else { |
1693 // If not aliased, check the arguments. | 1624 // If not aliased, check the arguments. |
1694 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1625 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
1695 return ElementsAccessor::ForArray(arguments) | 1626 return ArgumentsAccessor::GetAccessorPairImpl(obj, key, arguments); |
1696 ->GetAccessorPair(obj, key, arguments); | |
1697 } | 1627 } |
1698 } | 1628 } |
1699 | 1629 |
1700 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1630 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1701 Handle<FixedArrayBase> parameter_map) { | 1631 Handle<FixedArrayBase> parameter_map) { |
1702 // Sloppy arguments objects are not arrays. | 1632 // Sloppy arguments objects are not arrays. |
1703 UNREACHABLE(); | 1633 UNREACHABLE(); |
1704 } | 1634 } |
1705 | 1635 |
1706 virtual void Delete(Handle<JSObject> obj, uint32_t key, | |
1707 LanguageMode language_mode) final { | |
1708 Isolate* isolate = obj->GetIsolate(); | |
1709 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); | |
1710 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | |
1711 if (!probe->IsTheHole()) { | |
1712 // TODO(kmillikin): We could check if this was the last aliased | |
1713 // parameter, and revert to normal elements in that case. That | |
1714 // would enable GC of the context. | |
1715 parameter_map->set_the_hole(key + 2); | |
1716 } else { | |
1717 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | |
1718 if (arguments->IsDictionary()) { | |
1719 DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode); | |
1720 } else { | |
1721 // It's difficult to access the version of DeleteCommon that is declared | |
1722 // in the templatized super class, call the concrete implementation in | |
1723 // the class for the most generalized ElementsKind subclass. | |
1724 FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); | |
1725 } | |
1726 } | |
1727 } | |
1728 | |
1729 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | |
1730 FixedArrayBase* to, ElementsKind from_kind, | |
1731 uint32_t to_start, int packed_size, | |
1732 int copy_size) { | |
1733 DCHECK(!to->IsDictionary()); | |
1734 if (from_kind == DICTIONARY_ELEMENTS) { | |
1735 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, | |
1736 to_start, copy_size); | |
1737 } else { | |
1738 DCHECK_EQ(FAST_HOLEY_ELEMENTS, from_kind); | |
1739 CopyObjectToObjectElements(from, from_kind, from_start, to, | |
1740 FAST_HOLEY_ELEMENTS, to_start, copy_size); | |
1741 } | |
1742 } | |
1743 | |
1744 static uint32_t GetCapacityImpl(JSObject* holder, | 1636 static uint32_t GetCapacityImpl(JSObject* holder, |
1745 FixedArrayBase* backing_store) { | 1637 FixedArrayBase* backing_store) { |
1746 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1638 FixedArray* parameter_map = FixedArray::cast(backing_store); |
1747 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1639 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1748 return parameter_map->length() - 2 + | 1640 return parameter_map->length() - 2 + |
1749 ForArray(arguments)->GetCapacity(holder, arguments); | 1641 ArgumentsAccessor::GetCapacityImpl(holder, arguments); |
1750 } | 1642 } |
1751 | 1643 |
1752 static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) { | 1644 static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) { |
1753 FixedArray* parameter_map = FixedArray::cast(parameters); | 1645 FixedArray* parameter_map = FixedArray::cast(parameters); |
1754 uint32_t length = parameter_map->length() - 2; | 1646 uint32_t length = parameter_map->length() - 2; |
1755 if (index < length) { | 1647 if (index < length) { |
1756 return !GetParameterMapArg(parameter_map, index)->IsTheHole(); | 1648 return !GetParameterMapArg(parameter_map, index)->IsTheHole(); |
1757 } | 1649 } |
1758 | 1650 |
1759 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1651 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1760 return ForArray(arguments)->HasIndex(arguments, index - length); | 1652 return ArgumentsAccessor::HasIndexImpl(arguments, index - length); |
1761 } | 1653 } |
1762 | 1654 |
1763 static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters, | 1655 static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters, |
1764 uint32_t index) { | 1656 uint32_t index) { |
1765 FixedArray* parameter_map = FixedArray::cast(parameters); | 1657 FixedArray* parameter_map = FixedArray::cast(parameters); |
1766 uint32_t length = parameter_map->length() - 2; | 1658 uint32_t length = parameter_map->length() - 2; |
1767 if (index < length) return index; | 1659 if (index < length) return index; |
1768 | 1660 |
1769 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1661 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1770 return ForArray(arguments)->GetKeyForIndex(arguments, index - length); | 1662 return ArgumentsAccessor::GetKeyForIndexImpl(arguments, index - length); |
1771 } | 1663 } |
1772 | 1664 |
1773 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 1665 static uint32_t GetIndexForKeyImpl(JSObject* holder, |
1774 FixedArrayBase* parameters, uint32_t key) { | 1666 FixedArrayBase* parameters, uint32_t key) { |
1775 FixedArray* parameter_map = FixedArray::cast(parameters); | 1667 FixedArray* parameter_map = FixedArray::cast(parameters); |
1776 Object* probe = GetParameterMapArg(parameter_map, key); | 1668 Object* probe = GetParameterMapArg(parameter_map, key); |
1777 if (!probe->IsTheHole()) return key; | 1669 if (!probe->IsTheHole()) return key; |
1778 | 1670 |
1779 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1671 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1780 uint32_t index = ElementsAccessor::ForArray(arguments) | 1672 uint32_t index = |
1781 ->GetIndexForKey(holder, arguments, key); | 1673 ArgumentsAccessor::GetIndexForKeyImpl(holder, arguments, key); |
1782 if (index == kMaxUInt32) return index; | 1674 if (index == kMaxUInt32) return index; |
1783 return (parameter_map->length() - 2) + index; | 1675 return (parameter_map->length() - 2) + index; |
1784 } | 1676 } |
1785 | 1677 |
1786 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, | 1678 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
1787 uint32_t index) { | 1679 uint32_t index) { |
1788 FixedArray* parameter_map = FixedArray::cast(parameters); | 1680 FixedArray* parameter_map = FixedArray::cast(parameters); |
1789 uint32_t length = parameter_map->length() - 2; | 1681 uint32_t length = parameter_map->length() - 2; |
1790 if (index < length) { | 1682 if (index < length) { |
1791 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1683 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
1792 } | 1684 } |
1793 index -= length; | 1685 index -= length; |
1794 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1686 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1795 return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index); | 1687 return ArgumentsAccessor::GetDetailsImpl(arguments, index); |
1796 } | 1688 } |
1797 | 1689 |
1798 private: | |
1799 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { | 1690 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { |
1800 uint32_t length = parameter_map->length() - 2; | 1691 uint32_t length = parameter_map->length() - 2; |
1801 return key < length | 1692 return key < length |
1802 ? parameter_map->get(key + 2) | 1693 ? parameter_map->get(key + 2) |
1803 : Object::cast(parameter_map->GetHeap()->the_hole_value()); | 1694 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
1804 } | 1695 } |
1805 }; | 1696 }; |
1806 | 1697 |
1807 | 1698 |
1808 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1699 class FastSloppyArgumentsElementsAccessor |
1809 return elements_accessors_[ElementsKindForArray(array)]; | 1700 : public SloppyArgumentsElementsAccessor< |
1810 } | 1701 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| 1702 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1703 public: |
| 1704 friend class SloppyArgumentsElementsAccessor< |
| 1705 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| 1706 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1707 friend class ElementsAccessorBase< |
| 1708 FastSloppyArgumentsElementsAccessor, |
| 1709 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1710 explicit FastSloppyArgumentsElementsAccessor(const char* name) |
| 1711 : SloppyArgumentsElementsAccessor< |
| 1712 FastSloppyArgumentsElementsAccessor, |
| 1713 FastHoleyObjectElementsAccessor, |
| 1714 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1715 |
| 1716 protected: |
| 1717 static void AddImpl(Handle<JSObject> object, uint32_t key, |
| 1718 Handle<Object> value, PropertyAttributes attributes, |
| 1719 uint32_t new_capacity) { |
| 1720 DCHECK_EQ(NONE, attributes); |
| 1721 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1722 Handle<FixedArrayBase> old_elements( |
| 1723 FixedArrayBase::cast(parameter_map->get(1))); |
| 1724 if (old_elements->IsSeededNumberDictionary() || |
| 1725 static_cast<uint32_t>(old_elements->length()) < new_capacity) { |
| 1726 GrowCapacityAndConvertImpl(object, new_capacity); |
| 1727 } |
| 1728 SetImpl(object->elements(), key, *value); |
| 1729 } |
| 1730 |
| 1731 static void ReconfigureImpl(Handle<JSObject> object, |
| 1732 Handle<FixedArrayBase> store, uint32_t index, |
| 1733 Handle<Object> value, |
| 1734 PropertyAttributes attributes) { |
| 1735 Handle<SeededNumberDictionary> dictionary = |
| 1736 JSObject::NormalizeElements(object); |
| 1737 FixedArray::cast(*store)->set(1, *dictionary); |
| 1738 uint32_t length = static_cast<uint32_t>(store->length()) - 2; |
| 1739 if (index >= length) { |
| 1740 index = dictionary->FindEntry(index - length) + length; |
| 1741 } |
| 1742 object->GetElementsAccessor()->Reconfigure(object, store, index, value, |
| 1743 attributes); |
| 1744 } |
| 1745 |
| 1746 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1747 FixedArrayBase* to, ElementsKind from_kind, |
| 1748 uint32_t to_start, int packed_size, |
| 1749 int copy_size) { |
| 1750 DCHECK(!to->IsDictionary()); |
| 1751 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { |
| 1752 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, |
| 1753 to_start, copy_size); |
| 1754 } else { |
| 1755 DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, from_kind); |
| 1756 CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to, |
| 1757 FAST_HOLEY_ELEMENTS, to_start, copy_size); |
| 1758 } |
| 1759 } |
| 1760 |
| 1761 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
| 1762 uint32_t capacity) { |
| 1763 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1764 Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1))); |
| 1765 ElementsKind from_kind = object->GetElementsKind(); |
| 1766 // This method should only be called if there's a reason to update the |
| 1767 // elements. |
| 1768 DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS || |
| 1769 static_cast<uint32_t>(old_elements->length()) < capacity); |
| 1770 Handle<FixedArrayBase> elements = |
| 1771 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
| 1772 Handle<Map> new_map = JSObject::GetElementsTransitionMap( |
| 1773 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); |
| 1774 JSObject::MigrateToMap(object, new_map); |
| 1775 parameter_map->set(1, *elements); |
| 1776 JSObject::ValidateElements(object); |
| 1777 } |
| 1778 }; |
1811 | 1779 |
1812 | 1780 |
1813 ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) { | 1781 class SlowSloppyArgumentsElementsAccessor |
1814 return ForArray(*array); | 1782 : public SloppyArgumentsElementsAccessor< |
1815 } | 1783 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1784 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1785 public: |
| 1786 friend class ElementsAccessorBase< |
| 1787 SlowSloppyArgumentsElementsAccessor, |
| 1788 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1789 friend class SloppyArgumentsElementsAccessor< |
| 1790 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1791 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1792 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
| 1793 : SloppyArgumentsElementsAccessor< |
| 1794 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1795 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1796 |
| 1797 protected: |
| 1798 static void AddImpl(Handle<JSObject> object, uint32_t key, |
| 1799 Handle<Object> value, PropertyAttributes attributes, |
| 1800 uint32_t new_capacity) { |
| 1801 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1802 Handle<FixedArrayBase> old_elements( |
| 1803 FixedArrayBase::cast(parameter_map->get(1))); |
| 1804 Handle<SeededNumberDictionary> dictionary = |
| 1805 old_elements->IsSeededNumberDictionary() |
| 1806 ? Handle<SeededNumberDictionary>::cast(old_elements) |
| 1807 : JSObject::NormalizeElements(object); |
| 1808 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1809 Handle<SeededNumberDictionary> new_dictionary = |
| 1810 SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details); |
| 1811 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
| 1812 if (*dictionary != *new_dictionary) { |
| 1813 FixedArray::cast(object->elements())->set(1, *new_dictionary); |
| 1814 } |
| 1815 } |
| 1816 |
| 1817 static void ReconfigureImpl(Handle<JSObject> object, |
| 1818 Handle<FixedArrayBase> store, uint32_t index, |
| 1819 Handle<Object> value, |
| 1820 PropertyAttributes attributes) { |
| 1821 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); |
| 1822 uint32_t length = parameter_map->length() - 2; |
| 1823 if (index < length) { |
| 1824 Object* probe = parameter_map->get(index + 2); |
| 1825 DCHECK(!probe->IsTheHole()); |
| 1826 Context* context = Context::cast(parameter_map->get(0)); |
| 1827 int context_index = Smi::cast(probe)->value(); |
| 1828 DCHECK(!context->get(context_index)->IsTheHole()); |
| 1829 context->set(context_index, *value); |
| 1830 |
| 1831 // Redefining attributes of an aliased element destroys fast aliasing. |
| 1832 parameter_map->set_the_hole(index + 2); |
| 1833 // For elements that are still writable we re-establish slow aliasing. |
| 1834 if ((attributes & READ_ONLY) == 0) { |
| 1835 Isolate* isolate = store->GetIsolate(); |
| 1836 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); |
| 1837 } |
| 1838 |
| 1839 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1840 Handle<SeededNumberDictionary> arguments( |
| 1841 SeededNumberDictionary::cast(parameter_map->get(1))); |
| 1842 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, |
| 1843 value, details); |
| 1844 parameter_map->set(1, *arguments); |
| 1845 } else { |
| 1846 Handle<FixedArrayBase> arguments( |
| 1847 FixedArrayBase::cast(parameter_map->get(1))); |
| 1848 DictionaryElementsAccessor::ReconfigureImpl( |
| 1849 object, arguments, index - length, value, attributes); |
| 1850 } |
| 1851 } |
| 1852 }; |
1816 | 1853 |
1817 | 1854 |
1818 void ElementsAccessor::InitializeOncePerProcess() { | 1855 void ElementsAccessor::InitializeOncePerProcess() { |
1819 static ElementsAccessor* accessor_array[] = { | 1856 static ElementsAccessor* accessor_array[] = { |
1820 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), | 1857 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), |
1821 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1858 ELEMENTS_LIST(ACCESSOR_ARRAY) |
1822 #undef ACCESSOR_ARRAY | 1859 #undef ACCESSOR_ARRAY |
1823 }; | 1860 }; |
1824 | 1861 |
1825 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 1862 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 break; | 2006 break; |
1970 } | 2007 } |
1971 | 2008 |
1972 array->set_elements(*elms); | 2009 array->set_elements(*elms); |
1973 array->set_length(Smi::FromInt(number_of_elements)); | 2010 array->set_length(Smi::FromInt(number_of_elements)); |
1974 return array; | 2011 return array; |
1975 } | 2012 } |
1976 | 2013 |
1977 } // namespace internal | 2014 } // namespace internal |
1978 } // namespace v8 | 2015 } // namespace v8 |
OLD | NEW |