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/elements.h" | 5 #include "src/elements.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/factory.h" | 9 #include "src/factory.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 Handle<FixedArrayBase> backing_store) final { | 663 Handle<FixedArrayBase> backing_store) final { |
664 return ElementsAccessorSubclass::PopImpl(receiver, backing_store); | 664 return ElementsAccessorSubclass::PopImpl(receiver, backing_store); |
665 } | 665 } |
666 | 666 |
667 static Handle<Object> PopImpl(Handle<JSArray> receiver, | 667 static Handle<Object> PopImpl(Handle<JSArray> receiver, |
668 Handle<FixedArrayBase> backing_store) { | 668 Handle<FixedArrayBase> backing_store) { |
669 UNREACHABLE(); | 669 UNREACHABLE(); |
670 return Handle<Object>(); | 670 return Handle<Object>(); |
671 } | 671 } |
672 | 672 |
673 virtual Handle<Object> Shift(Handle<JSArray> receiver, | |
674 Handle<FixedArrayBase> backing_store) final { | |
675 return ElementsAccessorSubclass::ShiftImpl(receiver, backing_store); | |
676 } | |
677 | |
678 static Handle<Object> ShiftImpl(Handle<JSArray> receiver, | |
679 Handle<FixedArrayBase> backing_store) { | |
680 UNREACHABLE(); | |
681 return Handle<Object>(); | |
682 } | |
683 | |
673 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { | 684 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
674 ElementsAccessorSubclass::SetLengthImpl(array, length, | 685 ElementsAccessorSubclass::SetLengthImpl(array, length, |
675 handle(array->elements())); | 686 handle(array->elements())); |
676 } | 687 } |
677 | 688 |
678 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 689 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
679 Handle<FixedArrayBase> backing_store); | 690 Handle<FixedArrayBase> backing_store) { |
691 DCHECK(!array->SetLengthWouldNormalize(length)); | |
692 DCHECK(IsFastElementsKind(array->GetElementsKind())); | |
693 uint32_t old_length = 0; | |
694 CHECK(array->length()->ToArrayIndex(&old_length)); | |
695 | |
696 if (old_length < length) { | |
697 ElementsKind kind = array->GetElementsKind(); | |
698 if (!IsFastHoleyElementsKind(kind)) { | |
699 kind = GetHoleyElementsKind(kind); | |
700 JSObject::TransitionElementsKind(array, kind); | |
701 } | |
702 } | |
703 | |
704 // Check whether the backing store should be shrunk. | |
705 uint32_t capacity = backing_store->length(); | |
706 if (length == 0) { | |
707 array->initialize_elements(); | |
708 } else if (length <= capacity) { | |
709 if (array->HasFastSmiOrObjectElements()) { | |
710 backing_store = JSObject::EnsureWritableFastElements(array); | |
711 } | |
712 if (2 * length <= capacity) { | |
713 // If more than half the elements won't be used, trim the array. | |
714 array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | |
715 *backing_store, capacity - length); | |
716 } else { | |
717 // Otherwise, fill the unused tail with holes. | |
718 for (uint32_t i = length; i < old_length; i++) { | |
719 BackingStore::cast(*backing_store)->set_the_hole(i); | |
720 } | |
721 } | |
722 } else { | |
723 // Check whether the backing store should be expanded. | |
724 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | |
725 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | |
726 } | |
727 | |
728 array->set_length(Smi::FromInt(length)); | |
729 JSObject::ValidateElements(array); | |
730 } | |
680 | 731 |
681 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 732 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
682 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, | 733 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
683 ElementsKind from_kind, uint32_t capacity) { | 734 ElementsKind from_kind, uint32_t capacity) { |
684 return ConvertElementsWithCapacity( | 735 return ConvertElementsWithCapacity( |
685 object, old_elements, from_kind, capacity, 0, 0, | 736 object, old_elements, from_kind, capacity, 0, 0, |
686 ElementsAccessor::kCopyToEndAndInitializeToHole); | 737 ElementsAccessor::kCopyToEndAndInitializeToHole); |
687 } | 738 } |
688 | 739 |
689 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 740 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1254 DCHECK(BackingStore::get(backing_store, i)->IsSmi() || | 1305 DCHECK(BackingStore::get(backing_store, i)->IsSmi() || |
1255 (IsFastHoleyElementsKind(KindTraits::Kind) && | 1306 (IsFastHoleyElementsKind(KindTraits::Kind) && |
1256 backing_store->is_the_hole(i))); | 1307 backing_store->is_the_hole(i))); |
1257 } | 1308 } |
1258 } | 1309 } |
1259 #endif | 1310 #endif |
1260 } | 1311 } |
1261 | 1312 |
1262 static Handle<Object> PopImpl(Handle<JSArray> receiver, | 1313 static Handle<Object> PopImpl(Handle<JSArray> receiver, |
1263 Handle<FixedArrayBase> backing_store) { | 1314 Handle<FixedArrayBase> backing_store) { |
1264 uint32_t new_length = | 1315 uint32_t len = |
1265 static_cast<uint32_t>(Smi::cast(receiver->length())->value()) - 1; | 1316 static_cast<uint32_t>(Smi::cast(receiver->length())->value()); |
1317 if (len == 0) { | |
Igor Sheludko
2015/09/02 12:35:20
ArrayPop already handles this case. Maybe this sho
Camillo Bruni
2015/09/02 13:04:55
Right.
| |
1318 return receiver->GetIsolate()->factory()->undefined_value(); | |
1319 } | |
1320 uint32_t new_length = len - 1; | |
1266 Handle<Object> result = | 1321 Handle<Object> result = |
1267 FastElementsAccessorSubclass::GetImpl(backing_store, new_length); | 1322 FastElementsAccessorSubclass::GetImpl(backing_store, new_length); |
1268 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, | 1323 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, |
1269 backing_store); | 1324 backing_store); |
1270 | 1325 |
1271 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { | 1326 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { |
1327 return receiver->GetIsolate()->factory()->undefined_value(); | |
1328 } | |
1329 return result; | |
1330 } | |
1331 | |
1332 static Handle<Object> ShiftImpl(Handle<JSArray> receiver, | |
1333 Handle<FixedArrayBase> backing_store) { | |
1334 uint32_t len = | |
1335 static_cast<uint32_t>(Smi::cast(receiver->length())->value()); | |
1336 Isolate* isolate = receiver->GetIsolate(); | |
1337 if (len == 0) { | |
Igor Sheludko
2015/09/02 12:35:20
Same here.
Camillo Bruni
2015/09/02 13:04:55
ditto.
| |
1338 return isolate->factory()->undefined_value(); | |
1339 } | |
1340 int new_length = len - 1; | |
1341 Handle<Object> result = | |
1342 FastElementsAccessorSubclass::GetImpl(backing_store, 0); | |
1343 Heap* heap = isolate->heap(); | |
1344 if (heap->CanMoveObjectStart(*backing_store)) { | |
1345 receiver->set_elements(heap->LeftTrimFixedArray(*backing_store, 1)); | |
1346 } else { | |
1347 FastElementsAccessorSubclass::MoveElements(heap, backing_store, 0, 1, | |
1348 new_length, 0, 0); | |
1349 } | |
1350 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, | |
1351 backing_store); | |
1352 | |
1353 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { | |
1272 result = receiver->GetIsolate()->factory()->undefined_value(); | 1354 result = receiver->GetIsolate()->factory()->undefined_value(); |
1273 } | 1355 } |
1274 return result; | 1356 return result; |
1275 } | 1357 } |
1276 | 1358 |
1277 static uint32_t PushImpl(Handle<JSArray> receiver, | 1359 static uint32_t PushImpl(Handle<JSArray> receiver, |
1278 Handle<FixedArrayBase> backing_store, | 1360 Handle<FixedArrayBase> backing_store, |
1279 Arguments* args, uint32_t push_size) { | 1361 Arguments* args, uint32_t push_size) { |
1280 uint32_t len = Smi::cast(receiver->length())->value(); | 1362 uint32_t len = Smi::cast(receiver->length())->value(); |
1281 if (push_size == 0) { | 1363 if (push_size == 0) { |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2115 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); | 2197 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
2116 Handle<Map> new_map = JSObject::GetElementsTransitionMap( | 2198 Handle<Map> new_map = JSObject::GetElementsTransitionMap( |
2117 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); | 2199 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); |
2118 JSObject::MigrateToMap(object, new_map); | 2200 JSObject::MigrateToMap(object, new_map); |
2119 parameter_map->set(1, *elements); | 2201 parameter_map->set(1, *elements); |
2120 JSObject::ValidateElements(object); | 2202 JSObject::ValidateElements(object); |
2121 } | 2203 } |
2122 }; | 2204 }; |
2123 | 2205 |
2124 | 2206 |
2125 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | |
2126 void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: | |
2127 SetLengthImpl(Handle<JSArray> array, uint32_t length, | |
2128 Handle<FixedArrayBase> backing_store) { | |
2129 DCHECK(!array->SetLengthWouldNormalize(length)); | |
2130 DCHECK(IsFastElementsKind(array->GetElementsKind())); | |
2131 uint32_t old_length = 0; | |
2132 CHECK(array->length()->ToArrayIndex(&old_length)); | |
2133 | |
2134 if (old_length < length) { | |
2135 ElementsKind kind = array->GetElementsKind(); | |
2136 if (!IsFastHoleyElementsKind(kind)) { | |
2137 kind = GetHoleyElementsKind(kind); | |
2138 JSObject::TransitionElementsKind(array, kind); | |
2139 } | |
2140 } | |
2141 | |
2142 // Check whether the backing store should be shrunk. | |
2143 uint32_t capacity = backing_store->length(); | |
2144 if (length == 0) { | |
2145 array->initialize_elements(); | |
2146 } else if (length <= capacity) { | |
2147 if (array->HasFastSmiOrObjectElements()) { | |
2148 backing_store = JSObject::EnsureWritableFastElements(array); | |
2149 } | |
2150 if (2 * length <= capacity) { | |
2151 // If more than half the elements won't be used, trim the array. | |
2152 array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | |
2153 *backing_store, capacity - length); | |
2154 } else { | |
2155 // Otherwise, fill the unused tail with holes. | |
2156 for (uint32_t i = length; i < old_length; i++) { | |
2157 BackingStore::cast(*backing_store)->set_the_hole(i); | |
2158 } | |
2159 } | |
2160 } else { | |
2161 // Check whether the backing store should be expanded. | |
2162 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | |
2163 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | |
2164 } | |
2165 | |
2166 array->set_length(Smi::FromInt(length)); | |
2167 JSObject::ValidateElements(array); | |
2168 } | |
2169 } // namespace | 2207 } // namespace |
2170 | 2208 |
2171 | 2209 |
2172 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index, | 2210 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index, |
2173 bool allow_appending) { | 2211 bool allow_appending) { |
2174 DisallowHeapAllocation no_allocation; | 2212 DisallowHeapAllocation no_allocation; |
2175 Object* raw_length = NULL; | 2213 Object* raw_length = NULL; |
2176 const char* elements_type = "array"; | 2214 const char* elements_type = "array"; |
2177 if (obj->IsJSArray()) { | 2215 if (obj->IsJSArray()) { |
2178 JSArray* array = JSArray::cast(*obj); | 2216 JSArray* array = JSArray::cast(*obj); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2317 if (elements_accessors_ == NULL) return; | 2355 if (elements_accessors_ == NULL) return; |
2318 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 2356 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
2319 ELEMENTS_LIST(ACCESSOR_DELETE) | 2357 ELEMENTS_LIST(ACCESSOR_DELETE) |
2320 #undef ACCESSOR_DELETE | 2358 #undef ACCESSOR_DELETE |
2321 elements_accessors_ = NULL; | 2359 elements_accessors_ = NULL; |
2322 } | 2360 } |
2323 | 2361 |
2324 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2362 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2325 } // namespace internal | 2363 } // namespace internal |
2326 } // namespace v8 | 2364 } // namespace v8 |
OLD | NEW |