OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
11 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace interpreter { | 15 namespace interpreter { |
16 | 16 |
17 class BytecodeGeneratorHelper { | 17 class BytecodeGeneratorHelper { |
18 public: | 18 public: |
19 const char* kFunctionName = "f"; | 19 const char* kFunctionName = "f"; |
20 | 20 |
21 const int kLastParamIndex = | 21 static const int kLastParamIndex = |
22 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 22 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
23 | 23 |
24 BytecodeGeneratorHelper() { | 24 BytecodeGeneratorHelper() { |
25 i::FLAG_vector_stores = true; | 25 i::FLAG_vector_stores = true; |
26 i::FLAG_ignition = true; | 26 i::FLAG_ignition = true; |
27 i::FLAG_ignition_filter = StrDup(kFunctionName); | 27 i::FLAG_ignition_filter = StrDup(kFunctionName); |
28 i::FLAG_always_opt = false; | 28 i::FLAG_always_opt = false; |
29 CcTest::i_isolate()->interpreter()->Initialize(); | 29 CcTest::i_isolate()->interpreter()->Initialize(); |
30 } | 30 } |
31 | 31 |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 B(Ldar), R(helper.kLastParamIndex), // | 463 B(Ldar), R(helper.kLastParamIndex), // |
464 B(Star), R(1), // | 464 B(Star), R(1), // |
465 B(LdaSmi8), U8(-124), // | 465 B(LdaSmi8), U8(-124), // |
466 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // | 466 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // |
467 B(Return) // | 467 B(Return) // |
468 }, | 468 }, |
469 1, | 469 1, |
470 {"name"}}}; | 470 {"name"}}}; |
471 for (size_t i = 0; i < arraysize(snippets); i++) { | 471 for (size_t i = 0; i < arraysize(snippets); i++) { |
472 Handle<BytecodeArray> bytecode_array = | 472 Handle<BytecodeArray> bytecode_array = |
473 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 473 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
474 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 474 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
475 } | 475 } |
476 } | 476 } |
477 | 477 |
478 | 478 |
479 TEST(PropertyStores) { | 479 TEST(PropertyStores) { |
480 InitializedHandleScope handle_scope; | 480 InitializedHandleScope handle_scope; |
481 BytecodeGeneratorHelper helper; | 481 BytecodeGeneratorHelper helper; |
482 | 482 |
483 FeedbackVectorSlotKind ic_kinds[] = {i::FeedbackVectorSlotKind::STORE_IC, | 483 FeedbackVectorSlotKind ic_kinds[] = {i::FeedbackVectorSlotKind::STORE_IC, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 B(LdaSmi8), U8(-124), // | 566 B(LdaSmi8), U8(-124), // |
567 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), // | 567 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), // |
568 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), // | 568 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), // |
569 B(LdaUndefined), // | 569 B(LdaUndefined), // |
570 B(Return) // | 570 B(Return) // |
571 }, | 571 }, |
572 1, | 572 1, |
573 {"name"}}}; | 573 {"name"}}}; |
574 for (size_t i = 0; i < arraysize(snippets); i++) { | 574 for (size_t i = 0; i < arraysize(snippets); i++) { |
575 Handle<BytecodeArray> bytecode_array = | 575 Handle<BytecodeArray> bytecode_array = |
576 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 576 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
577 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 577 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
578 } | 578 } |
579 } | 579 } |
580 | 580 |
581 | 581 |
582 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" | 582 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" |
583 | 583 |
584 | 584 |
585 TEST(PropertyCall) { | 585 TEST(PropertyCall) { |
586 InitializedHandleScope handle_scope; | 586 InitializedHandleScope handle_scope; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 B(Star), R(2), // | 644 B(Star), R(2), // |
645 B(Ldar), R(helper.kLastParamIndex), // | 645 B(Ldar), R(helper.kLastParamIndex), // |
646 B(Star), R(3), // | 646 B(Star), R(3), // |
647 B(Call), R(0), R(1), U8(2), // | 647 B(Call), R(0), R(1), U8(2), // |
648 B(Return) // | 648 B(Return) // |
649 }, | 649 }, |
650 1, | 650 1, |
651 {"func"}}}; | 651 {"func"}}}; |
652 for (size_t i = 0; i < arraysize(snippets); i++) { | 652 for (size_t i = 0; i < arraysize(snippets); i++) { |
653 Handle<BytecodeArray> bytecode_array = | 653 Handle<BytecodeArray> bytecode_array = |
654 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 654 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
655 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 655 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
656 } | 656 } |
657 } | 657 } |
658 | 658 |
659 | 659 |
660 TEST(LoadGlobal) { | 660 TEST(LoadGlobal) { |
661 InitializedHandleScope handle_scope; | 661 InitializedHandleScope handle_scope; |
662 BytecodeGeneratorHelper helper; | 662 BytecodeGeneratorHelper helper; |
663 | 663 |
664 ExpectedSnippet<const char*> snippets[] = { | 664 ExpectedSnippet<const char*> snippets[] = { |
665 {"var a = 1;\nfunction f() { return a; }\nf()", | 665 {"var a = 1;\nfunction f() { return a; }\nf()", |
666 0, 1, 3, | 666 0, 1, 3, |
667 { | 667 { |
668 B(LdaGlobal), _, | 668 B(LdaGlobal), _, |
669 B(Return) | 669 B(Return) |
670 }, | 670 }, |
671 }, | 671 }, |
672 {"function t() { }\nfunction f() { return t; }\nf()", | 672 {"function t() { }\nfunction f() { return t; }\nf()", |
673 0, 1, 3, | 673 0, 1, 3, |
674 { | 674 { |
675 B(LdaGlobal), _, | 675 B(LdaGlobal), _, |
676 B(Return) | 676 B(Return) |
677 }, | 677 }, |
678 }, | 678 }, |
679 }; | 679 }; |
680 | 680 |
681 for (size_t i = 0; i < arraysize(snippets); i++) { | 681 for (size_t i = 0; i < arraysize(snippets); i++) { |
682 Handle<BytecodeArray> bytecode_array = | 682 Handle<BytecodeArray> bytecode_array = |
683 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 683 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
684 bytecode_array->Print(); | |
685 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 684 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
686 } | 685 } |
687 } | 686 } |
688 | 687 |
689 | 688 |
690 TEST(CallGlobal) { | 689 TEST(CallGlobal) { |
691 InitializedHandleScope handle_scope; | 690 InitializedHandleScope handle_scope; |
692 BytecodeGeneratorHelper helper; | 691 BytecodeGeneratorHelper helper; |
693 | 692 |
694 ExpectedSnippet<const char*> snippets[] = { | 693 ExpectedSnippet<const char*> snippets[] = { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 } | 729 } |
731 | 730 |
732 | 731 |
733 TEST(IfConditions) { | 732 TEST(IfConditions) { |
734 InitializedHandleScope handle_scope; | 733 InitializedHandleScope handle_scope; |
735 BytecodeGeneratorHelper helper; | 734 BytecodeGeneratorHelper helper; |
736 | 735 |
737 Handle<Object> unused = helper.factory()->undefined_value(); | 736 Handle<Object> unused = helper.factory()->undefined_value(); |
738 | 737 |
739 ExpectedSnippet<Handle<Object>> snippets[] = { | 738 ExpectedSnippet<Handle<Object>> snippets[] = { |
740 {"function f() { if (0) { return 1; } else { return -1; } }", | 739 {"function f() { if (0) { return 1; } else { return -1; } } f()", |
741 0, | 740 0, |
742 1, | 741 1, |
743 14, | 742 14, |
744 {B(LdaZero), // | 743 {B(LdaZero), // |
745 B(ToBoolean), // | 744 B(ToBoolean), // |
746 B(JumpIfFalse), U8(7), // | 745 B(JumpIfFalse), U8(7), // |
747 B(LdaSmi8), U8(1), // | 746 B(LdaSmi8), U8(1), // |
748 B(Return), // | 747 B(Return), // |
749 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 748 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
750 B(LdaSmi8), U8(-1), // | 749 B(LdaSmi8), U8(-1), // |
751 B(Return), // | 750 B(Return), // |
752 B(LdaUndefined), // | 751 B(LdaUndefined), // |
753 B(Return)}, // | 752 B(Return)}, // |
754 0, | 753 0, |
755 {unused, unused, unused, unused}}, | 754 {unused, unused, unused, unused}}, |
756 {"function f() { if ('lucky') { return 1; } else { return -1; } }", | 755 {"function f() { if ('lucky') { return 1; } else { return -1; } } f();", |
757 0, | 756 0, |
758 1, | 757 1, |
759 15, | 758 15, |
760 {B(LdaConstant), U8(0), // | 759 {B(LdaConstant), U8(0), // |
761 B(ToBoolean), // | 760 B(ToBoolean), // |
762 B(JumpIfFalse), U8(7), // | 761 B(JumpIfFalse), U8(7), // |
763 B(LdaSmi8), U8(1), // | 762 B(LdaSmi8), U8(1), // |
764 B(Return), // | 763 B(Return), // |
765 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 764 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
766 B(LdaSmi8), U8(-1), // | 765 B(LdaSmi8), U8(-1), // |
767 B(Return), // | 766 B(Return), // |
768 B(LdaUndefined), // | 767 B(LdaUndefined), // |
769 B(Return)}, // | 768 B(Return)}, // |
770 1, | 769 1, |
771 {helper.factory()->NewStringFromStaticChars("lucky"), unused, | 770 {helper.factory()->NewStringFromStaticChars("lucky"), unused, unused, |
772 unused, unused}}, | 771 unused}}, |
773 {"function f() { if (false) { return 1; } else { return -1; } }", | 772 {"function f() { if (false) { return 1; } else { return -1; } } f();", |
774 0, | 773 0, |
775 1, | 774 1, |
776 13, | 775 13, |
777 {B(LdaFalse), // | 776 {B(LdaFalse), // |
778 B(JumpIfFalse), U8(7), // | 777 B(JumpIfFalse), U8(7), // |
779 B(LdaSmi8), U8(1), // | 778 B(LdaSmi8), U8(1), // |
780 B(Return), // | 779 B(Return), // |
781 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 780 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
782 B(LdaSmi8), U8(-1), // | 781 B(LdaSmi8), U8(-1), // |
783 B(Return), // | 782 B(Return), // |
784 B(LdaUndefined), // | 783 B(LdaUndefined), // |
785 B(Return)}, // | 784 B(Return)}, // |
786 0, | 785 0, |
787 {unused, unused, unused, unused}}, | 786 {unused, unused, unused, unused}}, |
788 {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }", | 787 {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }" |
| 788 "f(99);", |
789 kPointerSize, | 789 kPointerSize, |
790 2, | 790 2, |
791 19, | 791 19, |
792 {B(Ldar), R(-5), // | 792 {B(Ldar), R(-5), // |
793 B(Star), R(0), // | 793 B(Star), R(0), // |
794 B(LdaZero), // | 794 B(LdaZero), // |
795 B(TestLessThanEqual), R(0), // | 795 B(TestLessThanOrEqual), R(0), // |
796 B(JumpIfFalse), U8(7), // | 796 B(JumpIfFalse), U8(7), // |
797 B(LdaConstant), U8(0), // | 797 B(LdaConstant), U8(0), // |
798 B(Return), // | 798 B(Return), // |
799 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 799 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
800 B(LdaConstant), U8(1), // | 800 B(LdaConstant), U8(1), // |
801 B(Return), // | 801 B(Return), // |
802 B(LdaUndefined), // | 802 B(LdaUndefined), // |
803 B(Return)}, // | 803 B(Return)}, // |
804 2, | 804 2, |
805 {helper.factory()->NewNumberFromInt(200), | 805 {helper.factory()->NewNumberFromInt(200), |
806 helper.factory()->NewNumberFromInt(-200), unused, unused}}, | 806 helper.factory()->NewNumberFromInt(-200), unused, unused}}, |
807 {"function f(a, b) { if (a in b) { return 200; } }", | 807 {"function f(a, b) { if (a in b) { return 200; } }" |
| 808 "f('prop', { prop: 'yes'});", |
808 kPointerSize, | 809 kPointerSize, |
809 3, | 810 3, |
810 17, | 811 17, |
811 {B(Ldar), R(-6), // | 812 {B(Ldar), R(-6), // |
812 B(Star), R(0), // | 813 B(Star), R(0), // |
813 B(Ldar), R(-5), // | 814 B(Ldar), R(-5), // |
814 B(TestIn), R(0), // | 815 B(TestIn), R(0), // |
815 B(JumpIfFalse), U8(7), // | 816 B(JumpIfFalse), U8(7), // |
816 B(LdaConstant), U8(0), // | 817 B(LdaConstant), U8(0), // |
817 B(Return), // | 818 B(Return), // |
818 B(Jump), U8(2), // TODO(oth): Unreachable jump after return | 819 B(Jump), U8(2), // TODO(oth): Unreachable jump after return |
819 B(LdaUndefined), // | 820 B(LdaUndefined), // |
820 B(Return)}, // | 821 B(Return)}, // |
821 1, | 822 1, |
822 {helper.factory()->NewNumberFromInt(200), unused, unused, unused}}, | 823 {helper.factory()->NewNumberFromInt(200), unused, unused, unused}}, |
823 {"function f(a, b) { if (a instanceof b) { return 200; } }", | |
824 kPointerSize, | |
825 3, | |
826 17, | |
827 {B(Ldar), R(-6), // | |
828 B(Star), R(0), // | |
829 B(Ldar), R(-5), // | |
830 B(TestInstanceOf), R(0), // | |
831 B(JumpIfFalse), U8(7), // | |
832 B(LdaConstant), U8(0), // | |
833 B(Return), // | |
834 B(Jump), U8(2), // TODO(oth): Unreachable jump after return | |
835 B(LdaUndefined), // | |
836 B(Return)}, // | |
837 1, | |
838 {helper.factory()->NewNumberFromInt(200), unused, unused, unused}}, | |
839 {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { " | 824 {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { " |
840 #define X "b = a; a = b; " | 825 #define X "b = a; a = b; " |
841 X X X X X X X X X X X X X X X X X X X X X X X X | 826 X X X X X X X X X X X X X X X X X X X X X X X X |
842 #undef X | 827 #undef X |
843 " return 200; } else { return -200; } }", | 828 " return 200; } else { return -200; } } f(0.001)", |
844 3 * kPointerSize, | 829 3 * kPointerSize, |
845 2, | 830 2, |
846 218, | 831 218, |
847 {B(LdaZero), // | 832 {B(LdaZero), // |
848 B(Star), R(0), // | 833 B(Star), R(0), // |
849 B(LdaZero), // | 834 B(LdaZero), // |
850 B(Star), R(1), // | 835 B(Star), R(1), // |
851 B(Ldar), R(0), // | 836 B(Ldar), R(0), // |
852 B(Star), R(2), // | 837 B(Star), R(2), // |
853 B(LdaConstant), U8(0), // | 838 B(LdaConstant), U8(0), // |
854 B(TestEqualStrict), R(2), // | 839 B(TestEqualStrict), R(2), // |
855 B(JumpIfFalseConstant), U8(2), // | 840 B(JumpIfFalseConstant), U8(2), // |
856 #define X B(Ldar), R(0), B(Star), R(1), B(Ldar), R(1), B(Star), R(0), | 841 #define X B(Ldar), R(0), B(Star), R(1), B(Ldar), R(1), B(Star), R(0), |
857 X X X X X X X X X X X X X X X X X X X X X X X X | 842 X X X X X X X X X X X X X X X X X X X X X X X X |
858 #undef X | 843 #undef X |
859 B(LdaConstant), | 844 B(LdaConstant), |
860 U8(1), // | 845 U8(1), // |
861 B(Return), // | 846 B(Return), // |
862 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 847 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
863 B(LdaConstant), U8(3), // | 848 B(LdaConstant), U8(3), // |
864 B(Return), // | 849 B(Return), // |
865 B(LdaUndefined), // | 850 B(LdaUndefined), // |
866 B(Return)}, // | 851 B(Return)}, // |
867 4, | 852 4, |
868 {helper.factory()->NewHeapNumber(0.01), | 853 {helper.factory()->NewHeapNumber(0.01), |
869 helper.factory()->NewNumberFromInt(200), | 854 helper.factory()->NewNumberFromInt(200), |
870 helper.factory()->NewNumberFromInt(199), | 855 helper.factory()->NewNumberFromInt(199), |
871 helper.factory()->NewNumberFromInt(-200)}}}; | 856 helper.factory()->NewNumberFromInt(-200)}}, |
| 857 {"function f(a, b) {\n" |
| 858 " if (a == b) { return 1; }\n" |
| 859 " if (a === b) { return 1; }\n" |
| 860 " if (a < b) { return 1; }\n" |
| 861 " if (a > b) { return 1; }\n" |
| 862 " if (a <= b) { return 1; }\n" |
| 863 " if (a >= b) { return 1; }\n" |
| 864 " if (a in b) { return 1; }\n" |
| 865 " if (a instanceof b) { return 1; }\n" |
| 866 " /* if (a != b) { return 1; } */" // TODO(oth) Ast visitor yields |
| 867 " /* if (a !== b) { return 1; } */" // UNARY NOT, rather than !=/!==. |
| 868 " return 0;\n" |
| 869 "} f(1, 1);", |
| 870 kPointerSize, |
| 871 3, |
| 872 122, |
| 873 { |
| 874 #define IF_CONDITION_RETURN(condition) \ |
| 875 B(Ldar), R(-6), \ |
| 876 B(Star), R(0), \ |
| 877 B(Ldar), R(-5), \ |
| 878 B(condition), R(0), \ |
| 879 B(JumpIfFalse), U8(7), \ |
| 880 B(LdaSmi8), U8(1), \ |
| 881 B(Return), \ |
| 882 B(Jump), U8(2), |
| 883 IF_CONDITION_RETURN(TestEqual) // |
| 884 IF_CONDITION_RETURN(TestEqualStrict) // |
| 885 IF_CONDITION_RETURN(TestLessThan) // |
| 886 IF_CONDITION_RETURN(TestGreaterThan) // |
| 887 IF_CONDITION_RETURN(TestLessThanOrEqual) // |
| 888 IF_CONDITION_RETURN(TestGreaterThanOrEqual) // |
| 889 IF_CONDITION_RETURN(TestIn) // |
| 890 IF_CONDITION_RETURN(TestInstanceOf) // |
| 891 #undef IF_CONDITION_RETURN |
| 892 B(LdaZero), // |
| 893 B(Return)}, // |
| 894 0, |
| 895 {unused, unused, unused, unused}}, |
| 896 }; |
872 | 897 |
873 for (size_t i = 0; i < arraysize(snippets); i++) { | 898 for (size_t i = 0; i < arraysize(snippets); i++) { |
874 Handle<BytecodeArray> bytecode_array = | 899 Handle<BytecodeArray> bytecode_array = |
875 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 900 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
876 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 901 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
877 } | 902 } |
878 } | 903 } |
879 | 904 |
880 | 905 |
881 } // namespace interpreter | 906 } // namespace interpreter |
882 } // namespace internal | 907 } // namespace internal |
883 } // namespance v8 | 908 } // namespance v8 |
OLD | NEW |