Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/array.js

Issue 15777007: Re-land: Implement ObservedArrayPop, ObservedArrayShift, ObservedArrayUnshift & ObservedArraySplice (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 separator = NonStringToString(separator); 388 separator = NonStringToString(separator);
389 } 389 }
390 390
391 var result = %_FastAsciiArrayJoin(this, separator); 391 var result = %_FastAsciiArrayJoin(this, separator);
392 if (!IS_UNDEFINED(result)) return result; 392 if (!IS_UNDEFINED(result)) return result;
393 393
394 return Join(this, length, separator, ConvertToString); 394 return Join(this, length, separator, ConvertToString);
395 } 395 }
396 396
397 397
398 function ObservedArrayPop(n) {
399 n--;
400 var value = this[n];
401
402 EnqueueSpliceRecord(this, n, [value], 1, 0);
403
404 try {
405 BeginPerformSplice(this);
406 delete this[n];
407 this.length = n;
408 } finally {
409 EndPerformSplice(this);
410 }
411
412 return value;
413 }
414
398 // Removes the last element from the array and returns it. See 415 // Removes the last element from the array and returns it. See
399 // ECMA-262, section 15.4.4.6. 416 // ECMA-262, section 15.4.4.6.
400 function ArrayPop() { 417 function ArrayPop() {
401 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 418 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
402 throw MakeTypeError("called_on_null_or_undefined", 419 throw MakeTypeError("called_on_null_or_undefined",
403 ["Array.prototype.pop"]); 420 ["Array.prototype.pop"]);
404 } 421 }
405 422
406 var n = TO_UINT32(this.length); 423 var n = TO_UINT32(this.length);
407 if (n == 0) { 424 if (n == 0) {
408 this.length = n; 425 this.length = n;
409 return; 426 return;
410 } 427 }
428
429 if (%IsObserved(this))
430 return ObservedArrayPop.call(this, n);
431
411 n--; 432 n--;
412 var value = this[n]; 433 var value = this[n];
413 delete this[n]; 434 delete this[n];
414 this.length = n; 435 this.length = n;
415 return value; 436 return value;
416 } 437 }
417 438
418 439
419 function ObservedArrayPush() { 440 function ObservedArrayPush() {
420 var n = TO_UINT32(this.length); 441 var n = TO_UINT32(this.length);
421 var m = %_ArgumentsLength(); 442 var m = %_ArgumentsLength();
422 443
423 EnqueueSpliceRecord(this, n, [], 0, m); 444 EnqueueSpliceRecord(this, n, [], 0, m);
424 445
425 try { 446 try {
426 BeginPerformSplice(this); 447 BeginPerformSplice(this);
427
428 for (var i = 0; i < m; i++) { 448 for (var i = 0; i < m; i++) {
429 this[i+n] = %_Arguments(i); 449 this[i+n] = %_Arguments(i);
430 } 450 }
431 this.length = n + m; 451 this.length = n + m;
432 } finally { 452 } finally {
433 EndPerformSplice(this); 453 EndPerformSplice(this);
434 } 454 }
435 455
436 return this.length; 456 return this.length;
437 } 457 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 if (!IS_UNDEFINED(current_j) || j in this) { 571 if (!IS_UNDEFINED(current_j) || j in this) {
552 this[i] = current_j; 572 this[i] = current_j;
553 delete this[j]; 573 delete this[j];
554 } 574 }
555 } 575 }
556 } 576 }
557 return this; 577 return this;
558 } 578 }
559 579
560 580
581 function ObservedArrayShift(len) {
582 var first = this[0];
583
584 EnqueueSpliceRecord(this, 0, [first], 1, 0);
585
586 try {
587 BeginPerformSplice(this);
588 SimpleMove(this, 0, 1, len, 0);
589 this.length = len - 1;
590 } finally {
591 EndPerformSplice(this);
592 }
593
594 return first;
595 }
596
561 function ArrayShift() { 597 function ArrayShift() {
562 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 598 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
563 throw MakeTypeError("called_on_null_or_undefined", 599 throw MakeTypeError("called_on_null_or_undefined",
564 ["Array.prototype.shift"]); 600 ["Array.prototype.shift"]);
565 } 601 }
566 602
567 var len = TO_UINT32(this.length); 603 var len = TO_UINT32(this.length);
568 604
569 if (len === 0) { 605 if (len === 0) {
570 this.length = 0; 606 this.length = 0;
571 return; 607 return;
572 } 608 }
573 609
610 if (%IsObserved(this))
611 return ObservedArrayShift.call(this, len);
612
574 var first = this[0]; 613 var first = this[0];
575 614
576 if (IS_ARRAY(this) && !%IsObserved(this)) { 615 if (IS_ARRAY(this)) {
577 SmartMove(this, 0, 1, len, 0); 616 SmartMove(this, 0, 1, len, 0);
578 } else { 617 } else {
579 SimpleMove(this, 0, 1, len, 0); 618 SimpleMove(this, 0, 1, len, 0);
580 } 619 }
581 620
582 this.length = len - 1; 621 this.length = len - 1;
583 622
584 return first; 623 return first;
585 } 624 }
586 625
626 function ObservedArrayUnshift() {
627 var len = TO_UINT32(this.length);
628 var num_arguments = %_ArgumentsLength();
629
630 EnqueueSpliceRecord(this, 0, [], 0, num_arguments);
631
632 try {
633 BeginPerformSplice(this);
634 SimpleMove(this, 0, 0, len, num_arguments);
635 for (var i = 0; i < num_arguments; i++) {
636 this[i] = %_Arguments(i);
637 }
638 this.length = len + num_arguments;
639 } finally {
640 EndPerformSplice(this);
641 }
642
643 return len + num_arguments;
644 }
587 645
588 function ArrayUnshift(arg1) { // length == 1 646 function ArrayUnshift(arg1) { // length == 1
589 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 647 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
590 throw MakeTypeError("called_on_null_or_undefined", 648 throw MakeTypeError("called_on_null_or_undefined",
591 ["Array.prototype.unshift"]); 649 ["Array.prototype.unshift"]);
592 } 650 }
593 651
652 if (%IsObserved(this))
653 return ObservedArrayUnshift.apply(this, arguments);
654
594 var len = TO_UINT32(this.length); 655 var len = TO_UINT32(this.length);
595 var num_arguments = %_ArgumentsLength(); 656 var num_arguments = %_ArgumentsLength();
596 657
597 if (IS_ARRAY(this) && !%IsObserved(this)) { 658 if (IS_ARRAY(this)) {
598 SmartMove(this, 0, 0, len, num_arguments); 659 SmartMove(this, 0, 0, len, num_arguments);
599 } else { 660 } else {
600 SimpleMove(this, 0, 0, len, num_arguments); 661 SimpleMove(this, 0, 0, len, num_arguments);
601 } 662 }
602 663
603 for (var i = 0; i < num_arguments; i++) { 664 for (var i = 0; i < num_arguments; i++) {
604 this[i] = %_Arguments(i); 665 this[i] = %_Arguments(i);
605 } 666 }
606 667
607 this.length = len + num_arguments; 668 this.length = len + num_arguments;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } else { 709 } else {
649 SimpleSlice(this, start_i, end_i - start_i, len, result); 710 SimpleSlice(this, start_i, end_i - start_i, len, result);
650 } 711 }
651 712
652 result.length = end_i - start_i; 713 result.length = end_i - start_i;
653 714
654 return result; 715 return result;
655 } 716 }
656 717
657 718
719 function ComputeSpliceStartIndex(start_i, len) {
720 if (start_i < 0) {
721 start_i += len;
722 return start_i < 0 ? 0 : start_i;
723 }
724
725 return start_i > len ? len : start_i;
726 }
727
728
729 function ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i) {
730 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
731 // given as a request to delete all the elements from the start.
732 // And it differs from the case of undefined delete count.
733 // This does not follow ECMA-262, but we do the same for
734 // compatibility.
735 var del_count = 0;
736 if (num_arguments == 1)
737 return len - start_i;
738
739 del_count = TO_INTEGER(delete_count);
740 if (del_count < 0)
741 return 0;
742
743 if (del_count > len - start_i)
744 return len - start_i;
745
746 return del_count;
747 }
748
749
750 function ObservedArraySplice(start, delete_count) {
751 var num_arguments = %_ArgumentsLength();
752 var len = TO_UINT32(this.length);
753 var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
754 var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
755 start_i);
756 var deleted_elements = [];
757 deleted_elements.length = del_count;
758 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
759
760 try {
761 BeginPerformSplice(this);
762
763 SimpleSlice(this, start_i, del_count, len, deleted_elements);
764 SimpleMove(this, start_i, del_count, len, num_elements_to_add);
765
766 // Insert the arguments into the resulting array in
767 // place of the deleted elements.
768 var i = start_i;
769 var arguments_index = 2;
770 var arguments_length = %_ArgumentsLength();
771 while (arguments_index < arguments_length) {
772 this[i++] = %_Arguments(arguments_index++);
773 }
774 this.length = len - del_count + num_elements_to_add;
775
776 } finally {
777 EndPerformSplice(this);
778 if (deleted_elements.length || num_elements_to_add) {
779 EnqueueSpliceRecord(this,
780 start_i,
781 deleted_elements.slice(),
782 deleted_elements.length,
783 num_elements_to_add);
784 }
785 }
786
787 // Return the deleted elements.
788 return deleted_elements;
789 }
790
791
658 function ArraySplice(start, delete_count) { 792 function ArraySplice(start, delete_count) {
659 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 793 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
660 throw MakeTypeError("called_on_null_or_undefined", 794 throw MakeTypeError("called_on_null_or_undefined",
661 ["Array.prototype.splice"]); 795 ["Array.prototype.splice"]);
662 } 796 }
663 797
798 if (%IsObserved(this))
799 return ObservedArraySplice.apply(this, arguments);
800
664 var num_arguments = %_ArgumentsLength(); 801 var num_arguments = %_ArgumentsLength();
665
666 var len = TO_UINT32(this.length); 802 var len = TO_UINT32(this.length);
667 var start_i = TO_INTEGER(start); 803 var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
668 804 var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
669 if (start_i < 0) { 805 start_i);
670 start_i += len;
671 if (start_i < 0) start_i = 0;
672 } else {
673 if (start_i > len) start_i = len;
674 }
675
676 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
677 // given as a request to delete all the elements from the start.
678 // And it differs from the case of undefined delete count.
679 // This does not follow ECMA-262, but we do the same for
680 // compatibility.
681 var del_count = 0;
682 if (num_arguments == 1) {
683 del_count = len - start_i;
684 } else {
685 del_count = TO_INTEGER(delete_count);
686 if (del_count < 0) del_count = 0;
687 if (del_count > len - start_i) del_count = len - start_i;
688 }
689
690 var deleted_elements = []; 806 var deleted_elements = [];
691 deleted_elements.length = del_count; 807 deleted_elements.length = del_count;
692 808 var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
693 // Number of elements to add.
694 var num_additional_args = 0;
695 if (num_arguments > 2) {
696 num_additional_args = num_arguments - 2;
697 }
698 809
699 var use_simple_splice = true; 810 var use_simple_splice = true;
700
701 if (IS_ARRAY(this) && 811 if (IS_ARRAY(this) &&
702 !%IsObserved(this) && 812 num_elements_to_add !== del_count) {
703 num_additional_args !== del_count) {
704 // If we are only deleting/moving a few things near the end of the 813 // If we are only deleting/moving a few things near the end of the
705 // array then the simple version is going to be faster, because it 814 // array then the simple version is going to be faster, because it
706 // doesn't touch most of the array. 815 // doesn't touch most of the array.
707 var estimated_non_hole_elements = %EstimateNumberOfElements(this); 816 var estimated_non_hole_elements = %EstimateNumberOfElements(this);
708 if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) { 817 if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
709 use_simple_splice = false; 818 use_simple_splice = false;
710 } 819 }
711 } 820 }
712 821
713 if (use_simple_splice) { 822 if (use_simple_splice) {
714 SimpleSlice(this, start_i, del_count, len, deleted_elements); 823 SimpleSlice(this, start_i, del_count, len, deleted_elements);
715 SimpleMove(this, start_i, del_count, len, num_additional_args); 824 SimpleMove(this, start_i, del_count, len, num_elements_to_add);
716 } else { 825 } else {
717 SmartSlice(this, start_i, del_count, len, deleted_elements); 826 SmartSlice(this, start_i, del_count, len, deleted_elements);
718 SmartMove(this, start_i, del_count, len, num_additional_args); 827 SmartMove(this, start_i, del_count, len, num_elements_to_add);
719 } 828 }
720 829
721 // Insert the arguments into the resulting array in 830 // Insert the arguments into the resulting array in
722 // place of the deleted elements. 831 // place of the deleted elements.
723 var i = start_i; 832 var i = start_i;
724 var arguments_index = 2; 833 var arguments_index = 2;
725 var arguments_length = %_ArgumentsLength(); 834 var arguments_length = %_ArgumentsLength();
726 while (arguments_index < arguments_length) { 835 while (arguments_index < arguments_length) {
727 this[i++] = %_Arguments(arguments_index++); 836 this[i++] = %_Arguments(arguments_index++);
728 } 837 }
729 this.length = len - del_count + num_additional_args; 838 this.length = len - del_count + num_elements_to_add;
730 839
731 // Return the deleted elements. 840 // Return the deleted elements.
732 return deleted_elements; 841 return deleted_elements;
733 } 842 }
734 843
735 844
736 function ArraySort(comparefn) { 845 function ArraySort(comparefn) {
737 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 846 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
738 throw MakeTypeError("called_on_null_or_undefined", 847 throw MakeTypeError("called_on_null_or_undefined",
739 ["Array.prototype.sort"]); 848 ["Array.prototype.sort"]);
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 )); 1657 ));
1549 1658
1550 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array( 1659 SetUpLockedPrototype(InternalPackedArray, $Array(), $Array(
1551 "join", getFunction("join", ArrayJoin), 1660 "join", getFunction("join", ArrayJoin),
1552 "pop", getFunction("pop", ArrayPop), 1661 "pop", getFunction("pop", ArrayPop),
1553 "push", getFunction("push", ArrayPush) 1662 "push", getFunction("push", ArrayPush)
1554 )); 1663 ));
1555 } 1664 }
1556 1665
1557 SetUpArray(); 1666 SetUpArray();
OLDNEW
« no previous file with comments | « no previous file | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698