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 friend class SloppyArgumentsElementsAccessor< | |
553 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | |
554 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
927 typename KindTraits> | 929 typename KindTraits> |
928 class FastElementsAccessor | 930 class FastElementsAccessor |
929 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 931 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
930 public: | 932 public: |
931 explicit FastElementsAccessor(const char* name) | 933 explicit FastElementsAccessor(const char* name) |
932 : ElementsAccessorBase<FastElementsAccessorSubclass, | 934 : ElementsAccessorBase<FastElementsAccessorSubclass, |
933 KindTraits>(name) {} | 935 KindTraits>(name) {} |
934 | 936 |
935 protected: | 937 protected: |
936 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 938 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
937 friend class SloppyArgumentsElementsAccessor; | 939 friend class FastSloppyArgumentsElementsAccessor; |
940 friend class SloppyArgumentsElementsAccessor< | |
941 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | |
942 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
938 | 943 |
939 typedef typename KindTraits::BackingStore BackingStore; | 944 typedef typename KindTraits::BackingStore BackingStore; |
940 | 945 |
941 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 946 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
942 LanguageMode language_mode) { | 947 LanguageMode language_mode) { |
943 DCHECK(obj->HasFastSmiOrObjectElements() || | 948 DCHECK(obj->HasFastSmiOrObjectElements() || |
944 obj->HasFastDoubleElements() || | 949 obj->HasFastDoubleElements() || |
945 obj->HasFastArgumentsElements()); | 950 obj->HasFastArgumentsElements()); |
946 Isolate* isolate = obj->GetIsolate(); | 951 Isolate* isolate = obj->GetIsolate(); |
947 Heap* heap = obj->GetHeap(); | 952 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() || | 1064 DCHECK(BackingStore::get(backing_store, i)->IsSmi() || |
1060 (IsFastHoleyElementsKind(KindTraits::Kind) && | 1065 (IsFastHoleyElementsKind(KindTraits::Kind) && |
1061 backing_store->is_the_hole(i))); | 1066 backing_store->is_the_hole(i))); |
1062 } | 1067 } |
1063 } | 1068 } |
1064 #endif | 1069 #endif |
1065 } | 1070 } |
1066 }; | 1071 }; |
1067 | 1072 |
1068 | 1073 |
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, | 1074 template<typename FastElementsAccessorSubclass, |
1097 typename KindTraits> | 1075 typename KindTraits> |
1098 class FastSmiOrObjectElementsAccessor | 1076 class FastSmiOrObjectElementsAccessor |
1099 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { | 1077 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { |
1100 public: | 1078 public: |
1101 explicit FastSmiOrObjectElementsAccessor(const char* name) | 1079 explicit FastSmiOrObjectElementsAccessor(const char* name) |
1102 : FastElementsAccessor<FastElementsAccessorSubclass, | 1080 : FastElementsAccessor<FastElementsAccessorSubclass, |
1103 KindTraits>(name) {} | 1081 KindTraits>(name) {} |
1104 | 1082 |
1105 // NOTE: this method violates the handlified function signature convention: | 1083 // NOTE: this method violates the handlified function signature convention: |
(...skipping 19 matching lines...) Expand all Loading... | |
1125 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 1103 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
1126 AllowHeapAllocation allow_allocation; | 1104 AllowHeapAllocation allow_allocation; |
1127 CopyDoubleToObjectElements( | 1105 CopyDoubleToObjectElements( |
1128 from, from_start, to, to_kind, to_start, copy_size); | 1106 from, from_start, to, to_kind, to_start, copy_size); |
1129 break; | 1107 break; |
1130 } | 1108 } |
1131 case DICTIONARY_ELEMENTS: | 1109 case DICTIONARY_ELEMENTS: |
1132 CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start, | 1110 CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start, |
1133 copy_size); | 1111 copy_size); |
1134 break; | 1112 break; |
1135 case SLOPPY_ARGUMENTS_ELEMENTS: { | 1113 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
1136 // TODO(verwaest): This is a temporary hack to support extending | 1114 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
1137 // SLOPPY_ARGUMENTS_ELEMENTS in GrowCapacityAndConvert. | 1115 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) \ | 1116 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1147 case EXTERNAL_##TYPE##_ELEMENTS: \ | 1117 case EXTERNAL_##TYPE##_ELEMENTS: \ |
1148 case TYPE##_ELEMENTS: \ | 1118 case TYPE##_ELEMENTS: \ |
1149 UNREACHABLE(); | 1119 UNREACHABLE(); |
1150 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1120 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1151 #undef TYPED_ARRAY_CASE | 1121 #undef TYPED_ARRAY_CASE |
1152 } | 1122 } |
1153 } | 1123 } |
1154 }; | 1124 }; |
1155 | 1125 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1230 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); | 1200 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); |
1231 break; | 1201 break; |
1232 case FAST_ELEMENTS: | 1202 case FAST_ELEMENTS: |
1233 case FAST_HOLEY_ELEMENTS: | 1203 case FAST_HOLEY_ELEMENTS: |
1234 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); | 1204 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); |
1235 break; | 1205 break; |
1236 case DICTIONARY_ELEMENTS: | 1206 case DICTIONARY_ELEMENTS: |
1237 CopyDictionaryToDoubleElements(from, from_start, to, to_start, | 1207 CopyDictionaryToDoubleElements(from, from_start, to, to_start, |
1238 copy_size); | 1208 copy_size); |
1239 break; | 1209 break; |
1240 case SLOPPY_ARGUMENTS_ELEMENTS: | 1210 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
1211 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: | |
1241 UNREACHABLE(); | 1212 UNREACHABLE(); |
1242 | 1213 |
1243 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1214 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1244 case EXTERNAL_##TYPE##_ELEMENTS: \ | 1215 case EXTERNAL_##TYPE##_ELEMENTS: \ |
1245 case TYPE##_ELEMENTS: \ | 1216 case TYPE##_ELEMENTS: \ |
1246 UNREACHABLE(); | 1217 UNREACHABLE(); |
1247 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1218 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1248 #undef TYPED_ARRAY_CASE | 1219 #undef TYPED_ARRAY_CASE |
1249 } | 1220 } |
1250 } | 1221 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1410 | 1381 |
1411 // Update the number of elements. | 1382 // Update the number of elements. |
1412 dict->ElementsRemoved(removed_entries); | 1383 dict->ElementsRemoved(removed_entries); |
1413 } | 1384 } |
1414 } | 1385 } |
1415 | 1386 |
1416 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); | 1387 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); |
1417 array->set_length(*length_obj); | 1388 array->set_length(*length_obj); |
1418 } | 1389 } |
1419 | 1390 |
1391 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | |
1392 FixedArrayBase* to, ElementsKind from_kind, | |
1393 uint32_t to_start, int packed_size, | |
1394 int copy_size) { | |
1395 UNREACHABLE(); | |
1396 } | |
1397 | |
1398 | |
1399 protected: | |
1400 friend class ElementsAccessorBase<DictionaryElementsAccessor, | |
1401 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | |
1402 friend class SlowSloppyArgumentsElementsAccessor; | |
1403 friend class SloppyArgumentsElementsAccessor< | |
1404 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
1405 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1406 | |
1420 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 1407 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
1421 LanguageMode language_mode) { | 1408 LanguageMode language_mode) { |
1422 Isolate* isolate = obj->GetIsolate(); | 1409 Isolate* isolate = obj->GetIsolate(); |
1423 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), | 1410 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), |
1424 isolate); | 1411 isolate); |
1425 bool is_arguments = | 1412 bool is_arguments = obj->HasSloppyArgumentsElements(); |
1426 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); | |
1427 if (is_arguments) { | 1413 if (is_arguments) { |
1428 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); | 1414 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); |
1429 } | 1415 } |
1430 Handle<SeededNumberDictionary> dictionary = | 1416 Handle<SeededNumberDictionary> dictionary = |
1431 Handle<SeededNumberDictionary>::cast(backing_store); | 1417 Handle<SeededNumberDictionary>::cast(backing_store); |
1432 int entry = dictionary->FindEntry(key); | 1418 int entry = dictionary->FindEntry(key); |
1433 if (entry != SeededNumberDictionary::kNotFound) { | 1419 if (entry != SeededNumberDictionary::kNotFound) { |
1434 Handle<Object> result = | 1420 Handle<Object> result = |
1435 SeededNumberDictionary::DeleteProperty(dictionary, entry); | 1421 SeededNumberDictionary::DeleteProperty(dictionary, entry); |
1436 USE(result); | 1422 USE(result); |
1437 DCHECK(result->IsTrue()); | 1423 DCHECK(result->IsTrue()); |
1438 Handle<FixedArray> new_elements = | 1424 Handle<FixedArray> new_elements = |
1439 SeededNumberDictionary::Shrink(dictionary, key); | 1425 SeededNumberDictionary::Shrink(dictionary, key); |
1440 | 1426 |
1441 if (is_arguments) { | 1427 if (is_arguments) { |
1442 FixedArray::cast(obj->elements())->set(1, *new_elements); | 1428 FixedArray::cast(obj->elements())->set(1, *new_elements); |
1443 } else { | 1429 } else { |
1444 obj->set_elements(*new_elements); | 1430 obj->set_elements(*new_elements); |
1445 } | 1431 } |
1446 } | 1432 } |
1447 } | 1433 } |
1448 | 1434 |
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, | 1435 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
1462 LanguageMode language_mode) final { | 1436 LanguageMode language_mode) final { |
1463 DeleteCommon(obj, key, language_mode); | 1437 DeleteCommon(obj, key, language_mode); |
1464 } | 1438 } |
1465 | 1439 |
1466 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1440 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
1467 Handle<FixedArrayBase> store) { | 1441 Handle<FixedArrayBase> store) { |
1468 Handle<SeededNumberDictionary> backing_store = | 1442 Handle<SeededNumberDictionary> backing_store = |
1469 Handle<SeededNumberDictionary>::cast(store); | 1443 Handle<SeededNumberDictionary>::cast(store); |
1470 Isolate* isolate = backing_store->GetIsolate(); | 1444 Isolate* isolate = backing_store->GetIsolate(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1549 : static_cast<uint32_t>(entry); | 1523 : static_cast<uint32_t>(entry); |
1550 } | 1524 } |
1551 | 1525 |
1552 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1526 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1553 uint32_t index) { | 1527 uint32_t index) { |
1554 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); | 1528 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); |
1555 } | 1529 } |
1556 }; | 1530 }; |
1557 | 1531 |
1558 | 1532 |
1559 class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< | 1533 template <typename SloppyArgumentsElementsAccessorSubclass, |
1560 SloppyArgumentsElementsAccessor, | 1534 typename ArgumentsAccessor, typename KindTraits> |
1561 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > { | 1535 class SloppyArgumentsElementsAccessor |
1536 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | |
1537 KindTraits> { | |
1562 public: | 1538 public: |
1563 explicit SloppyArgumentsElementsAccessor(const char* name) | 1539 explicit SloppyArgumentsElementsAccessor(const char* name) |
1564 : ElementsAccessorBase< | 1540 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1565 SloppyArgumentsElementsAccessor, | 1541 KindTraits>(name) {} |
1566 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1542 |
1567 protected: | 1543 protected: |
1568 friend class ElementsAccessorBase< | 1544 friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
1569 SloppyArgumentsElementsAccessor, | 1545 KindTraits>; |
1570 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1571 | 1546 |
1572 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1547 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
1573 Handle<FixedArrayBase> parameters) { | 1548 Handle<FixedArrayBase> parameters) { |
1574 Isolate* isolate = obj->GetIsolate(); | 1549 Isolate* isolate = obj->GetIsolate(); |
1575 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1550 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
1576 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1551 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
1577 if (!probe->IsTheHole()) { | 1552 if (!probe->IsTheHole()) { |
1578 DisallowHeapAllocation no_gc; | 1553 DisallowHeapAllocation no_gc; |
1579 Context* context = Context::cast(parameter_map->get(0)); | 1554 Context* context = Context::cast(parameter_map->get(0)); |
1580 int context_index = Handle<Smi>::cast(probe)->value(); | 1555 int context_index = Handle<Smi>::cast(probe)->value(); |
1581 DCHECK(!context->get(context_index)->IsTheHole()); | 1556 DCHECK(!context->get(context_index)->IsTheHole()); |
1582 return handle(context->get(context_index), isolate); | 1557 return handle(context->get(context_index), isolate); |
1583 } else { | 1558 } else { |
1584 // Object is not mapped, defer to the arguments. | 1559 // Object is not mapped, defer to the arguments. |
1585 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), | 1560 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), |
1586 isolate); | 1561 isolate); |
1587 Handle<Object> result = | 1562 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. | 1563 // Elements of the arguments object in slow mode might be slow aliases. |
1590 if (result->IsAliasedArgumentsEntry()) { | 1564 if (result->IsAliasedArgumentsEntry()) { |
1591 DisallowHeapAllocation no_gc; | 1565 DisallowHeapAllocation no_gc; |
1592 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); | 1566 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); |
1593 Context* context = Context::cast(parameter_map->get(0)); | 1567 Context* context = Context::cast(parameter_map->get(0)); |
1594 int context_index = entry->aliased_context_slot(); | 1568 int context_index = entry->aliased_context_slot(); |
1595 DCHECK(!context->get(context_index)->IsTheHole()); | 1569 DCHECK(!context->get(context_index)->IsTheHole()); |
1596 return handle(context->get(context_index), isolate); | 1570 return handle(context->get(context_index), isolate); |
1597 } else { | 1571 } else { |
1598 return result; | 1572 return result; |
1599 } | 1573 } |
1600 } | 1574 } |
1601 } | 1575 } |
1602 | 1576 |
1603 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 1577 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
1604 uint32_t capacity) { | 1578 uint32_t capacity) { |
1605 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1579 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 } | 1580 } |
1618 | 1581 |
1619 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | 1582 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { |
1620 FixedArray* parameter_map = FixedArray::cast(store); | 1583 FixedArray* parameter_map = FixedArray::cast(store); |
1621 Object* probe = GetParameterMapArg(parameter_map, key); | 1584 Object* probe = GetParameterMapArg(parameter_map, key); |
1622 if (!probe->IsTheHole()) { | 1585 if (!probe->IsTheHole()) { |
1623 Context* context = Context::cast(parameter_map->get(0)); | 1586 Context* context = Context::cast(parameter_map->get(0)); |
1624 int context_index = Smi::cast(probe)->value(); | 1587 int context_index = Smi::cast(probe)->value(); |
1625 DCHECK(!context->get(context_index)->IsTheHole()); | 1588 DCHECK(!context->get(context_index)->IsTheHole()); |
1626 context->set(context_index, value); | 1589 context->set(context_index, value); |
1627 } else { | 1590 } else { |
1628 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1591 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1629 ElementsAccessor::ForArray(arguments)->Set(arguments, key, value); | 1592 ArgumentsAccessor::SetImpl(arguments, key, value); |
1630 } | 1593 } |
1631 } | 1594 } |
1632 | 1595 |
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( | 1596 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
1686 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { | 1597 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { |
1687 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1598 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
1688 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), | 1599 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), |
1689 obj->GetIsolate()); | 1600 obj->GetIsolate()); |
1690 if (!probe->IsTheHole()) { | 1601 if (!probe->IsTheHole()) { |
1691 return MaybeHandle<AccessorPair>(); | 1602 return MaybeHandle<AccessorPair>(); |
1692 } else { | 1603 } else { |
1693 // If not aliased, check the arguments. | 1604 // If not aliased, check the arguments. |
1694 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1605 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
1695 return ElementsAccessor::ForArray(arguments) | 1606 return ArgumentsAccessor::GetAccessorPairImpl(obj, key, arguments); |
1696 ->GetAccessorPair(obj, key, arguments); | |
1697 } | 1607 } |
1698 } | 1608 } |
1699 | 1609 |
1700 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1610 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1701 Handle<FixedArrayBase> parameter_map) { | 1611 Handle<FixedArrayBase> parameter_map) { |
1702 // Sloppy arguments objects are not arrays. | 1612 // Sloppy arguments objects are not arrays. |
1703 UNREACHABLE(); | 1613 UNREACHABLE(); |
1704 } | 1614 } |
1705 | 1615 |
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, | 1616 static uint32_t GetCapacityImpl(JSObject* holder, |
1745 FixedArrayBase* backing_store) { | 1617 FixedArrayBase* backing_store) { |
1746 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1618 FixedArray* parameter_map = FixedArray::cast(backing_store); |
1747 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1619 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1748 return parameter_map->length() - 2 + | 1620 return parameter_map->length() - 2 + |
1749 ForArray(arguments)->GetCapacity(holder, arguments); | 1621 ArgumentsAccessor::GetCapacityImpl(holder, arguments); |
1750 } | 1622 } |
1751 | 1623 |
1752 static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) { | 1624 static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) { |
1753 FixedArray* parameter_map = FixedArray::cast(parameters); | 1625 FixedArray* parameter_map = FixedArray::cast(parameters); |
1754 uint32_t length = parameter_map->length() - 2; | 1626 uint32_t length = parameter_map->length() - 2; |
1755 if (index < length) { | 1627 if (index < length) { |
1756 return !GetParameterMapArg(parameter_map, index)->IsTheHole(); | 1628 return !GetParameterMapArg(parameter_map, index)->IsTheHole(); |
1757 } | 1629 } |
1758 | 1630 |
1759 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1631 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1760 return ForArray(arguments)->HasIndex(arguments, index - length); | 1632 return ArgumentsAccessor::HasIndexImpl(arguments, index - length); |
1761 } | 1633 } |
1762 | 1634 |
1763 static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters, | 1635 static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters, |
1764 uint32_t index) { | 1636 uint32_t index) { |
1765 FixedArray* parameter_map = FixedArray::cast(parameters); | 1637 FixedArray* parameter_map = FixedArray::cast(parameters); |
1766 uint32_t length = parameter_map->length() - 2; | 1638 uint32_t length = parameter_map->length() - 2; |
1767 if (index < length) return index; | 1639 if (index < length) return index; |
1768 | 1640 |
1769 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1641 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1770 return ForArray(arguments)->GetKeyForIndex(arguments, index - length); | 1642 return ArgumentsAccessor::GetKeyForIndexImpl(arguments, index - length); |
1771 } | 1643 } |
1772 | 1644 |
1773 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 1645 static uint32_t GetIndexForKeyImpl(JSObject* holder, |
1774 FixedArrayBase* parameters, uint32_t key) { | 1646 FixedArrayBase* parameters, uint32_t key) { |
1775 FixedArray* parameter_map = FixedArray::cast(parameters); | 1647 FixedArray* parameter_map = FixedArray::cast(parameters); |
1776 Object* probe = GetParameterMapArg(parameter_map, key); | 1648 Object* probe = GetParameterMapArg(parameter_map, key); |
1777 if (!probe->IsTheHole()) return key; | 1649 if (!probe->IsTheHole()) return key; |
1778 | 1650 |
1779 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1651 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1780 uint32_t index = ElementsAccessor::ForArray(arguments) | 1652 uint32_t index = |
1781 ->GetIndexForKey(holder, arguments, key); | 1653 ArgumentsAccessor::GetIndexForKeyImpl(holder, arguments, key); |
1782 if (index == kMaxUInt32) return index; | 1654 if (index == kMaxUInt32) return index; |
1783 return (parameter_map->length() - 2) + index; | 1655 return (parameter_map->length() - 2) + index; |
1784 } | 1656 } |
1785 | 1657 |
1786 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, | 1658 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
1787 uint32_t index) { | 1659 uint32_t index) { |
1788 FixedArray* parameter_map = FixedArray::cast(parameters); | 1660 FixedArray* parameter_map = FixedArray::cast(parameters); |
1789 uint32_t length = parameter_map->length() - 2; | 1661 uint32_t length = parameter_map->length() - 2; |
1790 if (index < length) { | 1662 if (index < length) { |
1791 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1663 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
1792 } | 1664 } |
1793 index -= length; | 1665 index -= length; |
1794 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1666 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1795 return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index); | 1667 return ArgumentsAccessor::GetDetailsImpl(arguments, index); |
1796 } | 1668 } |
1797 | 1669 |
1798 private: | |
1799 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { | 1670 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { |
1800 uint32_t length = parameter_map->length() - 2; | 1671 uint32_t length = parameter_map->length() - 2; |
1801 return key < length | 1672 return key < length |
1802 ? parameter_map->get(key + 2) | 1673 ? parameter_map->get(key + 2) |
1803 : Object::cast(parameter_map->GetHeap()->the_hole_value()); | 1674 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
1804 } | 1675 } |
1805 }; | 1676 }; |
1806 | 1677 |
1807 | 1678 |
1808 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1679 class FastSloppyArgumentsElementsAccessor |
1809 return elements_accessors_[ElementsKindForArray(array)]; | 1680 : public SloppyArgumentsElementsAccessor< |
1810 } | 1681 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
1682 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { | |
1683 public: | |
1684 friend class SloppyArgumentsElementsAccessor< | |
1685 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | |
1686 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1687 friend class ElementsAccessorBase< | |
1688 FastSloppyArgumentsElementsAccessor, | |
1689 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1690 explicit FastSloppyArgumentsElementsAccessor(const char* name) | |
1691 : SloppyArgumentsElementsAccessor< | |
1692 FastSloppyArgumentsElementsAccessor, | |
1693 FastHoleyObjectElementsAccessor, | |
1694 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | |
1695 | |
1696 protected: | |
1697 static void AddImpl(Handle<JSObject> object, uint32_t key, | |
1698 Handle<Object> value, PropertyAttributes attributes, | |
1699 uint32_t new_capacity) { | |
1700 DCHECK_EQ(NONE, attributes); | |
1701 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | |
1702 Handle<FixedArrayBase> old_elements( | |
1703 FixedArrayBase::cast(parameter_map->get(1))); | |
1704 if (old_elements->IsSeededNumberDictionary() || | |
1705 static_cast<uint32_t>(old_elements->length()) < new_capacity) { | |
1706 GrowCapacityAndConvertImpl(object, new_capacity); | |
1707 } | |
1708 SetImpl(object->elements(), key, *value); | |
1709 } | |
1710 | |
1711 static void ReconfigureImpl(Handle<JSObject> object, | |
1712 Handle<FixedArrayBase> store, uint32_t index, | |
1713 Handle<Object> value, | |
1714 PropertyAttributes attributes) { | |
1715 Handle<SeededNumberDictionary> dictionary = | |
1716 JSObject::NormalizeElements(object); | |
1717 FixedArray::cast(*store)->set(1, *dictionary); | |
1718 uint32_t length = static_cast<uint32_t>(store->length()) - 2; | |
1719 if (index >= length) { | |
1720 index = dictionary->FindEntry(index - length) + length; | |
1721 } | |
1722 object->GetElementsAccessor()->Reconfigure(object, store, index, value, | |
1723 attributes); | |
1724 } | |
1725 | |
1726 virtual void Delete(Handle<JSObject> obj, uint32_t key, | |
1727 LanguageMode language_mode) final { | |
1728 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | |
1729 if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) { | |
1730 // TODO(kmillikin): We could check if this was the last aliased | |
1731 // parameter, and revert to normal elements in that case. That | |
1732 // would enable GC of the context. | |
1733 parameter_map->set_the_hole(key + 2); | |
1734 } else { | |
1735 FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); | |
Igor Sheludko
2015/07/02 13:28:42
You can put the implementation of this to the pare
Toon Verwaest
2015/07/02 13:49:01
Done.
| |
1736 } | |
1737 } | |
1738 | |
1739 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | |
1740 FixedArrayBase* to, ElementsKind from_kind, | |
1741 uint32_t to_start, int packed_size, | |
1742 int copy_size) { | |
1743 DCHECK(!to->IsDictionary()); | |
1744 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { | |
1745 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, | |
1746 to_start, copy_size); | |
1747 } else { | |
1748 DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, from_kind); | |
1749 CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to, | |
1750 FAST_HOLEY_ELEMENTS, to_start, copy_size); | |
1751 } | |
1752 } | |
1753 | |
1754 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | |
1755 uint32_t capacity) { | |
1756 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | |
1757 Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1))); | |
1758 ElementsKind from_kind = object->GetElementsKind(); | |
1759 // This method should only be called if there's a reason to update the | |
1760 // elements. | |
1761 DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS || | |
1762 static_cast<uint32_t>(old_elements->length()) < capacity); | |
1763 Handle<FixedArrayBase> elements = | |
1764 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); | |
1765 Handle<Map> new_map = JSObject::GetElementsTransitionMap( | |
1766 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); | |
1767 JSObject::MigrateToMap(object, new_map); | |
1768 parameter_map->set(1, *elements); | |
1769 JSObject::ValidateElements(object); | |
1770 } | |
1771 }; | |
1811 | 1772 |
1812 | 1773 |
1813 ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) { | 1774 class SlowSloppyArgumentsElementsAccessor |
1814 return ForArray(*array); | 1775 : public SloppyArgumentsElementsAccessor< |
1815 } | 1776 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
1777 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | |
1778 public: | |
1779 friend class ElementsAccessorBase< | |
1780 SlowSloppyArgumentsElementsAccessor, | |
1781 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1782 friend class SloppyArgumentsElementsAccessor< | |
1783 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
1784 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
1785 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | |
1786 : SloppyArgumentsElementsAccessor< | |
1787 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
1788 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | |
1789 | |
1790 protected: | |
1791 static void AddImpl(Handle<JSObject> object, uint32_t key, | |
1792 Handle<Object> value, PropertyAttributes attributes, | |
1793 uint32_t new_capacity) { | |
1794 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | |
1795 Handle<FixedArrayBase> old_elements( | |
1796 FixedArrayBase::cast(parameter_map->get(1))); | |
1797 Handle<SeededNumberDictionary> dictionary = | |
1798 old_elements->IsSeededNumberDictionary() | |
1799 ? Handle<SeededNumberDictionary>::cast(old_elements) | |
1800 : JSObject::NormalizeElements(object); | |
1801 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
1802 Handle<SeededNumberDictionary> new_dictionary = | |
1803 SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details); | |
1804 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | |
1805 if (*dictionary != *new_dictionary) { | |
1806 FixedArray::cast(object->elements())->set(1, *new_dictionary); | |
1807 } | |
1808 } | |
1809 | |
1810 static void ReconfigureImpl(Handle<JSObject> object, | |
1811 Handle<FixedArrayBase> store, uint32_t index, | |
1812 Handle<Object> value, | |
1813 PropertyAttributes attributes) { | |
1814 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); | |
1815 uint32_t length = parameter_map->length() - 2; | |
1816 if (index < length) { | |
1817 Object* probe = parameter_map->get(index + 2); | |
1818 DCHECK(!probe->IsTheHole()); | |
1819 Context* context = Context::cast(parameter_map->get(0)); | |
1820 int context_index = Smi::cast(probe)->value(); | |
1821 DCHECK(!context->get(context_index)->IsTheHole()); | |
1822 context->set(context_index, *value); | |
1823 | |
1824 // Redefining attributes of an aliased element destroys fast aliasing. | |
1825 parameter_map->set_the_hole(index + 2); | |
1826 // For elements that are still writable we re-establish slow aliasing. | |
1827 if ((attributes & READ_ONLY) == 0) { | |
1828 Isolate* isolate = store->GetIsolate(); | |
1829 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); | |
1830 } | |
1831 | |
1832 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
1833 Handle<SeededNumberDictionary> arguments( | |
1834 SeededNumberDictionary::cast(parameter_map->get(1))); | |
1835 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, | |
1836 value, details); | |
1837 parameter_map->set(1, *arguments); | |
1838 } else { | |
1839 Handle<FixedArrayBase> arguments( | |
1840 FixedArrayBase::cast(parameter_map->get(1))); | |
1841 DictionaryElementsAccessor::ReconfigureImpl( | |
1842 object, arguments, index - length, value, attributes); | |
1843 } | |
1844 } | |
1845 | |
1846 virtual void Delete(Handle<JSObject> obj, uint32_t key, | |
1847 LanguageMode language_mode) final { | |
1848 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | |
1849 if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) { | |
1850 // TODO(kmillikin): We could check if this was the last aliased | |
1851 // parameter, and revert to normal elements in that case. That | |
1852 // would enable GC of the context. | |
1853 parameter_map->set_the_hole(key + 2); | |
1854 } else { | |
1855 DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode); | |
1856 } | |
1857 } | |
1858 }; | |
1816 | 1859 |
1817 | 1860 |
1818 void ElementsAccessor::InitializeOncePerProcess() { | 1861 void ElementsAccessor::InitializeOncePerProcess() { |
1819 static ElementsAccessor* accessor_array[] = { | 1862 static ElementsAccessor* accessor_array[] = { |
1820 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), | 1863 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), |
1821 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1864 ELEMENTS_LIST(ACCESSOR_ARRAY) |
1822 #undef ACCESSOR_ARRAY | 1865 #undef ACCESSOR_ARRAY |
1823 }; | 1866 }; |
1824 | 1867 |
1825 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 1868 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1969 break; | 2012 break; |
1970 } | 2013 } |
1971 | 2014 |
1972 array->set_elements(*elms); | 2015 array->set_elements(*elms); |
1973 array->set_length(Smi::FromInt(number_of_elements)); | 2016 array->set_length(Smi::FromInt(number_of_elements)); |
1974 return array; | 2017 return array; |
1975 } | 2018 } |
1976 | 2019 |
1977 } // namespace internal | 2020 } // namespace internal |
1978 } // namespace v8 | 2021 } // namespace v8 |
OLD | NEW |