| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 } | 408 } |
| 409 | 409 |
| 410 return value; | 410 return value; |
| 411 } | 411 } |
| 412 | 412 |
| 413 // Removes the last element from the array and returns it. See | 413 // Removes the last element from the array and returns it. See |
| 414 // ECMA-262, section 15.4.4.6. | 414 // ECMA-262, section 15.4.4.6. |
| 415 function ArrayPop() { | 415 function ArrayPop() { |
| 416 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop"); | 416 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop"); |
| 417 | 417 |
| 418 var n = TO_UINT32(this.length); | 418 var array = TO_OBJECT_INLINE(this); |
| 419 var n = TO_UINT32(array.length); |
| 419 if (n == 0) { | 420 if (n == 0) { |
| 420 this.length = n; | 421 array.length = n; |
| 421 return; | 422 return; |
| 422 } | 423 } |
| 423 | 424 |
| 424 if (ObjectIsSealed(this)) { | 425 if (%IsObserved(array)) |
| 425 throw MakeTypeError("array_functions_change_sealed", | 426 return ObservedArrayPop.call(array, n); |
| 426 ["Array.prototype.pop"]); | |
| 427 } | |
| 428 | |
| 429 if (%IsObserved(this)) | |
| 430 return ObservedArrayPop.call(this, n); | |
| 431 | 427 |
| 432 n--; | 428 n--; |
| 433 var value = this[n]; | 429 var value = array[n]; |
| 434 Delete(this, ToName(n), true); | 430 Delete(array, ToName(n), true); |
| 435 this.length = n; | 431 array.length = n; |
| 436 return value; | 432 return value; |
| 437 } | 433 } |
| 438 | 434 |
| 439 | 435 |
| 440 function ObservedArrayPush() { | 436 function ObservedArrayPush() { |
| 441 var n = TO_UINT32(this.length); | 437 var n = TO_UINT32(this.length); |
| 442 var m = %_ArgumentsLength(); | 438 var m = %_ArgumentsLength(); |
| 443 | 439 |
| 444 try { | 440 try { |
| 445 BeginPerformSplice(this); | 441 BeginPerformSplice(this); |
| 446 for (var i = 0; i < m; i++) { | 442 for (var i = 0; i < m; i++) { |
| 447 this[i+n] = %_Arguments(i); | 443 this[i+n] = %_Arguments(i); |
| 448 } | 444 } |
| 449 var new_length = n + m; | 445 var new_length = n + m; |
| 450 this.length = new_length; | 446 this.length = new_length; |
| 451 } finally { | 447 } finally { |
| 452 EndPerformSplice(this); | 448 EndPerformSplice(this); |
| 453 EnqueueSpliceRecord(this, n, [], m); | 449 EnqueueSpliceRecord(this, n, [], m); |
| 454 } | 450 } |
| 455 | 451 |
| 456 return new_length; | 452 return new_length; |
| 457 } | 453 } |
| 458 | 454 |
| 459 // Appends the arguments to the end of the array and returns the new | 455 // Appends the arguments to the end of the array and returns the new |
| 460 // length of the array. See ECMA-262, section 15.4.4.7. | 456 // length of the array. See ECMA-262, section 15.4.4.7. |
| 461 function ArrayPush() { | 457 function ArrayPush() { |
| 462 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push"); | 458 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push"); |
| 463 | 459 |
| 464 var n = TO_UINT32(this.length); | |
| 465 var m = %_ArgumentsLength(); | |
| 466 | |
| 467 if (%IsObserved(this)) | 460 if (%IsObserved(this)) |
| 468 return ObservedArrayPush.apply(this, arguments); | 461 return ObservedArrayPush.apply(this, arguments); |
| 469 | 462 |
| 463 var array = TO_OBJECT_INLINE(this); |
| 464 var n = TO_UINT32(array.length); |
| 465 var m = %_ArgumentsLength(); |
| 466 |
| 470 for (var i = 0; i < m; i++) { | 467 for (var i = 0; i < m; i++) { |
| 471 // Use SetProperty rather than a direct keyed store to ensure that the store | 468 // Use SetProperty rather than a direct keyed store to ensure that the store |
| 472 // site doesn't become poisened with an elements transition KeyedStoreIC. | 469 // site doesn't become poisened with an elements transition KeyedStoreIC. |
| 473 // | 470 %SetProperty(array, i+n, %_Arguments(i), 0, kStrictMode); |
| 474 // TODO(danno): Using %SetProperty is a temporary workaround. The spec says | |
| 475 // that ToObject needs to be called for primitive values (and | |
| 476 // Runtime_SetProperty seem to ignore them). | |
| 477 %SetProperty(this, i+n, %_Arguments(i), 0, kStrictMode); | |
| 478 } | 471 } |
| 479 | 472 |
| 480 var new_length = n + m; | 473 var new_length = n + m; |
| 481 this.length = new_length; | 474 array.length = new_length; |
| 482 return new_length; | 475 return new_length; |
| 483 } | 476 } |
| 484 | 477 |
| 485 | 478 |
| 486 // Returns an array containing the array elements of the object followed | 479 // Returns an array containing the array elements of the object followed |
| 487 // by the array elements of each argument in order. See ECMA-262, | 480 // by the array elements of each argument in order. See ECMA-262, |
| 488 // section 15.4.4.7. | 481 // section 15.4.4.7. |
| 489 function ArrayConcat(arg1) { // length == 1 | 482 function ArrayConcat(arg1) { // length == 1 |
| 490 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat"); | 483 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat"); |
| 491 | 484 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 EndPerformSplice(this); | 582 EndPerformSplice(this); |
| 590 EnqueueSpliceRecord(this, 0, [first], 0); | 583 EnqueueSpliceRecord(this, 0, [first], 0); |
| 591 } | 584 } |
| 592 | 585 |
| 593 return first; | 586 return first; |
| 594 } | 587 } |
| 595 | 588 |
| 596 function ArrayShift() { | 589 function ArrayShift() { |
| 597 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift"); | 590 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift"); |
| 598 | 591 |
| 599 var len = TO_UINT32(this.length); | 592 var array = TO_OBJECT_INLINE(this); |
| 593 var len = TO_UINT32(array.length); |
| 600 | 594 |
| 601 if (len === 0) { | 595 if (len === 0) { |
| 602 this.length = 0; | 596 array.length = 0; |
| 603 return; | 597 return; |
| 604 } | 598 } |
| 605 | 599 |
| 606 if (ObjectIsSealed(this)) { | 600 if (ObjectIsSealed(array)) { |
| 607 throw MakeTypeError("array_functions_change_sealed", | 601 throw MakeTypeError("array_functions_change_sealed", |
| 608 ["Array.prototype.shift"]); | 602 ["Array.prototype.shift"]); |
| 609 } | 603 } |
| 610 | 604 |
| 611 if (%IsObserved(this)) | 605 if (%IsObserved(array)) |
| 612 return ObservedArrayShift.call(this, len); | 606 return ObservedArrayShift.call(array, len); |
| 613 | 607 |
| 614 var first = this[0]; | 608 var first = array[0]; |
| 615 | 609 |
| 616 if (IS_ARRAY(this)) { | 610 if (IS_ARRAY(array)) { |
| 617 SmartMove(this, 0, 1, len, 0); | 611 SmartMove(array, 0, 1, len, 0); |
| 618 } else { | 612 } else { |
| 619 SimpleMove(this, 0, 1, len, 0); | 613 SimpleMove(array, 0, 1, len, 0); |
| 620 } | 614 } |
| 621 | 615 |
| 622 this.length = len - 1; | 616 array.length = len - 1; |
| 623 | 617 |
| 624 return first; | 618 return first; |
| 625 } | 619 } |
| 626 | 620 |
| 627 function ObservedArrayUnshift() { | 621 function ObservedArrayUnshift() { |
| 628 var len = TO_UINT32(this.length); | 622 var len = TO_UINT32(this.length); |
| 629 var num_arguments = %_ArgumentsLength(); | 623 var num_arguments = %_ArgumentsLength(); |
| 630 | 624 |
| 631 try { | 625 try { |
| 632 BeginPerformSplice(this); | 626 BeginPerformSplice(this); |
| 633 SimpleMove(this, 0, 0, len, num_arguments); | 627 SimpleMove(this, 0, 0, len, num_arguments); |
| 634 for (var i = 0; i < num_arguments; i++) { | 628 for (var i = 0; i < num_arguments; i++) { |
| 635 this[i] = %_Arguments(i); | 629 this[i] = %_Arguments(i); |
| 636 } | 630 } |
| 637 var new_length = len + num_arguments; | 631 var new_length = len + num_arguments; |
| 638 this.length = new_length; | 632 this.length = new_length; |
| 639 } finally { | 633 } finally { |
| 640 EndPerformSplice(this); | 634 EndPerformSplice(this); |
| 641 EnqueueSpliceRecord(this, 0, [], num_arguments); | 635 EnqueueSpliceRecord(this, 0, [], num_arguments); |
| 642 } | 636 } |
| 643 | 637 |
| 644 return new_length; | 638 return new_length; |
| 645 } | 639 } |
| 646 | 640 |
| 647 function ArrayUnshift(arg1) { // length == 1 | 641 function ArrayUnshift(arg1) { // length == 1 |
| 648 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift"); | 642 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift"); |
| 649 | 643 |
| 650 var len = TO_UINT32(this.length); | |
| 651 var num_arguments = %_ArgumentsLength(); | |
| 652 var is_sealed = ObjectIsSealed(this); | |
| 653 | |
| 654 if (%IsObserved(this)) | 644 if (%IsObserved(this)) |
| 655 return ObservedArrayUnshift.apply(this, arguments); | 645 return ObservedArrayUnshift.apply(this, arguments); |
| 656 | 646 |
| 657 if (IS_ARRAY(this) && !is_sealed) { | 647 var array = TO_OBJECT_INLINE(this); |
| 658 SmartMove(this, 0, 0, len, num_arguments); | 648 var len = TO_UINT32(array.length); |
| 649 var num_arguments = %_ArgumentsLength(); |
| 650 var is_sealed = ObjectIsSealed(array); |
| 651 |
| 652 if (IS_ARRAY(array) && !is_sealed) { |
| 653 SmartMove(array, 0, 0, len, num_arguments); |
| 659 } else { | 654 } else { |
| 660 SimpleMove(this, 0, 0, len, num_arguments); | 655 SimpleMove(array, 0, 0, len, num_arguments); |
| 661 } | 656 } |
| 662 | 657 |
| 663 for (var i = 0; i < num_arguments; i++) { | 658 for (var i = 0; i < num_arguments; i++) { |
| 664 this[i] = %_Arguments(i); | 659 array[i] = %_Arguments(i); |
| 665 } | 660 } |
| 666 | 661 |
| 667 var new_length = len + num_arguments; | 662 var new_length = len + num_arguments; |
| 668 this.length = new_length; | 663 array.length = new_length; |
| 669 return new_length; | 664 return new_length; |
| 670 } | 665 } |
| 671 | 666 |
| 672 | 667 |
| 673 function ArraySlice(start, end) { | 668 function ArraySlice(start, end) { |
| 674 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice"); | 669 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice"); |
| 675 | 670 |
| 676 var len = TO_UINT32(this.length); | 671 var len = TO_UINT32(this.length); |
| 677 var start_i = TO_INTEGER(start); | 672 var start_i = TO_INTEGER(start); |
| 678 var end_i = len; | 673 var end_i = len; |
| (...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1627 )); | 1622 )); |
| 1628 | 1623 |
| 1629 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( | 1624 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( |
| 1630 "join", getFunction("join", ArrayJoin), | 1625 "join", getFunction("join", ArrayJoin), |
| 1631 "pop", getFunction("pop", ArrayPop), | 1626 "pop", getFunction("pop", ArrayPop), |
| 1632 "push", getFunction("push", ArrayPush) | 1627 "push", getFunction("push", ArrayPush) |
| 1633 )); | 1628 )); |
| 1634 } | 1629 } |
| 1635 | 1630 |
| 1636 SetUpArray(); | 1631 SetUpArray(); |
| OLD | NEW |