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

Side by Side Diff: src/array.js

Issue 416403002: Keep new arrays allocated with 'new Array(N)' in fast mode (revisited) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/elements.cc » ('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 "use strict"; 5 "use strict";
6 6
7 // This file relies on the fact that the following declarations have been made 7 // This file relies on the fact that the following declarations have been made
8 // in runtime.js: 8 // in runtime.js:
9 // var $Array = global.Array; 9 // var $Array = global.Array;
10 10
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 var e = array[key]; 79 var e = array[key];
80 if (!IS_STRING(e)) e = convert(e); 80 if (!IS_STRING(e)) e = convert(e);
81 elements[elements_length++] = e; 81 elements[elements_length++] = e;
82 last_key = key; 82 last_key = key;
83 } 83 }
84 } 84 }
85 return %StringBuilderConcat(elements, elements_length, ''); 85 return %StringBuilderConcat(elements, elements_length, '');
86 } 86 }
87 87
88 88
89 function UseSparseVariant(object, length, is_array) { 89 function UseSparseVariant(array, length, is_array, touched) {
90 return is_array && 90 // Only use the sparse variant on arrays that are likely to be sparse and the
91 length > 1000 && 91 // number of elements touched in the operation is relatively small compared to
92 (!%_IsSmi(length) || 92 // the overall size of the array.
93 %EstimateNumberOfElements(object) < (length >> 2)); 93 if (!is_array || length < 1000 || %IsObserved(array)) {
94 return false;
95 }
96 if (!%_IsSmi(length)) {
97 return true;
98 }
99 var elements_threshold = length >> 2; // No more than 75% holes
100 var estimated_elements = %EstimateNumberOfElements(array);
101 return (estimated_elements < elements_threshold) &&
102 (touched > estimated_elements * 4);
94 } 103 }
95 104
96 105
97 function Join(array, length, separator, convert) { 106 function Join(array, length, separator, convert) {
98 if (length == 0) return ''; 107 if (length == 0) return '';
99 108
100 var is_array = IS_ARRAY(array); 109 var is_array = IS_ARRAY(array);
101 110
102 if (is_array) { 111 if (is_array) {
103 // If the array is cyclic, return the empty string for already 112 // If the array is cyclic, return the empty string for already
104 // visited arrays. 113 // visited arrays.
105 if (!%PushIfAbsent(visited_arrays, array)) return ''; 114 if (!%PushIfAbsent(visited_arrays, array)) return '';
106 } 115 }
107 116
108 // Attempt to convert the elements. 117 // Attempt to convert the elements.
109 try { 118 try {
110 if (UseSparseVariant(array, length, is_array)) { 119 if (UseSparseVariant(array, length, is_array, length)) {
120 %NormalizeElements(array);
111 if (separator.length == 0) { 121 if (separator.length == 0) {
112 return SparseJoin(array, length, convert); 122 return SparseJoin(array, length, convert);
113 } else { 123 } else {
114 return SparseJoinWithSeparatorJS(array, length, convert, separator); 124 return SparseJoinWithSeparatorJS(array, length, convert, separator);
115 } 125 }
116 } 126 }
117 127
118 // Fast case for one-element arrays. 128 // Fast case for one-element arrays.
119 if (length == 1) { 129 if (length == 1) {
120 var e = array[0]; 130 var e = array[0];
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 } 521 }
512 } 522 }
513 } 523 }
514 } 524 }
515 525
516 526
517 function ArrayReverse() { 527 function ArrayReverse() {
518 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse"); 528 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
519 529
520 var array = TO_OBJECT_INLINE(this); 530 var array = TO_OBJECT_INLINE(this);
521 var j = TO_UINT32(array.length) - 1; 531 var len = TO_UINT32(array.length);
522 532
523 if (UseSparseVariant(array, j, IS_ARRAY(array))) { 533 if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
524 SparseReverse(array, j+1); 534 %NormalizeElements(array);
535 SparseReverse(array, len);
525 return array; 536 return array;
526 } 537 }
527 538
539 var j = len - 1;
528 for (var i = 0; i < j; i++, j--) { 540 for (var i = 0; i < j; i++, j--) {
529 var current_i = array[i]; 541 var current_i = array[i];
530 if (!IS_UNDEFINED(current_i) || i in array) { 542 if (!IS_UNDEFINED(current_i) || i in array) {
531 var current_j = array[j]; 543 var current_j = array[j];
532 if (!IS_UNDEFINED(current_j) || j in array) { 544 if (!IS_UNDEFINED(current_j) || j in array) {
533 array[i] = current_j; 545 array[i] = current_j;
534 array[j] = current_i; 546 array[j] = current_i;
535 } else { 547 } else {
536 array[j] = current_i; 548 array[j] = current_i;
537 delete array[i]; 549 delete array[i];
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 end_i += len; 675 end_i += len;
664 if (end_i < 0) end_i = 0; 676 if (end_i < 0) end_i = 0;
665 } else { 677 } else {
666 if (end_i > len) end_i = len; 678 if (end_i > len) end_i = len;
667 } 679 }
668 680
669 var result = []; 681 var result = [];
670 682
671 if (end_i < start_i) return result; 683 if (end_i < start_i) return result;
672 684
673 if (IS_ARRAY(array) && 685 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
674 !%IsObserved(array) && 686 %NormalizeElements(array);
675 (end_i > 1000) && 687 %NormalizeElements(result);
676 (%EstimateNumberOfElements(array) < end_i)) {
677 SmartSlice(array, start_i, end_i - start_i, len, result); 688 SmartSlice(array, start_i, end_i - start_i, len, result);
678 } else { 689 } else {
679 SimpleSlice(array, start_i, end_i - start_i, len, result); 690 SimpleSlice(array, start_i, end_i - start_i, len, result);
680 } 691 }
681 692
682 result.length = end_i - start_i; 693 result.length = end_i - start_i;
683 694
684 return result; 695 return result;
685 } 696 }
686 697
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0; 785 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
775 786
776 if (del_count != num_elements_to_add && ObjectIsSealed(array)) { 787 if (del_count != num_elements_to_add && ObjectIsSealed(array)) {
777 throw MakeTypeError("array_functions_change_sealed", 788 throw MakeTypeError("array_functions_change_sealed",
778 ["Array.prototype.splice"]); 789 ["Array.prototype.splice"]);
779 } else if (del_count > 0 && ObjectIsFrozen(array)) { 790 } else if (del_count > 0 && ObjectIsFrozen(array)) {
780 throw MakeTypeError("array_functions_on_frozen", 791 throw MakeTypeError("array_functions_on_frozen",
781 ["Array.prototype.splice"]); 792 ["Array.prototype.splice"]);
782 } 793 }
783 794
784 var use_simple_splice = true; 795 var changed_elements = del_count;
785 if (IS_ARRAY(array) && 796 if (num_elements_to_add != del_count) {
786 num_elements_to_add !== del_count) { 797 // If the slice needs to do a actually move elements after the insertion
787 // If we are only deleting/moving a few things near the end of the 798 // point, then include those in the estimate of changed elements.
788 // array then the simple version is going to be faster, because it 799 changed_elements += len - start_i - del_count;
789 // doesn't touch most of the array.
790 var estimated_non_hole_elements = %EstimateNumberOfElements(array);
791 if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
792 use_simple_splice = false;
793 }
794 } 800 }
795 801 if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
796 if (use_simple_splice) { 802 %NormalizeElements(array);
803 %NormalizeElements(deleted_elements);
804 SmartSlice(array, start_i, del_count, len, deleted_elements);
805 SmartMove(array, start_i, del_count, len, num_elements_to_add);
806 } else {
797 SimpleSlice(array, start_i, del_count, len, deleted_elements); 807 SimpleSlice(array, start_i, del_count, len, deleted_elements);
798 SimpleMove(array, start_i, del_count, len, num_elements_to_add); 808 SimpleMove(array, start_i, del_count, len, num_elements_to_add);
799 } else {
800 SmartSlice(array, start_i, del_count, len, deleted_elements);
801 SmartMove(array, start_i, del_count, len, num_elements_to_add);
802 } 809 }
803 810
804 // Insert the arguments into the resulting array in 811 // Insert the arguments into the resulting array in
805 // place of the deleted elements. 812 // place of the deleted elements.
806 var i = start_i; 813 var i = start_i;
807 var arguments_index = 2; 814 var arguments_index = 2;
808 var arguments_length = %_ArgumentsLength(); 815 var arguments_length = %_ArgumentsLength();
809 while (arguments_index < arguments_length) { 816 while (arguments_index < arguments_length) {
810 array[i++] = %_Arguments(arguments_index++); 817 array[i++] = %_Arguments(arguments_index++);
811 } 818 }
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 index = TO_INTEGER(index); 1283 index = TO_INTEGER(index);
1277 // If index is negative, index from the end of the array. 1284 // If index is negative, index from the end of the array.
1278 if (index < 0) { 1285 if (index < 0) {
1279 index = length + index; 1286 index = length + index;
1280 // If index is still negative, search the entire array. 1287 // If index is still negative, search the entire array.
1281 if (index < 0) index = 0; 1288 if (index < 0) index = 0;
1282 } 1289 }
1283 } 1290 }
1284 var min = index; 1291 var min = index;
1285 var max = length; 1292 var max = length;
1286 if (UseSparseVariant(this, length, IS_ARRAY(this))) { 1293 if (UseSparseVariant(this, length, IS_ARRAY(this), max - min)) {
1294 %NormalizeElements(this);
1287 var indices = %GetArrayKeys(this, length); 1295 var indices = %GetArrayKeys(this, length);
1288 if (IS_NUMBER(indices)) { 1296 if (IS_NUMBER(indices)) {
1289 // It's an interval. 1297 // It's an interval.
1290 max = indices; // Capped by length already. 1298 max = indices; // Capped by length already.
1291 // Fall through to loop below. 1299 // Fall through to loop below.
1292 } else { 1300 } else {
1293 if (indices.length == 0) return -1; 1301 if (indices.length == 0) return -1;
1294 // Get all the keys in sorted order. 1302 // Get all the keys in sorted order.
1295 var sortedKeys = GetSortedArrayKeys(this, indices); 1303 var sortedKeys = GetSortedArrayKeys(this, indices);
1296 var n = sortedKeys.length; 1304 var n = sortedKeys.length;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 } else { 1339 } else {
1332 index = TO_INTEGER(index); 1340 index = TO_INTEGER(index);
1333 // If index is negative, index from end of the array. 1341 // If index is negative, index from end of the array.
1334 if (index < 0) index += length; 1342 if (index < 0) index += length;
1335 // If index is still negative, do not search the array. 1343 // If index is still negative, do not search the array.
1336 if (index < 0) return -1; 1344 if (index < 0) return -1;
1337 else if (index >= length) index = length - 1; 1345 else if (index >= length) index = length - 1;
1338 } 1346 }
1339 var min = 0; 1347 var min = 0;
1340 var max = index; 1348 var max = index;
1341 if (UseSparseVariant(this, length, IS_ARRAY(this))) { 1349 if (UseSparseVariant(this, length, IS_ARRAY(this), index)) {
1350 %NormalizeElements(this);
1342 var indices = %GetArrayKeys(this, index + 1); 1351 var indices = %GetArrayKeys(this, index + 1);
1343 if (IS_NUMBER(indices)) { 1352 if (IS_NUMBER(indices)) {
1344 // It's an interval. 1353 // It's an interval.
1345 max = indices; // Capped by index already. 1354 max = indices; // Capped by index already.
1346 // Fall through to loop below. 1355 // Fall through to loop below.
1347 } else { 1356 } else {
1348 if (indices.length == 0) return -1; 1357 if (indices.length == 0) return -1;
1349 // Get all the keys in sorted order. 1358 // Get all the keys in sorted order.
1350 var sortedKeys = GetSortedArrayKeys(this, indices); 1359 var sortedKeys = GetSortedArrayKeys(this, indices);
1351 var i = sortedKeys.length - 1; 1360 var i = sortedKeys.length - 1;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 )); 1532 ));
1524 1533
1525 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( 1534 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array(
1526 "join", getFunction("join", ArrayJoin), 1535 "join", getFunction("join", ArrayJoin),
1527 "pop", getFunction("pop", ArrayPop), 1536 "pop", getFunction("pop", ArrayPop),
1528 "push", getFunction("push", ArrayPush) 1537 "push", getFunction("push", ArrayPush)
1529 )); 1538 ));
1530 } 1539 }
1531 1540
1532 SetUpArray(); 1541 SetUpArray();
OLDNEW
« no previous file with comments | « no previous file | src/elements.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698