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