Chromium Code Reviews| 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 |