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 "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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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(array, length, is_array, touched) { | 89 function UseSparseVariant(array, length, is_array, touched) { |
90 // Only use the sparse variant on arrays that are likely to be sparse and the | 90 // Only use the sparse variant on arrays that are likely to be sparse and the |
91 // number of elements touched in the operation is relatively small compared to | 91 // number of elements touched in the operation is relatively small compared to |
92 // the overall size of the array. | 92 // the overall size of the array. |
93 if (!is_array || length < 1000 || %IsObserved(array)) { | 93 if (!is_array || length < 1000 || %IsObserved(array) || |
| 94 %HasComplexElements(array)) { |
94 return false; | 95 return false; |
95 } | 96 } |
96 if (!%_IsSmi(length)) { | 97 if (!%_IsSmi(length)) { |
97 return true; | 98 return true; |
98 } | 99 } |
99 var elements_threshold = length >> 2; // No more than 75% holes | 100 var elements_threshold = length >> 2; // No more than 75% holes |
100 var estimated_elements = %EstimateNumberOfElements(array); | 101 var estimated_elements = %EstimateNumberOfElements(array); |
101 return (estimated_elements < elements_threshold) && | 102 return (estimated_elements < elements_threshold) && |
102 (touched > estimated_elements * 4); | 103 (touched > estimated_elements * 4); |
103 } | 104 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 // must throw a TypeError if ToObject(e).toLocaleString isn't | 197 // must throw a TypeError if ToObject(e).toLocaleString isn't |
197 // callable. | 198 // callable. |
198 var e_obj = ToObject(e); | 199 var e_obj = ToObject(e); |
199 return %ToString(e_obj.toLocaleString()); | 200 return %ToString(e_obj.toLocaleString()); |
200 } | 201 } |
201 } | 202 } |
202 | 203 |
203 | 204 |
204 // This function implements the optimized splice implementation that can use | 205 // This function implements the optimized splice implementation that can use |
205 // special array operations to handle sparse arrays in a sensible fashion. | 206 // special array operations to handle sparse arrays in a sensible fashion. |
206 function SmartSlice(array, start_i, del_count, len, deleted_elements) { | 207 function SparseSlice(array, start_i, del_count, len, deleted_elements) { |
207 // Move deleted elements to a new array (the return value from splice). | 208 // Move deleted elements to a new array (the return value from splice). |
208 var indices = %GetArrayKeys(array, start_i + del_count); | 209 var indices = %GetArrayKeys(array, start_i + del_count); |
209 if (IS_NUMBER(indices)) { | 210 if (IS_NUMBER(indices)) { |
210 var limit = indices; | 211 var limit = indices; |
211 for (var i = start_i; i < limit; ++i) { | 212 for (var i = start_i; i < limit; ++i) { |
212 var current = array[i]; | 213 var current = array[i]; |
213 if (!IS_UNDEFINED(current) || i in array) { | 214 if (!IS_UNDEFINED(current) || i in array) { |
214 deleted_elements[i - start_i] = current; | 215 deleted_elements[i - start_i] = current; |
215 } | 216 } |
216 } | 217 } |
217 } else { | 218 } else { |
218 var length = indices.length; | 219 var length = indices.length; |
219 for (var k = 0; k < length; ++k) { | 220 for (var k = 0; k < length; ++k) { |
220 var key = indices[k]; | 221 var key = indices[k]; |
221 if (!IS_UNDEFINED(key)) { | 222 if (!IS_UNDEFINED(key)) { |
222 if (key >= start_i) { | 223 if (key >= start_i) { |
223 var current = array[key]; | 224 var current = array[key]; |
224 if (!IS_UNDEFINED(current) || key in array) { | 225 if (!IS_UNDEFINED(current) || key in array) { |
225 deleted_elements[key - start_i] = current; | 226 deleted_elements[key - start_i] = current; |
226 } | 227 } |
227 } | 228 } |
228 } | 229 } |
229 } | 230 } |
230 } | 231 } |
231 } | 232 } |
232 | 233 |
233 | 234 |
234 // This function implements the optimized splice implementation that can use | 235 // This function implements the optimized splice implementation that can use |
235 // special array operations to handle sparse arrays in a sensible fashion. | 236 // special array operations to handle sparse arrays in a sensible fashion. |
236 function SmartMove(array, start_i, del_count, len, num_additional_args) { | 237 function SparseMove(array, start_i, del_count, len, num_additional_args) { |
237 // Bail out if no moving is necessary. | 238 // Bail out if no moving is necessary. |
238 if (num_additional_args === del_count) return; | 239 if (num_additional_args === del_count) return; |
239 // Move data to new array. | 240 // Move data to new array. |
240 var new_array = new InternalArray(len - del_count + num_additional_args); | 241 var new_array = new InternalArray(len - del_count + num_additional_args); |
241 var indices = %GetArrayKeys(array, len); | 242 var indices = %GetArrayKeys(array, len); |
242 if (IS_NUMBER(indices)) { | 243 if (IS_NUMBER(indices)) { |
243 var limit = indices; | 244 var limit = indices; |
244 for (var i = 0; i < start_i && i < limit; ++i) { | 245 for (var i = 0; i < start_i && i < limit; ++i) { |
245 var current = array[i]; | 246 var current = array[i]; |
246 if (!IS_UNDEFINED(current) || i in array) { | 247 if (!IS_UNDEFINED(current) || i in array) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 if (ObjectIsSealed(array)) { | 602 if (ObjectIsSealed(array)) { |
602 throw MakeTypeError("array_functions_change_sealed", | 603 throw MakeTypeError("array_functions_change_sealed", |
603 ["Array.prototype.shift"]); | 604 ["Array.prototype.shift"]); |
604 } | 605 } |
605 | 606 |
606 if (%IsObserved(array)) | 607 if (%IsObserved(array)) |
607 return ObservedArrayShift.call(array, len); | 608 return ObservedArrayShift.call(array, len); |
608 | 609 |
609 var first = array[0]; | 610 var first = array[0]; |
610 | 611 |
611 if (IS_ARRAY(array)) { | 612 if (UseSparseVariant(array, len, IS_ARRAY(array), len)) { |
612 SmartMove(array, 0, 1, len, 0); | 613 SparseMove(array, 0, 1, len, 0); |
613 } else { | 614 } else { |
614 SimpleMove(array, 0, 1, len, 0); | 615 SimpleMove(array, 0, 1, len, 0); |
615 } | 616 } |
616 | 617 |
617 array.length = len - 1; | 618 array.length = len - 1; |
618 | 619 |
619 return first; | 620 return first; |
620 } | 621 } |
621 | 622 |
622 function ObservedArrayUnshift() { | 623 function ObservedArrayUnshift() { |
(...skipping 18 matching lines...) Expand all Loading... |
641 | 642 |
642 function ArrayUnshift(arg1) { // length == 1 | 643 function ArrayUnshift(arg1) { // length == 1 |
643 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift"); | 644 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift"); |
644 | 645 |
645 if (%IsObserved(this)) | 646 if (%IsObserved(this)) |
646 return ObservedArrayUnshift.apply(this, arguments); | 647 return ObservedArrayUnshift.apply(this, arguments); |
647 | 648 |
648 var array = TO_OBJECT_INLINE(this); | 649 var array = TO_OBJECT_INLINE(this); |
649 var len = TO_UINT32(array.length); | 650 var len = TO_UINT32(array.length); |
650 var num_arguments = %_ArgumentsLength(); | 651 var num_arguments = %_ArgumentsLength(); |
651 var is_sealed = ObjectIsSealed(array); | |
652 | 652 |
653 if (IS_ARRAY(array) && !is_sealed && len > 0) { | 653 if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) && |
654 SmartMove(array, 0, 0, len, num_arguments); | 654 !ObjectIsSealed(array)) { |
| 655 SparseMove(array, 0, 0, len, num_arguments); |
655 } else { | 656 } else { |
656 SimpleMove(array, 0, 0, len, num_arguments); | 657 SimpleMove(array, 0, 0, len, num_arguments); |
657 } | 658 } |
658 | 659 |
659 for (var i = 0; i < num_arguments; i++) { | 660 for (var i = 0; i < num_arguments; i++) { |
660 array[i] = %_Arguments(i); | 661 array[i] = %_Arguments(i); |
661 } | 662 } |
662 | 663 |
663 var new_length = len + num_arguments; | 664 var new_length = len + num_arguments; |
664 array.length = new_length; | 665 array.length = new_length; |
(...skipping 25 matching lines...) Expand all Loading... |
690 if (end_i > len) end_i = len; | 691 if (end_i > len) end_i = len; |
691 } | 692 } |
692 | 693 |
693 var result = []; | 694 var result = []; |
694 | 695 |
695 if (end_i < start_i) return result; | 696 if (end_i < start_i) return result; |
696 | 697 |
697 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { | 698 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { |
698 %NormalizeElements(array); | 699 %NormalizeElements(array); |
699 %NormalizeElements(result); | 700 %NormalizeElements(result); |
700 SmartSlice(array, start_i, end_i - start_i, len, result); | 701 SparseSlice(array, start_i, end_i - start_i, len, result); |
701 } else { | 702 } else { |
702 SimpleSlice(array, start_i, end_i - start_i, len, result); | 703 SimpleSlice(array, start_i, end_i - start_i, len, result); |
703 } | 704 } |
704 | 705 |
705 result.length = end_i - start_i; | 706 result.length = end_i - start_i; |
706 | 707 |
707 return result; | 708 return result; |
708 } | 709 } |
709 | 710 |
710 | 711 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 | 807 |
807 var changed_elements = del_count; | 808 var changed_elements = del_count; |
808 if (num_elements_to_add != del_count) { | 809 if (num_elements_to_add != del_count) { |
809 // If the slice needs to do a actually move elements after the insertion | 810 // If the slice needs to do a actually move elements after the insertion |
810 // point, then include those in the estimate of changed elements. | 811 // point, then include those in the estimate of changed elements. |
811 changed_elements += len - start_i - del_count; | 812 changed_elements += len - start_i - del_count; |
812 } | 813 } |
813 if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) { | 814 if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) { |
814 %NormalizeElements(array); | 815 %NormalizeElements(array); |
815 %NormalizeElements(deleted_elements); | 816 %NormalizeElements(deleted_elements); |
816 SmartSlice(array, start_i, del_count, len, deleted_elements); | 817 SparseSlice(array, start_i, del_count, len, deleted_elements); |
817 SmartMove(array, start_i, del_count, len, num_elements_to_add); | 818 SparseMove(array, start_i, del_count, len, num_elements_to_add); |
818 } else { | 819 } else { |
819 SimpleSlice(array, start_i, del_count, len, deleted_elements); | 820 SimpleSlice(array, start_i, del_count, len, deleted_elements); |
820 SimpleMove(array, start_i, del_count, len, num_elements_to_add); | 821 SimpleMove(array, start_i, del_count, len, num_elements_to_add); |
821 } | 822 } |
822 | 823 |
823 // Insert the arguments into the resulting array in | 824 // Insert the arguments into the resulting array in |
824 // place of the deleted elements. | 825 // place of the deleted elements. |
825 var i = start_i; | 826 var i = start_i; |
826 var arguments_index = 2; | 827 var arguments_index = 2; |
827 var arguments_length = %_ArgumentsLength(); | 828 var arguments_length = %_ArgumentsLength(); |
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 )); | 1569 )); |
1569 | 1570 |
1570 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( | 1571 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( |
1571 "join", getFunction("join", ArrayJoin), | 1572 "join", getFunction("join", ArrayJoin), |
1572 "pop", getFunction("pop", ArrayPop), | 1573 "pop", getFunction("pop", ArrayPop), |
1573 "push", getFunction("push", ArrayPush) | 1574 "push", getFunction("push", ArrayPush) |
1574 )); | 1575 )); |
1575 } | 1576 } |
1576 | 1577 |
1577 SetUpArray(); | 1578 SetUpArray(); |
OLD | NEW |