| 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 (function(global, utils) { | 5 (function(global, utils) { |
| 6 | 6 |
| 7 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
| 10 | 10 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 var length = indices.length; | 59 var length = indices.length; |
| 60 for (var k = 0; k < length; ++k) { | 60 for (var k = 0; k < length; ++k) { |
| 61 var key = indices[k]; | 61 var key = indices[k]; |
| 62 if (!IS_UNDEFINED(key)) { | 62 if (!IS_UNDEFINED(key)) { |
| 63 var e = array[key]; | 63 var e = array[key]; |
| 64 if (!IS_UNDEFINED(e) || key in array) { | 64 if (!IS_UNDEFINED(e) || key in array) { |
| 65 keys.push(key); | 65 keys.push(key); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 %_CallFunction(keys, function(a, b) { return a - b; }, ArraySort); | 69 keys.sort(function(a, b) { return a - b; }); |
| 70 } | 70 } |
| 71 return keys; | 71 return keys; |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 function SparseJoinWithSeparatorJS(array, len, convert, separator) { | 75 function SparseJoinWithSeparatorJS(array, len, convert, separator) { |
| 76 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); | 76 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); |
| 77 var totalLength = 0; | 77 var totalLength = 0; |
| 78 var elements = new InternalArray(keys.length * 2); | 78 var elements = new InternalArray(keys.length * 2); |
| 79 var previousKey = -1; | 79 var previousKey = -1; |
| (...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 while (arguments_index < arguments_length) { | 893 while (arguments_index < arguments_length) { |
| 894 array[i++] = %_Arguments(arguments_index++); | 894 array[i++] = %_Arguments(arguments_index++); |
| 895 } | 895 } |
| 896 array.length = len - del_count + num_elements_to_add; | 896 array.length = len - del_count + num_elements_to_add; |
| 897 | 897 |
| 898 // Return the deleted elements. | 898 // Return the deleted elements. |
| 899 return deleted_elements; | 899 return deleted_elements; |
| 900 } | 900 } |
| 901 | 901 |
| 902 | 902 |
| 903 function InnerArraySort(length, comparefn) { | 903 function InnerArraySort(array, length, comparefn) { |
| 904 // In-place QuickSort algorithm. | 904 // In-place QuickSort algorithm. |
| 905 // For short (length <= 22) arrays, insertion sort is used for efficiency. | 905 // For short (length <= 22) arrays, insertion sort is used for efficiency. |
| 906 | 906 |
| 907 if (!IS_CALLABLE(comparefn)) { | 907 if (!IS_CALLABLE(comparefn)) { |
| 908 comparefn = function (x, y) { | 908 comparefn = function (x, y) { |
| 909 if (x === y) return 0; | 909 if (x === y) return 0; |
| 910 if (%_IsSmi(x) && %_IsSmi(y)) { | 910 if (%_IsSmi(x) && %_IsSmi(y)) { |
| 911 return %SmiLexicographicCompare(x, y); | 911 return %SmiLexicographicCompare(x, y); |
| 912 } | 912 } |
| 913 x = ToString(x); | 913 x = ToString(x); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 obj[i] = UNDEFINED; | 1138 obj[i] = UNDEFINED; |
| 1139 } else { | 1139 } else { |
| 1140 delete obj[i]; | 1140 delete obj[i]; |
| 1141 } | 1141 } |
| 1142 } | 1142 } |
| 1143 | 1143 |
| 1144 // Return the number of defined elements. | 1144 // Return the number of defined elements. |
| 1145 return first_undefined; | 1145 return first_undefined; |
| 1146 }; | 1146 }; |
| 1147 | 1147 |
| 1148 if (length < 2) return this; | 1148 if (length < 2) return array; |
| 1149 | 1149 |
| 1150 var is_array = IS_ARRAY(this); | 1150 var is_array = IS_ARRAY(array); |
| 1151 var max_prototype_element; | 1151 var max_prototype_element; |
| 1152 if (!is_array) { | 1152 if (!is_array) { |
| 1153 // For compatibility with JSC, we also sort elements inherited from | 1153 // For compatibility with JSC, we also sort elements inherited from |
| 1154 // the prototype chain on non-Array objects. | 1154 // the prototype chain on non-Array objects. |
| 1155 // We do this by copying them to this object and sorting only | 1155 // We do this by copying them to this object and sorting only |
| 1156 // own elements. This is not very efficient, but sorting with | 1156 // own elements. This is not very efficient, but sorting with |
| 1157 // inherited elements happens very, very rarely, if at all. | 1157 // inherited elements happens very, very rarely, if at all. |
| 1158 // The specification allows "implementation dependent" behavior | 1158 // The specification allows "implementation dependent" behavior |
| 1159 // if an element on the prototype chain has an element that | 1159 // if an element on the prototype chain has an element that |
| 1160 // might interact with sorting. | 1160 // might interact with sorting. |
| 1161 max_prototype_element = CopyFromPrototype(this, length); | 1161 max_prototype_element = CopyFromPrototype(array, length); |
| 1162 } | 1162 } |
| 1163 | 1163 |
| 1164 // %RemoveArrayHoles returns -1 if fast removal is not supported. | 1164 // %RemoveArrayHoles returns -1 if fast removal is not supported. |
| 1165 var num_non_undefined = %RemoveArrayHoles(this, length); | 1165 var num_non_undefined = %RemoveArrayHoles(array, length); |
| 1166 | 1166 |
| 1167 if (num_non_undefined == -1) { | 1167 if (num_non_undefined == -1) { |
| 1168 // The array is observed, or there were indexed accessors in the array. | 1168 // The array is observed, or there were indexed accessors in the array. |
| 1169 // Move array holes and undefineds to the end using a Javascript function | 1169 // Move array holes and undefineds to the end using a Javascript function |
| 1170 // that is safe in the presence of accessors and is observable. | 1170 // that is safe in the presence of accessors and is observable. |
| 1171 num_non_undefined = SafeRemoveArrayHoles(this); | 1171 num_non_undefined = SafeRemoveArrayHoles(array); |
| 1172 } | 1172 } |
| 1173 | 1173 |
| 1174 QuickSort(this, 0, num_non_undefined); | 1174 QuickSort(array, 0, num_non_undefined); |
| 1175 | 1175 |
| 1176 if (!is_array && (num_non_undefined + 1 < max_prototype_element)) { | 1176 if (!is_array && (num_non_undefined + 1 < max_prototype_element)) { |
| 1177 // For compatibility with JSC, we shadow any elements in the prototype | 1177 // For compatibility with JSC, we shadow any elements in the prototype |
| 1178 // chain that has become exposed by sort moving a hole to its position. | 1178 // chain that has become exposed by sort moving a hole to its position. |
| 1179 ShadowPrototypeElements(this, num_non_undefined, max_prototype_element); | 1179 ShadowPrototypeElements(array, num_non_undefined, max_prototype_element); |
| 1180 } | 1180 } |
| 1181 | 1181 |
| 1182 return this; | 1182 return array; |
| 1183 } | 1183 } |
| 1184 | 1184 |
| 1185 | 1185 |
| 1186 function ArraySort(comparefn) { | 1186 function ArraySort(comparefn) { |
| 1187 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort"); | 1187 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort"); |
| 1188 | 1188 |
| 1189 var array = TO_OBJECT(this); | 1189 var array = TO_OBJECT(this); |
| 1190 var length = TO_UINT32(array.length); | 1190 var length = TO_UINT32(array.length); |
| 1191 return %_CallFunction(array, length, comparefn, InnerArraySort); | 1191 return InnerArraySort(array, length, comparefn); |
| 1192 } | 1192 } |
| 1193 | 1193 |
| 1194 | 1194 |
| 1195 // The following functions cannot be made efficient on sparse arrays while | 1195 // The following functions cannot be made efficient on sparse arrays while |
| 1196 // preserving the semantics, since the calls to the receiver function can add | 1196 // preserving the semantics, since the calls to the receiver function can add |
| 1197 // or delete elements from the array. | 1197 // or delete elements from the array. |
| 1198 function InnerArrayFilter(f, receiver, array, length) { | 1198 function InnerArrayFilter(f, receiver, array, length) { |
| 1199 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); | 1199 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); |
| 1200 var needs_wrapper = false; | 1200 var needs_wrapper = false; |
| 1201 if (IS_NULL(receiver)) { | 1201 if (IS_NULL(receiver)) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 var result = new GlobalArray(); | 1375 var result = new GlobalArray(); |
| 1376 %MoveArrayContents(accumulator, result); | 1376 %MoveArrayContents(accumulator, result); |
| 1377 return result; | 1377 return result; |
| 1378 } | 1378 } |
| 1379 | 1379 |
| 1380 | 1380 |
| 1381 // For .indexOf, we don't need to pass in the number of arguments | 1381 // For .indexOf, we don't need to pass in the number of arguments |
| 1382 // at the callsite since ToInteger(undefined) == 0; however, for | 1382 // at the callsite since ToInteger(undefined) == 0; however, for |
| 1383 // .lastIndexOf, we need to pass it, since the behavior for passing | 1383 // .lastIndexOf, we need to pass it, since the behavior for passing |
| 1384 // undefined is 0 but for not including the argument is length-1. | 1384 // undefined is 0 but for not including the argument is length-1. |
| 1385 function InnerArrayIndexOf(element, index, length) { | 1385 function InnerArrayIndexOf(array, element, index, length) { |
| 1386 if (length == 0) return -1; | 1386 if (length == 0) return -1; |
| 1387 if (IS_UNDEFINED(index)) { | 1387 if (IS_UNDEFINED(index)) { |
| 1388 index = 0; | 1388 index = 0; |
| 1389 } else { | 1389 } else { |
| 1390 index = TO_INTEGER(index); | 1390 index = TO_INTEGER(index); |
| 1391 // If index is negative, index from the end of the array. | 1391 // If index is negative, index from the end of the array. |
| 1392 if (index < 0) { | 1392 if (index < 0) { |
| 1393 index = length + index; | 1393 index = length + index; |
| 1394 // If index is still negative, search the entire array. | 1394 // If index is still negative, search the entire array. |
| 1395 if (index < 0) index = 0; | 1395 if (index < 0) index = 0; |
| 1396 } | 1396 } |
| 1397 } | 1397 } |
| 1398 var min = index; | 1398 var min = index; |
| 1399 var max = length; | 1399 var max = length; |
| 1400 if (UseSparseVariant(this, length, IS_ARRAY(this), max - min)) { | 1400 if (UseSparseVariant(array, length, IS_ARRAY(array), max - min)) { |
| 1401 %NormalizeElements(this); | 1401 %NormalizeElements(array); |
| 1402 var indices = %GetArrayKeys(this, length); | 1402 var indices = %GetArrayKeys(array, length); |
| 1403 if (IS_NUMBER(indices)) { | 1403 if (IS_NUMBER(indices)) { |
| 1404 // It's an interval. | 1404 // It's an interval. |
| 1405 max = indices; // Capped by length already. | 1405 max = indices; // Capped by length already. |
| 1406 // Fall through to loop below. | 1406 // Fall through to loop below. |
| 1407 } else { | 1407 } else { |
| 1408 if (indices.length == 0) return -1; | 1408 if (indices.length == 0) return -1; |
| 1409 // Get all the keys in sorted order. | 1409 // Get all the keys in sorted order. |
| 1410 var sortedKeys = GetSortedArrayKeys(this, indices); | 1410 var sortedKeys = GetSortedArrayKeys(array, indices); |
| 1411 var n = sortedKeys.length; | 1411 var n = sortedKeys.length; |
| 1412 var i = 0; | 1412 var i = 0; |
| 1413 while (i < n && sortedKeys[i] < index) i++; | 1413 while (i < n && sortedKeys[i] < index) i++; |
| 1414 while (i < n) { | 1414 while (i < n) { |
| 1415 var key = sortedKeys[i]; | 1415 var key = sortedKeys[i]; |
| 1416 if (!IS_UNDEFINED(key) && this[key] === element) return key; | 1416 if (!IS_UNDEFINED(key) && array[key] === element) return key; |
| 1417 i++; | 1417 i++; |
| 1418 } | 1418 } |
| 1419 return -1; | 1419 return -1; |
| 1420 } | 1420 } |
| 1421 } | 1421 } |
| 1422 // Lookup through the array. | 1422 // Lookup through the array. |
| 1423 if (!IS_UNDEFINED(element)) { | 1423 if (!IS_UNDEFINED(element)) { |
| 1424 for (var i = min; i < max; i++) { | 1424 for (var i = min; i < max; i++) { |
| 1425 if (this[i] === element) return i; | 1425 if (array[i] === element) return i; |
| 1426 } | 1426 } |
| 1427 return -1; | 1427 return -1; |
| 1428 } | 1428 } |
| 1429 // Lookup through the array. | 1429 // Lookup through the array. |
| 1430 for (var i = min; i < max; i++) { | 1430 for (var i = min; i < max; i++) { |
| 1431 if (IS_UNDEFINED(this[i]) && i in this) { | 1431 if (IS_UNDEFINED(array[i]) && i in array) { |
| 1432 return i; | 1432 return i; |
| 1433 } | 1433 } |
| 1434 } | 1434 } |
| 1435 return -1; | 1435 return -1; |
| 1436 } | 1436 } |
| 1437 | 1437 |
| 1438 | 1438 |
| 1439 function ArrayIndexOf(element, index) { | 1439 function ArrayIndexOf(element, index) { |
| 1440 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.indexOf"); | 1440 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.indexOf"); |
| 1441 | 1441 |
| 1442 var length = TO_UINT32(this.length); | 1442 var length = TO_UINT32(this.length); |
| 1443 return %_CallFunction(this, element, index, length, InnerArrayIndexOf); | 1443 return InnerArrayIndexOf(this, element, index, length); |
| 1444 } | 1444 } |
| 1445 | 1445 |
| 1446 | 1446 |
| 1447 function InnerArrayLastIndexOf(element, index, length, argumentsLength) { | 1447 function InnerArrayLastIndexOf(array, element, index, length, argumentsLength) { |
| 1448 if (length == 0) return -1; | 1448 if (length == 0) return -1; |
| 1449 if (argumentsLength < 2) { | 1449 if (argumentsLength < 2) { |
| 1450 index = length - 1; | 1450 index = length - 1; |
| 1451 } else { | 1451 } else { |
| 1452 index = TO_INTEGER(index); | 1452 index = TO_INTEGER(index); |
| 1453 // If index is negative, index from end of the array. | 1453 // If index is negative, index from end of the array. |
| 1454 if (index < 0) index += length; | 1454 if (index < 0) index += length; |
| 1455 // If index is still negative, do not search the array. | 1455 // If index is still negative, do not search the array. |
| 1456 if (index < 0) return -1; | 1456 if (index < 0) return -1; |
| 1457 else if (index >= length) index = length - 1; | 1457 else if (index >= length) index = length - 1; |
| 1458 } | 1458 } |
| 1459 var min = 0; | 1459 var min = 0; |
| 1460 var max = index; | 1460 var max = index; |
| 1461 if (UseSparseVariant(this, length, IS_ARRAY(this), index)) { | 1461 if (UseSparseVariant(array, length, IS_ARRAY(array), index)) { |
| 1462 %NormalizeElements(this); | 1462 %NormalizeElements(array); |
| 1463 var indices = %GetArrayKeys(this, index + 1); | 1463 var indices = %GetArrayKeys(array, index + 1); |
| 1464 if (IS_NUMBER(indices)) { | 1464 if (IS_NUMBER(indices)) { |
| 1465 // It's an interval. | 1465 // It's an interval. |
| 1466 max = indices; // Capped by index already. | 1466 max = indices; // Capped by index already. |
| 1467 // Fall through to loop below. | 1467 // Fall through to loop below. |
| 1468 } else { | 1468 } else { |
| 1469 if (indices.length == 0) return -1; | 1469 if (indices.length == 0) return -1; |
| 1470 // Get all the keys in sorted order. | 1470 // Get all the keys in sorted order. |
| 1471 var sortedKeys = GetSortedArrayKeys(this, indices); | 1471 var sortedKeys = GetSortedArrayKeys(array, indices); |
| 1472 var i = sortedKeys.length - 1; | 1472 var i = sortedKeys.length - 1; |
| 1473 while (i >= 0) { | 1473 while (i >= 0) { |
| 1474 var key = sortedKeys[i]; | 1474 var key = sortedKeys[i]; |
| 1475 if (!IS_UNDEFINED(key) && this[key] === element) return key; | 1475 if (!IS_UNDEFINED(key) && array[key] === element) return key; |
| 1476 i--; | 1476 i--; |
| 1477 } | 1477 } |
| 1478 return -1; | 1478 return -1; |
| 1479 } | 1479 } |
| 1480 } | 1480 } |
| 1481 // Lookup through the array. | 1481 // Lookup through the array. |
| 1482 if (!IS_UNDEFINED(element)) { | 1482 if (!IS_UNDEFINED(element)) { |
| 1483 for (var i = max; i >= min; i--) { | 1483 for (var i = max; i >= min; i--) { |
| 1484 if (this[i] === element) return i; | 1484 if (array[i] === element) return i; |
| 1485 } | 1485 } |
| 1486 return -1; | 1486 return -1; |
| 1487 } | 1487 } |
| 1488 for (var i = max; i >= min; i--) { | 1488 for (var i = max; i >= min; i--) { |
| 1489 if (IS_UNDEFINED(this[i]) && i in this) { | 1489 if (IS_UNDEFINED(array[i]) && i in array) { |
| 1490 return i; | 1490 return i; |
| 1491 } | 1491 } |
| 1492 } | 1492 } |
| 1493 return -1; | 1493 return -1; |
| 1494 } | 1494 } |
| 1495 | 1495 |
| 1496 | 1496 |
| 1497 function ArrayLastIndexOf(element, index) { | 1497 function ArrayLastIndexOf(element, index) { |
| 1498 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf"); | 1498 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf"); |
| 1499 | 1499 |
| 1500 var length = TO_UINT32(this.length); | 1500 var length = TO_UINT32(this.length); |
| 1501 return %_CallFunction(this, element, index, length, | 1501 return InnerArrayLastIndexOf(this, element, index, length, |
| 1502 %_ArgumentsLength(), InnerArrayLastIndexOf); | 1502 %_ArgumentsLength()); |
| 1503 } | 1503 } |
| 1504 | 1504 |
| 1505 | 1505 |
| 1506 function InnerArrayReduce(callback, current, array, length, argumentsLength) { | 1506 function InnerArrayReduce(callback, current, array, length, argumentsLength) { |
| 1507 if (!IS_CALLABLE(callback)) { | 1507 if (!IS_CALLABLE(callback)) { |
| 1508 throw MakeTypeError(kCalledNonCallable, callback); | 1508 throw MakeTypeError(kCalledNonCallable, callback); |
| 1509 } | 1509 } |
| 1510 | 1510 |
| 1511 var is_array = IS_ARRAY(array); | 1511 var is_array = IS_ARRAY(array); |
| 1512 var i = 0; | 1512 var i = 0; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 // The internal Array prototype doesn't need to be fancy, since it's never | 1665 // The internal Array prototype doesn't need to be fancy, since it's never |
| 1666 // exposed to user code. | 1666 // exposed to user code. |
| 1667 // Adding only the functions that are actually used. | 1667 // Adding only the functions that are actually used. |
| 1668 utils.SetUpLockedPrototype(InternalArray, GlobalArray(), [ | 1668 utils.SetUpLockedPrototype(InternalArray, GlobalArray(), [ |
| 1669 "concat", getFunction("concat", ArrayConcatJS), | 1669 "concat", getFunction("concat", ArrayConcatJS), |
| 1670 "indexOf", getFunction("indexOf", ArrayIndexOf), | 1670 "indexOf", getFunction("indexOf", ArrayIndexOf), |
| 1671 "join", getFunction("join", ArrayJoin), | 1671 "join", getFunction("join", ArrayJoin), |
| 1672 "pop", getFunction("pop", ArrayPop), | 1672 "pop", getFunction("pop", ArrayPop), |
| 1673 "push", getFunction("push", ArrayPush), | 1673 "push", getFunction("push", ArrayPush), |
| 1674 "shift", getFunction("shift", ArrayShift), | 1674 "shift", getFunction("shift", ArrayShift), |
| 1675 "sort", getFunction("sort", ArraySort), |
| 1675 "splice", getFunction("splice", ArraySplice) | 1676 "splice", getFunction("splice", ArraySplice) |
| 1676 ]); | 1677 ]); |
| 1677 | 1678 |
| 1678 utils.SetUpLockedPrototype(InternalPackedArray, GlobalArray(), [ | 1679 utils.SetUpLockedPrototype(InternalPackedArray, GlobalArray(), [ |
| 1679 "join", getFunction("join", ArrayJoin), | 1680 "join", getFunction("join", ArrayJoin), |
| 1680 "pop", getFunction("pop", ArrayPop), | 1681 "pop", getFunction("pop", ArrayPop), |
| 1681 "push", getFunction("push", ArrayPush), | 1682 "push", getFunction("push", ArrayPush), |
| 1682 "shift", getFunction("shift", ArrayShift) | 1683 "shift", getFunction("shift", ArrayShift) |
| 1683 ]); | 1684 ]); |
| 1684 | 1685 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1709 "array_concat", ArrayConcatJS, | 1710 "array_concat", ArrayConcatJS, |
| 1710 "array_pop", ArrayPop, | 1711 "array_pop", ArrayPop, |
| 1711 "array_push", ArrayPush, | 1712 "array_push", ArrayPush, |
| 1712 "array_shift", ArrayShift, | 1713 "array_shift", ArrayShift, |
| 1713 "array_splice", ArraySplice, | 1714 "array_splice", ArraySplice, |
| 1714 "array_slice", ArraySlice, | 1715 "array_slice", ArraySlice, |
| 1715 "array_unshift", ArrayUnshift, | 1716 "array_unshift", ArrayUnshift, |
| 1716 ]); | 1717 ]); |
| 1717 | 1718 |
| 1718 }); | 1719 }); |
| OLD | NEW |