Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: src/elements.cc

Issue 1317053006: Adding ElementsAccessor::Shift (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@2015-09-01_array_builtin_cleanup
Patch Set: Only use range checks in builtins Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/elements.h ('k') | test/mjsunit/array-natives-elements.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 DCHECK(len > 0);
1318 uint32_t new_length = len - 1;
1266 Handle<Object> result = 1319 Handle<Object> result =
1267 FastElementsAccessorSubclass::GetImpl(backing_store, new_length); 1320 FastElementsAccessorSubclass::GetImpl(backing_store, new_length);
1268 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length, 1321 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length,
1269 backing_store); 1322 backing_store);
1270 1323
1271 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) { 1324 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) {
1325 return receiver->GetIsolate()->factory()->undefined_value();
1326 }
1327 return result;
1328 }
1329
1330 static Handle<Object> ShiftImpl(Handle<JSArray> receiver,
1331 Handle<FixedArrayBase> backing_store) {
1332 uint32_t len =
1333 static_cast<uint32_t>(Smi::cast(receiver->length())->value());
1334 Isolate* isolate = receiver->GetIsolate();
1335 DCHECK(len > 0);
1336 int new_length = len - 1;
1337 Handle<Object> result =
1338 FastElementsAccessorSubclass::GetImpl(backing_store, 0);
1339 Heap* heap = isolate->heap();
1340 if (heap->CanMoveObjectStart(*backing_store)) {
1341 receiver->set_elements(heap->LeftTrimFixedArray(*backing_store, 1));
1342 } else {
1343 FastElementsAccessorSubclass::MoveElements(heap, backing_store, 0, 1,
1344 new_length, 0, 0);
1345 }
1346 FastElementsAccessorSubclass::SetLengthImpl(receiver, new_length,
1347 backing_store);
1348
1349 if (IsHoleyElementsKind(KindTraits::Kind) && result->IsTheHole()) {
1272 result = receiver->GetIsolate()->factory()->undefined_value(); 1350 result = receiver->GetIsolate()->factory()->undefined_value();
1273 } 1351 }
1274 return result; 1352 return result;
1275 } 1353 }
1276 1354
1277 static uint32_t PushImpl(Handle<JSArray> receiver, 1355 static uint32_t PushImpl(Handle<JSArray> receiver,
1278 Handle<FixedArrayBase> backing_store, 1356 Handle<FixedArrayBase> backing_store,
1279 Arguments* args, uint32_t push_size) { 1357 Arguments* args, uint32_t push_size) {
1280 uint32_t len = Smi::cast(receiver->length())->value(); 1358 uint32_t len = Smi::cast(receiver->length())->value();
1281 if (push_size == 0) { 1359 DCHECK(push_size > 0);
1282 return len;
1283 }
1284 uint32_t elms_len = backing_store->length(); 1360 uint32_t elms_len = backing_store->length();
1285 // Currently fixed arrays cannot grow too big, so 1361 // Currently fixed arrays cannot grow too big, so
1286 // we should never hit this case. 1362 // we should never hit this case.
1287 DCHECK(push_size <= static_cast<uint32_t>(Smi::kMaxValue - len)); 1363 DCHECK(push_size <= static_cast<uint32_t>(Smi::kMaxValue - len));
1288 uint32_t new_length = len + push_size; 1364 uint32_t new_length = len + push_size;
1289 1365
1290 if (new_length > elms_len) { 1366 if (new_length > elms_len) {
1291 // New backing storage is needed. 1367 // New backing storage is needed.
1292 uint32_t capacity = new_length + (new_length >> 1) + 16; 1368 uint32_t capacity = new_length + (new_length >> 1) + 16;
1293 backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity( 1369 backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
(...skipping 13 matching lines...) Expand all
1307 DCHECK(*backing_store == receiver->elements()); 1383 DCHECK(*backing_store == receiver->elements());
1308 // Set the length. 1384 // Set the length.
1309 receiver->set_length(Smi::FromInt(new_length)); 1385 receiver->set_length(Smi::FromInt(new_length));
1310 return new_length; 1386 return new_length;
1311 } 1387 }
1312 1388
1313 static uint32_t UnshiftImpl(Handle<JSArray> receiver, 1389 static uint32_t UnshiftImpl(Handle<JSArray> receiver,
1314 Handle<FixedArrayBase> backing_store, 1390 Handle<FixedArrayBase> backing_store,
1315 Arguments* args, uint32_t unshift_size) { 1391 Arguments* args, uint32_t unshift_size) {
1316 uint32_t len = Smi::cast(receiver->length())->value(); 1392 uint32_t len = Smi::cast(receiver->length())->value();
1317 if (unshift_size == 0) { 1393 DCHECK(unshift_size > 0);
1318 return len;
1319 }
1320 uint32_t elms_len = backing_store->length(); 1394 uint32_t elms_len = backing_store->length();
1321 // Currently fixed arrays cannot grow too big, so 1395 // Currently fixed arrays cannot grow too big, so
1322 // we should never hit this case. 1396 // we should never hit this case.
1323 DCHECK(unshift_size <= static_cast<uint32_t>(Smi::kMaxValue - len)); 1397 DCHECK(unshift_size <= static_cast<uint32_t>(Smi::kMaxValue - len));
1324 uint32_t new_length = len + unshift_size; 1398 uint32_t new_length = len + unshift_size;
1325 1399
1326 if (new_length > elms_len) { 1400 if (new_length > elms_len) {
1327 // New backing storage is needed. 1401 // New backing storage is needed.
1328 uint32_t capacity = new_length + (new_length >> 1) + 16; 1402 uint32_t capacity = new_length + (new_length >> 1) + 16;
1329 backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity( 1403 backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
(...skipping 25 matching lines...) Expand all
1355 1429
1356 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store, 1430 static void MoveElements(Heap* heap, Handle<FixedArrayBase> backing_store,
1357 int dst_index, int src_index, int len, 1431 int dst_index, int src_index, int len,
1358 int hole_start, int hole_end) { 1432 int hole_start, int hole_end) {
1359 UNREACHABLE(); 1433 UNREACHABLE();
1360 } 1434 }
1361 1435
1362 static Handle<JSArray> SliceImpl(Handle<JSObject> receiver, 1436 static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
1363 Handle<FixedArrayBase> backing_store, 1437 Handle<FixedArrayBase> backing_store,
1364 uint32_t start, uint32_t end) { 1438 uint32_t start, uint32_t end) {
1439 DCHECK(start < end);
1365 Isolate* isolate = receiver->GetIsolate(); 1440 Isolate* isolate = receiver->GetIsolate();
1366 if (end <= start) {
1367 return isolate->factory()->NewJSArray(KindTraits::Kind, 0, 0);
1368 }
1369 int result_len = end - start; 1441 int result_len = end - start;
1370 Handle<JSArray> result_array = isolate->factory()->NewJSArray( 1442 Handle<JSArray> result_array = isolate->factory()->NewJSArray(
1371 KindTraits::Kind, result_len, result_len); 1443 KindTraits::Kind, result_len, result_len);
1372 DisallowHeapAllocation no_gc; 1444 DisallowHeapAllocation no_gc;
1373 FastElementsAccessorSubclass::CopyElementsImpl( 1445 FastElementsAccessorSubclass::CopyElementsImpl(
1374 *backing_store, start, result_array->elements(), KindTraits::Kind, 0, 1446 *backing_store, start, result_array->elements(), KindTraits::Kind, 0,
1375 kPackedSizeNotKnown, result_len); 1447 kPackedSizeNotKnown, result_len);
1376 return result_array; 1448 return result_array;
1377 } 1449 }
1378 1450
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
2115 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); 2187 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
2116 Handle<Map> new_map = JSObject::GetElementsTransitionMap( 2188 Handle<Map> new_map = JSObject::GetElementsTransitionMap(
2117 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); 2189 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS);
2118 JSObject::MigrateToMap(object, new_map); 2190 JSObject::MigrateToMap(object, new_map);
2119 parameter_map->set(1, *elements); 2191 parameter_map->set(1, *elements);
2120 JSObject::ValidateElements(object); 2192 JSObject::ValidateElements(object);
2121 } 2193 }
2122 }; 2194 };
2123 2195
2124 2196
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 2197 } // namespace
2170 2198
2171 2199
2172 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index, 2200 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index,
2173 bool allow_appending) { 2201 bool allow_appending) {
2174 DisallowHeapAllocation no_allocation; 2202 DisallowHeapAllocation no_allocation;
2175 Object* raw_length = NULL; 2203 Object* raw_length = NULL;
2176 const char* elements_type = "array"; 2204 const char* elements_type = "array";
2177 if (obj->IsJSArray()) { 2205 if (obj->IsJSArray()) {
2178 JSArray* array = JSArray::cast(*obj); 2206 JSArray* array = JSArray::cast(*obj);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2318 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; 2346 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
2319 ELEMENTS_LIST(ACCESSOR_DELETE) 2347 ELEMENTS_LIST(ACCESSOR_DELETE)
2320 #undef ACCESSOR_DELETE 2348 #undef ACCESSOR_DELETE
2321 elements_accessors_ = NULL; 2349 elements_accessors_ = NULL;
2322 } 2350 }
2323 2351
2324 2352
2325 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; 2353 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL;
2326 } // namespace internal 2354 } // namespace internal
2327 } // namespace v8 2355 } // namespace v8
OLDNEW
« no previous file with comments | « src/elements.h ('k') | test/mjsunit/array-natives-elements.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698