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 |