| 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 |