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 #include "test/cctest/test-feedback-vector.h" | 12 #include "test/cctest/test-feedback-vector.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace interpreter { | 16 namespace interpreter { |
17 | 17 |
18 class BytecodeGeneratorHelper { | 18 class BytecodeGeneratorHelper { |
19 public: | 19 public: |
20 const char* kFunctionName = "f"; | 20 const char* kFunctionName = "f"; |
21 | 21 |
22 static const int kLastParamIndex = | 22 static const int kLastParamIndex = |
23 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 23 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
24 | 24 |
25 BytecodeGeneratorHelper() { | 25 BytecodeGeneratorHelper() { |
26 i::FLAG_vector_stores = true; | 26 i::FLAG_vector_stores = true; |
27 i::FLAG_ignition = true; | 27 i::FLAG_ignition = true; |
28 i::FLAG_ignition_filter = StrDup(kFunctionName); | 28 i::FLAG_ignition_filter = StrDup(kFunctionName); |
29 i::FLAG_always_opt = false; | 29 i::FLAG_always_opt = false; |
30 i::FLAG_allow_natives_syntax = true; | |
31 CcTest::i_isolate()->interpreter()->Initialize(); | 30 CcTest::i_isolate()->interpreter()->Initialize(); |
32 } | 31 } |
33 | 32 |
34 Isolate* isolate() { return CcTest::i_isolate(); } | 33 Isolate* isolate() { return CcTest::i_isolate(); } |
35 Factory* factory() { return CcTest::i_isolate()->factory(); } | 34 Factory* factory() { return CcTest::i_isolate()->factory(); } |
36 | 35 |
37 | 36 |
38 Handle<BytecodeArray> MakeBytecode(const char* script, | 37 Handle<BytecodeArray> MakeBytecode(const char* script, |
39 const char* function_name) { | 38 const char* function_name) { |
40 CompileRun(script); | 39 CompileRun(script); |
(...skipping 17 matching lines...) Expand all Loading... |
58 return MakeBytecode(program.start(), kFunctionName); | 57 return MakeBytecode(program.start(), kFunctionName); |
59 } | 58 } |
60 }; | 59 }; |
61 | 60 |
62 | 61 |
63 // Helper macros for handcrafting bytecode sequences. | 62 // Helper macros for handcrafting bytecode sequences. |
64 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 63 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
65 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 64 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
66 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 65 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
67 #define _ static_cast<uint8_t>(0x5a) | 66 #define _ static_cast<uint8_t>(0x5a) |
68 #if defined(V8_TARGET_LITTLE_ENDIAN) | |
69 #define U16(x) static_cast<uint8_t>((x) & 0xff), \ | |
70 static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff) | |
71 #elif defined(V8_TARGET_BIG_ENDIAN) | |
72 #define U16(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ | |
73 static_cast<uint8_t>((x) & 0xff) | |
74 #else | |
75 #error Unknown byte ordering | |
76 #endif | |
77 | 67 |
78 | 68 |
79 // Structure for containing expected bytecode snippets. | 69 // Structure for containing expected bytecode snippets. |
80 template<typename T> | 70 template<typename T> |
81 struct ExpectedSnippet { | 71 struct ExpectedSnippet { |
82 const char* code_snippet; | 72 const char* code_snippet; |
83 int frame_size; | 73 int frame_size; |
84 int parameter_count; | 74 int parameter_count; |
85 int bytecode_length; | 75 int bytecode_length; |
86 const uint8_t bytecode[512]; | 76 const uint8_t bytecode[512]; |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); | 677 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
688 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 678 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
689 } | 679 } |
690 } | 680 } |
691 | 681 |
692 | 682 |
693 TEST(LoadGlobal) { | 683 TEST(LoadGlobal) { |
694 InitializedHandleScope handle_scope; | 684 InitializedHandleScope handle_scope; |
695 BytecodeGeneratorHelper helper; | 685 BytecodeGeneratorHelper helper; |
696 | 686 |
697 ExpectedSnippet<int> snippets[] = { | 687 ExpectedSnippet<const char*> snippets[] = { |
698 { | 688 {"var a = 1;\nfunction f() { return a; }\nf()", |
699 "var a = 1;\nfunction f() { return a; }\nf()", | 689 0, 1, 3, |
700 0, | 690 { |
701 1, | 691 B(LdaGlobal), _, |
702 3, | 692 B(Return) |
703 { | 693 }, |
704 B(LdaGlobal), _, // | |
705 B(Return) // | |
706 }, | |
707 }, | 694 }, |
708 { | 695 {"function t() { }\nfunction f() { return t; }\nf()", |
709 "function t() { }\nfunction f() { return t; }\nf()", | 696 0, 1, 3, |
710 0, | 697 { |
711 1, | 698 B(LdaGlobal), _, |
712 3, | 699 B(Return) |
713 { | 700 }, |
714 B(LdaGlobal), _, // | |
715 B(Return) // | |
716 }, | |
717 }, | 701 }, |
718 }; | 702 }; |
719 | 703 |
720 for (size_t i = 0; i < arraysize(snippets); i++) { | 704 for (size_t i = 0; i < arraysize(snippets); i++) { |
721 Handle<BytecodeArray> bytecode_array = | 705 Handle<BytecodeArray> bytecode_array = |
722 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 706 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
723 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 707 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
724 } | 708 } |
725 } | 709 } |
726 | 710 |
727 | 711 |
728 TEST(CallGlobal) { | 712 TEST(CallGlobal) { |
729 InitializedHandleScope handle_scope; | 713 InitializedHandleScope handle_scope; |
730 BytecodeGeneratorHelper helper; | 714 BytecodeGeneratorHelper helper; |
731 | 715 |
732 ExpectedSnippet<int> snippets[] = { | 716 ExpectedSnippet<const char*> snippets[] = { |
733 { | 717 {"function t() { }\nfunction f() { return t(); }\nf()", |
734 "function t() { }\nfunction f() { return t(); }\nf()", | 718 2 * kPointerSize, 1, 12, |
735 2 * kPointerSize, | 719 { |
736 1, | 720 B(LdaUndefined), |
737 12, | 721 B(Star), R(1), |
738 { | 722 B(LdaGlobal), _, |
739 B(LdaUndefined), // | 723 B(Star), R(0), |
740 B(Star), R(1), // | 724 B(Call), R(0), R(1), U8(0), |
741 B(LdaGlobal), _, // | 725 B(Return) |
742 B(Star), R(0), // | 726 }, |
743 B(Call), R(0), R(1), U8(0), // | |
744 B(Return) // | |
745 }, | |
746 }, | 727 }, |
747 { | 728 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", |
748 "function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", | 729 5 * kPointerSize, 1, 24, |
749 5 * kPointerSize, | 730 { |
750 1, | 731 B(LdaUndefined), |
751 24, | 732 B(Star), R(1), |
752 { | 733 B(LdaGlobal), _, |
753 B(LdaUndefined), // | 734 B(Star), R(0), |
754 B(Star), R(1), // | 735 B(LdaSmi8), U8(1), |
755 B(LdaGlobal), _, // | 736 B(Star), R(2), |
756 B(Star), R(0), // | 737 B(LdaSmi8), U8(2), |
757 B(LdaSmi8), U8(1), // | 738 B(Star), R(3), |
758 B(Star), R(2), // | 739 B(LdaSmi8), U8(3), |
759 B(LdaSmi8), U8(2), // | 740 B(Star), R(4), |
760 B(Star), R(3), // | 741 B(Call), R(0), R(1), U8(3), |
761 B(LdaSmi8), U8(3), // | 742 B(Return) |
762 B(Star), R(4), // | 743 }, |
763 B(Call), R(0), R(1), U8(3), // | |
764 B(Return) // | |
765 }, | |
766 }, | 744 }, |
767 }; | 745 }; |
768 | 746 |
769 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
770 for (size_t i = 0; i < num_snippets; i++) { | |
771 Handle<BytecodeArray> bytecode_array = | |
772 helper.MakeBytecode(snippets[i].code_snippet, "f"); | |
773 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | |
774 } | |
775 } | |
776 | |
777 | |
778 TEST(CallRuntime) { | |
779 InitializedHandleScope handle_scope; | |
780 BytecodeGeneratorHelper helper; | |
781 | |
782 ExpectedSnippet<int> snippets[] = { | |
783 { | |
784 "function f() { %TheHole() }\nf()", | |
785 1 * kPointerSize, | |
786 1, | |
787 7, | |
788 { | |
789 B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), // | |
790 B(LdaUndefined), // | |
791 B(Return) // | |
792 }, | |
793 }, | |
794 { | |
795 "function f(a) { return %IsArray(a) }\nf(undefined)", | |
796 1 * kPointerSize, | |
797 2, | |
798 10, | |
799 { | |
800 B(Ldar), R(helper.kLastParamIndex), // | |
801 B(Star), R(0), // | |
802 B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), // | |
803 B(Return) // | |
804 }, | |
805 }, | |
806 { | |
807 "function f() { return %Add(1, 2) }\nf()", | |
808 2 * kPointerSize, | |
809 1, | |
810 14, | |
811 { | |
812 B(LdaSmi8), U8(1), // | |
813 B(Star), R(0), // | |
814 B(LdaSmi8), U8(2), // | |
815 B(Star), R(1), // | |
816 B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2), // | |
817 B(Return) // | |
818 }, | |
819 }, | |
820 }; | |
821 | |
822 for (size_t i = 0; i < arraysize(snippets); i++) { | 747 for (size_t i = 0; i < arraysize(snippets); i++) { |
823 Handle<BytecodeArray> bytecode_array = | 748 Handle<BytecodeArray> bytecode_array = |
824 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 749 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
825 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 750 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
826 } | 751 } |
827 } | 752 } |
828 | 753 |
829 | 754 |
830 TEST(IfConditions) { | 755 TEST(IfConditions) { |
831 InitializedHandleScope handle_scope; | 756 InitializedHandleScope handle_scope; |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 for (size_t i = 0; i < arraysize(snippets); i++) { | 1181 for (size_t i = 0; i < arraysize(snippets); i++) { |
1257 Handle<BytecodeArray> bytecode_array = | 1182 Handle<BytecodeArray> bytecode_array = |
1258 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 1183 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
1259 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 1184 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
1260 } | 1185 } |
1261 } | 1186 } |
1262 | 1187 |
1263 } // namespace interpreter | 1188 } // namespace interpreter |
1264 } // namespace internal | 1189 } // namespace internal |
1265 } // namespace v8 | 1190 } // namespace v8 |
OLD | NEW |