Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 keys.sort(function(a, b) { return a - b; }); | 65 keys.sort(function(a, b) { return a - b; }); |
| 66 return keys; | 66 return keys; |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 // Optimized for sparse arrays if separator is ''. | 70 // Optimized for sparse arrays if separator is ''. |
| 71 function SparseJoin(array, len, convert) { | 71 function SparseJoin(array, len, convert) { |
| 72 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); | 72 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); |
| 73 var builder = new StringBuilder(); | |
| 74 var last_key = -1; | 73 var last_key = -1; |
| 75 var keys_length = keys.length; | 74 var keys_length = keys.length; |
| 75 | |
| 76 var elements = new $Array(keys_length); | |
| 77 var elements_length = 0; | |
| 78 | |
| 76 for (var i = 0; i < keys_length; i++) { | 79 for (var i = 0; i < keys_length; i++) { |
| 77 var key = keys[i]; | 80 var key = keys[i]; |
| 78 if (key != last_key) { | 81 if (key != last_key) { |
| 79 var e = array[key]; | 82 var e = array[key]; |
| 80 if (typeof(e) !== 'string') e = convert(e); | 83 if (!IS_STRING(e)) e = convert(e); |
| 81 builder.add(e); | 84 elements[elements_length++] = e; |
| 82 last_key = key; | 85 last_key = key; |
| 83 } | 86 } |
| 84 } | 87 } |
| 85 return builder.generate(); | 88 return %StringBuilderConcat(elements, elements_length, ''); |
| 86 } | 89 } |
| 87 | 90 |
| 88 | 91 |
| 89 function UseSparseVariant(object, length, is_array) { | 92 function UseSparseVariant(object, length, is_array) { |
| 90 return is_array && | 93 return is_array && |
| 91 length > 1000 && | 94 length > 1000 && |
| 92 (!%_IsSmi(length) || | 95 (!%_IsSmi(length) || |
| 93 %EstimateNumberOfElements(object) < (length >> 2)); | 96 %EstimateNumberOfElements(object) < (length >> 2)); |
| 94 } | 97 } |
| 95 | 98 |
| 96 | 99 |
| 97 function Join(array, length, separator, convert) { | 100 function Join(array, length, separator, convert) { |
| 98 if (length == 0) return ''; | 101 if (length == 0) return ''; |
| 99 | 102 |
| 100 var is_array = IS_ARRAY(array); | 103 var is_array = IS_ARRAY(array); |
| 101 | 104 |
| 102 if (is_array) { | 105 if (is_array) { |
| 103 // If the array is cyclic, return the empty string for already | 106 // If the array is cyclic, return the empty string for already |
| 104 // visited arrays. | 107 // visited arrays. |
| 105 if (!%PushIfAbsent(visited_arrays, array)) return ''; | 108 if (!%PushIfAbsent(visited_arrays, array)) return ''; |
| 106 } | 109 } |
| 107 | 110 |
| 108 // Attempt to convert the elements. | 111 // Attempt to convert the elements. |
| 109 try { | 112 try { |
| 110 if (UseSparseVariant(array, length, is_array) && separator === '') { | 113 if (UseSparseVariant(array, length, is_array) && (separator.length == 0)) { |
|
Erik Corry
2010/01/06 14:03:57
I don't think the extra () around separator.length
| |
| 111 return SparseJoin(array, length, convert); | 114 return SparseJoin(array, length, convert); |
| 112 } | 115 } |
| 113 | 116 |
| 114 // Fast case for one-element arrays. | 117 // Fast case for one-element arrays. |
| 115 if (length == 1) { | 118 if (length == 1) { |
| 116 var e = array[0]; | 119 var e = array[0]; |
| 117 if (!IS_UNDEFINED(e) || (0 in array)) { | 120 if (!IS_UNDEFINED(e) || (0 in array)) { |
| 118 if (typeof(e) === 'string') return e; | 121 if (IS_STRING(e)) return e; |
| 119 return convert(e); | 122 return convert(e); |
| 120 } | 123 } |
| 121 } | 124 } |
| 122 | 125 |
| 123 var builder = new StringBuilder(); | 126 // Construct an array for the elements. |
| 127 var elements; | |
| 128 var elements_length = 0; | |
| 124 | 129 |
| 125 // We pull the empty separator check outside the loop for speed! | 130 // We pull the empty separator check outside the loop for speed! |
| 126 if (separator.length == 0) { | 131 if (separator.length == 0) { |
| 132 elements = new $Array(length); | |
| 127 for (var i = 0; i < length; i++) { | 133 for (var i = 0; i < length; i++) { |
| 128 var e = array[i]; | 134 var e = array[i]; |
| 129 if (!IS_UNDEFINED(e) || (i in array)) { | 135 if (!IS_UNDEFINED(e) || (i in array)) { |
| 130 if (typeof(e) !== 'string') e = convert(e); | 136 if (!IS_STRING(e)) e = convert(e); |
| 131 if (e.length > 0) { | 137 elements[elements_length++] = e; |
| 132 var elements = builder.elements; | |
| 133 elements[elements.length] = e; | |
| 134 } | |
| 135 } | 138 } |
| 136 } | 139 } |
| 137 } else { | 140 } else { |
| 141 elements = new $Array(length << 1); | |
| 138 for (var i = 0; i < length; i++) { | 142 for (var i = 0; i < length; i++) { |
| 139 var e = array[i]; | 143 var e = array[i]; |
| 140 if (i != 0) builder.add(separator); | 144 if (i != 0) elements[elements_length++] = separator; |
| 141 if (!IS_UNDEFINED(e) || (i in array)) { | 145 if (!IS_UNDEFINED(e) || (i in array)) { |
| 142 if (typeof(e) !== 'string') e = convert(e); | 146 if (!IS_STRING(e)) e = convert(e); |
| 143 if (e.length > 0) { | 147 elements[elements_length++] = e; |
| 144 var elements = builder.elements; | |
| 145 elements[elements.length] = e; | |
| 146 } | |
| 147 } | 148 } |
| 148 } | 149 } |
| 149 } | 150 } |
| 150 return builder.generate(); | 151 return %StringBuilderConcat(elements, elements_length, ''); |
| 151 } finally { | 152 } finally { |
| 152 // Make sure to pop the visited array no matter what happens. | 153 // Make sure to pop the visited array no matter what happens. |
| 153 if (is_array) visited_arrays.pop(); | 154 if (is_array) visited_arrays.pop(); |
| 154 } | 155 } |
| 155 } | 156 } |
| 156 | 157 |
| 157 | 158 |
| 158 function ConvertToString(e) { | 159 function ConvertToString(e) { |
| 159 if (typeof(e) === 'string') return e; | |
| 160 if (e == null) return ''; | 160 if (e == null) return ''; |
| 161 else return ToString(e); | 161 else return ToString(e); |
| 162 } | 162 } |
| 163 | 163 |
| 164 | 164 |
| 165 function ConvertToLocaleString(e) { | 165 function ConvertToLocaleString(e) { |
| 166 if (typeof(e) === 'string') return e; | 166 if (e == null) { |
| 167 if (e == null) return ''; | 167 return ''; |
| 168 else { | 168 } else { |
| 169 // e_obj's toLocaleString might be overwritten, check if it is a function. | 169 // e_obj's toLocaleString might be overwritten, check if it is a function. |
| 170 // Call ToString if toLocaleString is not a function. | 170 // Call ToString if toLocaleString is not a function. |
| 171 // See issue 877615. | 171 // See issue 877615. |
| 172 var e_obj = ToObject(e); | 172 var e_obj = ToObject(e); |
| 173 if (IS_FUNCTION(e_obj.toLocaleString)) | 173 if (IS_FUNCTION(e_obj.toLocaleString)) |
| 174 return ToString(e_obj.toLocaleString()); | 174 return ToString(e_obj.toLocaleString()); |
| 175 else | 175 else |
| 176 return ToString(e); | 176 return ToString(e); |
| 177 } | 177 } |
| 178 } | 178 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 352 | 352 |
| 353 function ArrayToLocaleString() { | 353 function ArrayToLocaleString() { |
| 354 if (!IS_ARRAY(this)) { | 354 if (!IS_ARRAY(this)) { |
| 355 throw new $TypeError('Array.prototype.toString is not generic'); | 355 throw new $TypeError('Array.prototype.toString is not generic'); |
| 356 } | 356 } |
| 357 return Join(this, this.length, ',', ConvertToLocaleString); | 357 return Join(this, this.length, ',', ConvertToLocaleString); |
| 358 } | 358 } |
| 359 | 359 |
| 360 | 360 |
| 361 function ArrayJoin(separator) { | 361 function ArrayJoin(separator) { |
| 362 if (IS_UNDEFINED(separator)) separator = ','; | 362 if (IS_UNDEFINED(separator)) { |
| 363 else separator = ToString(separator); | 363 separator = ','; |
| 364 return Join(this, ToUint32(this.length), separator, ConvertToString); | 364 } else if (!IS_STRING(separator)) { |
| 365 separator = ToString(separator); | |
| 366 } | |
| 367 var length = TO_UINT32(this.length); | |
| 368 return Join(this, length, separator, ConvertToString); | |
| 365 } | 369 } |
| 366 | 370 |
| 367 | 371 |
| 368 // Removes the last element from the array and returns it. See | 372 // Removes the last element from the array and returns it. See |
| 369 // ECMA-262, section 15.4.4.6. | 373 // ECMA-262, section 15.4.4.6. |
| 370 function ArrayPop() { | 374 function ArrayPop() { |
| 371 var n = ToUint32(this.length); | 375 var n = TO_UINT32(this.length); |
| 372 if (n == 0) { | 376 if (n == 0) { |
| 373 this.length = n; | 377 this.length = n; |
| 374 return; | 378 return; |
| 375 } | 379 } |
| 376 n--; | 380 n--; |
| 377 var value = this[n]; | 381 var value = this[n]; |
| 378 this.length = n; | 382 this.length = n; |
| 379 delete this[n]; | 383 delete this[n]; |
| 380 return value; | 384 return value; |
| 381 } | 385 } |
| 382 | 386 |
| 383 | 387 |
| 384 // Appends the arguments to the end of the array and returns the new | 388 // Appends the arguments to the end of the array and returns the new |
| 385 // length of the array. See ECMA-262, section 15.4.4.7. | 389 // length of the array. See ECMA-262, section 15.4.4.7. |
| 386 function ArrayPush() { | 390 function ArrayPush() { |
| 387 var n = ToUint32(this.length); | 391 var n = TO_UINT32(this.length); |
| 388 var m = %_ArgumentsLength(); | 392 var m = %_ArgumentsLength(); |
| 389 for (var i = 0; i < m; i++) { | 393 for (var i = 0; i < m; i++) { |
| 390 this[i+n] = %_Arguments(i); | 394 this[i+n] = %_Arguments(i); |
| 391 } | 395 } |
| 392 this.length = n + m; | 396 this.length = n + m; |
| 393 return this.length; | 397 return this.length; |
| 394 } | 398 } |
| 395 | 399 |
| 396 | 400 |
| 397 function ArrayConcat(arg1) { // length == 1 | 401 function ArrayConcat(arg1) { // length == 1 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 if (!IS_UNDEFINED(current_j) || high in array) { | 449 if (!IS_UNDEFINED(current_j) || high in array) { |
| 446 array[low] = current_j; | 450 array[low] = current_j; |
| 447 delete array[high]; | 451 delete array[high]; |
| 448 } | 452 } |
| 449 } | 453 } |
| 450 } | 454 } |
| 451 } | 455 } |
| 452 | 456 |
| 453 | 457 |
| 454 function ArrayReverse() { | 458 function ArrayReverse() { |
| 455 var j = ToUint32(this.length) - 1; | 459 var j = TO_UINT32(this.length) - 1; |
| 456 | 460 |
| 457 if (UseSparseVariant(this, j, IS_ARRAY(this))) { | 461 if (UseSparseVariant(this, j, IS_ARRAY(this))) { |
| 458 SparseReverse(this, j+1); | 462 SparseReverse(this, j+1); |
| 459 return this; | 463 return this; |
| 460 } | 464 } |
| 461 | 465 |
| 462 for (var i = 0; i < j; i++, j--) { | 466 for (var i = 0; i < j; i++, j--) { |
| 463 var current_i = this[i]; | 467 var current_i = this[i]; |
| 464 if (!IS_UNDEFINED(current_i) || i in this) { | 468 if (!IS_UNDEFINED(current_i) || i in this) { |
| 465 var current_j = this[j]; | 469 var current_j = this[j]; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 476 this[i] = current_j; | 480 this[i] = current_j; |
| 477 delete this[j]; | 481 delete this[j]; |
| 478 } | 482 } |
| 479 } | 483 } |
| 480 } | 484 } |
| 481 return this; | 485 return this; |
| 482 } | 486 } |
| 483 | 487 |
| 484 | 488 |
| 485 function ArrayShift() { | 489 function ArrayShift() { |
| 486 var len = ToUint32(this.length); | 490 var len = TO_UINT32(this.length); |
| 487 | 491 |
| 488 if (len === 0) { | 492 if (len === 0) { |
| 489 this.length = 0; | 493 this.length = 0; |
| 490 return; | 494 return; |
| 491 } | 495 } |
| 492 | 496 |
| 493 var first = this[0]; | 497 var first = this[0]; |
| 494 | 498 |
| 495 if (IS_ARRAY(this)) | 499 if (IS_ARRAY(this)) |
| 496 SmartMove(this, 0, 1, len, 0); | 500 SmartMove(this, 0, 1, len, 0); |
| 497 else | 501 else |
| 498 SimpleMove(this, 0, 1, len, 0); | 502 SimpleMove(this, 0, 1, len, 0); |
| 499 | 503 |
| 500 this.length = len - 1; | 504 this.length = len - 1; |
| 501 | 505 |
| 502 return first; | 506 return first; |
| 503 } | 507 } |
| 504 | 508 |
| 505 | 509 |
| 506 function ArrayUnshift(arg1) { // length == 1 | 510 function ArrayUnshift(arg1) { // length == 1 |
| 507 var len = ToUint32(this.length); | 511 var len = TO_UINT32(this.length); |
| 508 var num_arguments = %_ArgumentsLength(); | 512 var num_arguments = %_ArgumentsLength(); |
| 509 | 513 |
| 510 if (IS_ARRAY(this)) | 514 if (IS_ARRAY(this)) |
| 511 SmartMove(this, 0, 0, len, num_arguments); | 515 SmartMove(this, 0, 0, len, num_arguments); |
| 512 else | 516 else |
| 513 SimpleMove(this, 0, 0, len, num_arguments); | 517 SimpleMove(this, 0, 0, len, num_arguments); |
| 514 | 518 |
| 515 for (var i = 0; i < num_arguments; i++) { | 519 for (var i = 0; i < num_arguments; i++) { |
| 516 this[i] = %_Arguments(i); | 520 this[i] = %_Arguments(i); |
| 517 } | 521 } |
| 518 | 522 |
| 519 this.length = len + num_arguments; | 523 this.length = len + num_arguments; |
| 520 | 524 |
| 521 return len + num_arguments; | 525 return len + num_arguments; |
| 522 } | 526 } |
| 523 | 527 |
| 524 | 528 |
| 525 function ArraySlice(start, end) { | 529 function ArraySlice(start, end) { |
| 526 var len = ToUint32(this.length); | 530 var len = TO_UINT32(this.length); |
| 527 var start_i = TO_INTEGER(start); | 531 var start_i = TO_INTEGER(start); |
| 528 var end_i = len; | 532 var end_i = len; |
| 529 | 533 |
| 530 if (end !== void 0) end_i = TO_INTEGER(end); | 534 if (end !== void 0) end_i = TO_INTEGER(end); |
| 531 | 535 |
| 532 if (start_i < 0) { | 536 if (start_i < 0) { |
| 533 start_i += len; | 537 start_i += len; |
| 534 if (start_i < 0) start_i = 0; | 538 if (start_i < 0) start_i = 0; |
| 535 } else { | 539 } else { |
| 536 if (start_i > len) start_i = len; | 540 if (start_i > len) start_i = len; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 561 | 565 |
| 562 function ArraySplice(start, delete_count) { | 566 function ArraySplice(start, delete_count) { |
| 563 var num_arguments = %_ArgumentsLength(); | 567 var num_arguments = %_ArgumentsLength(); |
| 564 | 568 |
| 565 // SpiderMonkey and KJS return undefined in the case where no | 569 // SpiderMonkey and KJS return undefined in the case where no |
| 566 // arguments are given instead of using the implicit undefined | 570 // arguments are given instead of using the implicit undefined |
| 567 // arguments. This does not follow ECMA-262, but we do the same for | 571 // arguments. This does not follow ECMA-262, but we do the same for |
| 568 // compatibility. | 572 // compatibility. |
| 569 if (num_arguments == 0) return; | 573 if (num_arguments == 0) return; |
| 570 | 574 |
| 571 var len = ToUint32(this.length); | 575 var len = TO_UINT32(this.length); |
| 572 var start_i = TO_INTEGER(start); | 576 var start_i = TO_INTEGER(start); |
| 573 | 577 |
| 574 if (start_i < 0) { | 578 if (start_i < 0) { |
| 575 start_i += len; | 579 start_i += len; |
| 576 if (start_i < 0) start_i = 0; | 580 if (start_i < 0) start_i = 0; |
| 577 } else { | 581 } else { |
| 578 if (start_i > len) start_i = len; | 582 if (start_i > len) start_i = len; |
| 579 } | 583 } |
| 580 | 584 |
| 581 // SpiderMonkey and KJS treat the case where no delete count is | 585 // SpiderMonkey and KJS treat the case where no delete count is |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 obj[i] = void 0; | 847 obj[i] = void 0; |
| 844 } else { | 848 } else { |
| 845 delete obj[i]; | 849 delete obj[i]; |
| 846 } | 850 } |
| 847 } | 851 } |
| 848 | 852 |
| 849 // Return the number of defined elements. | 853 // Return the number of defined elements. |
| 850 return first_undefined; | 854 return first_undefined; |
| 851 } | 855 } |
| 852 | 856 |
| 853 length = ToUint32(this.length); | 857 length = TO_UINT32(this.length); |
| 854 if (length < 2) return this; | 858 if (length < 2) return this; |
| 855 | 859 |
| 856 var is_array = IS_ARRAY(this); | 860 var is_array = IS_ARRAY(this); |
| 857 var max_prototype_element; | 861 var max_prototype_element; |
| 858 if (!is_array) { | 862 if (!is_array) { |
| 859 // For compatibility with JSC, we also sort elements inherited from | 863 // For compatibility with JSC, we also sort elements inherited from |
| 860 // the prototype chain on non-Array objects. | 864 // the prototype chain on non-Array objects. |
| 861 // We do this by copying them to this object and sorting only | 865 // We do this by copying them to this object and sorting only |
| 862 // local elements. This is not very efficient, but sorting with | 866 // local elements. This is not very efficient, but sorting with |
| 863 // inherited elements happens very, very rarely, if at all. | 867 // inherited elements happens very, very rarely, if at all. |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1143 ArrayIndexOf: 1, | 1147 ArrayIndexOf: 1, |
| 1144 ArrayLastIndexOf: 1, | 1148 ArrayLastIndexOf: 1, |
| 1145 ArrayPush: 1, | 1149 ArrayPush: 1, |
| 1146 ArrayReduce: 1, | 1150 ArrayReduce: 1, |
| 1147 ArrayReduceRight: 1 | 1151 ArrayReduceRight: 1 |
| 1148 }); | 1152 }); |
| 1149 } | 1153 } |
| 1150 | 1154 |
| 1151 | 1155 |
| 1152 SetupArray(); | 1156 SetupArray(); |
| OLD | NEW |