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; |
30 CcTest::i_isolate()->interpreter()->Initialize(); | 31 CcTest::i_isolate()->interpreter()->Initialize(); |
31 } | 32 } |
32 | 33 |
33 Isolate* isolate() { return CcTest::i_isolate(); } | 34 Isolate* isolate() { return CcTest::i_isolate(); } |
34 Factory* factory() { return CcTest::i_isolate()->factory(); } | 35 Factory* factory() { return CcTest::i_isolate()->factory(); } |
35 | 36 |
36 | 37 |
37 Handle<BytecodeArray> MakeBytecode(const char* script, | 38 Handle<BytecodeArray> MakeBytecode(const char* script, |
38 const char* function_name) { | 39 const char* function_name) { |
39 CompileRun(script); | 40 CompileRun(script); |
(...skipping 17 matching lines...) Expand all Loading... |
57 return MakeBytecode(program.start(), kFunctionName); | 58 return MakeBytecode(program.start(), kFunctionName); |
58 } | 59 } |
59 }; | 60 }; |
60 | 61 |
61 | 62 |
62 // Helper macros for handcrafting bytecode sequences. | 63 // Helper macros for handcrafting bytecode sequences. |
63 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 64 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
64 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 65 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
65 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 66 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
66 #define _ static_cast<uint8_t>(0x5a) | 67 #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 |
67 | 77 |
68 | 78 |
69 // Structure for containing expected bytecode snippets. | 79 // Structure for containing expected bytecode snippets. |
70 template<typename T> | 80 template<typename T> |
71 struct ExpectedSnippet { | 81 struct ExpectedSnippet { |
72 const char* code_snippet; | 82 const char* code_snippet; |
73 int frame_size; | 83 int frame_size; |
74 int parameter_count; | 84 int parameter_count; |
75 int bytecode_length; | 85 int bytecode_length; |
76 const uint8_t bytecode[512]; | 86 const uint8_t bytecode[512]; |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); | 687 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); |
678 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 688 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
679 } | 689 } |
680 } | 690 } |
681 | 691 |
682 | 692 |
683 TEST(LoadGlobal) { | 693 TEST(LoadGlobal) { |
684 InitializedHandleScope handle_scope; | 694 InitializedHandleScope handle_scope; |
685 BytecodeGeneratorHelper helper; | 695 BytecodeGeneratorHelper helper; |
686 | 696 |
687 ExpectedSnippet<const char*> snippets[] = { | 697 ExpectedSnippet<int> snippets[] = { |
688 {"var a = 1;\nfunction f() { return a; }\nf()", | 698 { |
689 0, 1, 3, | 699 "var a = 1;\nfunction f() { return a; }\nf()", |
690 { | 700 0, |
691 B(LdaGlobal), _, | 701 1, |
692 B(Return) | 702 3, |
693 }, | 703 { |
| 704 B(LdaGlobal), _, // |
| 705 B(Return) // |
| 706 }, |
694 }, | 707 }, |
695 {"function t() { }\nfunction f() { return t; }\nf()", | 708 { |
696 0, 1, 3, | 709 "function t() { }\nfunction f() { return t; }\nf()", |
697 { | 710 0, |
698 B(LdaGlobal), _, | 711 1, |
699 B(Return) | 712 3, |
700 }, | 713 { |
| 714 B(LdaGlobal), _, // |
| 715 B(Return) // |
| 716 }, |
701 }, | 717 }, |
702 }; | 718 }; |
703 | 719 |
704 for (size_t i = 0; i < arraysize(snippets); i++) { | 720 for (size_t i = 0; i < arraysize(snippets); i++) { |
705 Handle<BytecodeArray> bytecode_array = | 721 Handle<BytecodeArray> bytecode_array = |
706 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 722 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
707 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 723 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
708 } | 724 } |
709 } | 725 } |
710 | 726 |
711 | 727 |
712 TEST(CallGlobal) { | 728 TEST(CallGlobal) { |
713 InitializedHandleScope handle_scope; | 729 InitializedHandleScope handle_scope; |
714 BytecodeGeneratorHelper helper; | 730 BytecodeGeneratorHelper helper; |
715 | 731 |
716 ExpectedSnippet<const char*> snippets[] = { | 732 ExpectedSnippet<int> snippets[] = { |
717 {"function t() { }\nfunction f() { return t(); }\nf()", | 733 { |
718 2 * kPointerSize, 1, 12, | 734 "function t() { }\nfunction f() { return t(); }\nf()", |
719 { | 735 2 * kPointerSize, |
720 B(LdaUndefined), | 736 1, |
721 B(Star), R(1), | 737 12, |
722 B(LdaGlobal), _, | 738 { |
723 B(Star), R(0), | 739 B(LdaUndefined), // |
724 B(Call), R(0), R(1), U8(0), | 740 B(Star), R(1), // |
725 B(Return) | 741 B(LdaGlobal), _, // |
726 }, | 742 B(Star), R(0), // |
| 743 B(Call), R(0), R(1), U8(0), // |
| 744 B(Return) // |
| 745 }, |
727 }, | 746 }, |
728 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", | 747 { |
729 5 * kPointerSize, 1, 24, | 748 "function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", |
730 { | 749 5 * kPointerSize, |
731 B(LdaUndefined), | 750 1, |
732 B(Star), R(1), | 751 24, |
733 B(LdaGlobal), _, | 752 { |
734 B(Star), R(0), | 753 B(LdaUndefined), // |
735 B(LdaSmi8), U8(1), | 754 B(Star), R(1), // |
736 B(Star), R(2), | 755 B(LdaGlobal), _, // |
737 B(LdaSmi8), U8(2), | 756 B(Star), R(0), // |
738 B(Star), R(3), | 757 B(LdaSmi8), U8(1), // |
739 B(LdaSmi8), U8(3), | 758 B(Star), R(2), // |
740 B(Star), R(4), | 759 B(LdaSmi8), U8(2), // |
741 B(Call), R(0), R(1), U8(3), | 760 B(Star), R(3), // |
742 B(Return) | 761 B(LdaSmi8), U8(3), // |
743 }, | 762 B(Star), R(4), // |
| 763 B(Call), R(0), R(1), U8(3), // |
| 764 B(Return) // |
| 765 }, |
744 }, | 766 }, |
745 }; | 767 }; |
746 | 768 |
| 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 |
747 for (size_t i = 0; i < arraysize(snippets); i++) { | 822 for (size_t i = 0; i < arraysize(snippets); i++) { |
748 Handle<BytecodeArray> bytecode_array = | 823 Handle<BytecodeArray> bytecode_array = |
749 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 824 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
750 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 825 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
751 } | 826 } |
752 } | 827 } |
753 | 828 |
754 | 829 |
755 TEST(IfConditions) { | 830 TEST(IfConditions) { |
756 InitializedHandleScope handle_scope; | 831 InitializedHandleScope handle_scope; |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1181 for (size_t i = 0; i < arraysize(snippets); i++) { | 1256 for (size_t i = 0; i < arraysize(snippets); i++) { |
1182 Handle<BytecodeArray> bytecode_array = | 1257 Handle<BytecodeArray> bytecode_array = |
1183 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 1258 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
1184 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 1259 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
1185 } | 1260 } |
1186 } | 1261 } |
1187 | 1262 |
1188 } // namespace interpreter | 1263 } // namespace interpreter |
1189 } // namespace internal | 1264 } // namespace internal |
1190 } // namespace v8 | 1265 } // namespace v8 |
OLD | NEW |