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 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 i::FLAG_allow_natives_syntax = true; |
29 CcTest::i_isolate()->interpreter()->Initialize(); | 30 CcTest::i_isolate()->interpreter()->Initialize(); |
30 } | 31 } |
31 | 32 |
32 | 33 |
33 Factory* factory() { return CcTest::i_isolate()->factory(); } | 34 Factory* factory() { return CcTest::i_isolate()->factory(); } |
34 | 35 |
35 | 36 |
36 Handle<BytecodeArray> MakeBytecode(const char* script, | 37 Handle<BytecodeArray> MakeBytecode(const char* script, |
37 const char* function_name) { | 38 const char* function_name) { |
38 CompileRun(script); | 39 CompileRun(script); |
(...skipping 17 matching lines...) Expand all Loading... |
56 return MakeBytecode(program.start(), kFunctionName); | 57 return MakeBytecode(program.start(), kFunctionName); |
57 } | 58 } |
58 }; | 59 }; |
59 | 60 |
60 | 61 |
61 // Helper macros for handcrafting bytecode sequences. | 62 // Helper macros for handcrafting bytecode sequences. |
62 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 63 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
63 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 64 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
64 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 65 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
65 #define _ static_cast<uint8_t>(0x5a) | 66 #define _ static_cast<uint8_t>(0x5a) |
66 | 67 #if defined(V8_TARGET_LITTLE_ENDIAN) |
| 68 #define U16(x) static_cast<uint8_t>((x) & 0xff), \ |
| 69 static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff) |
| 70 #elif defined(V8_TARGET_BIG_ENDIAN) |
| 71 #define U16(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ |
| 72 static_cast<uint8_t>((x) & 0xff) |
| 73 #else |
| 74 #error Unknown byte ordering |
| 75 #endif |
67 | 76 |
68 // Structure for containing expected bytecode snippets. | 77 // Structure for containing expected bytecode snippets. |
69 template<typename T> | 78 template<typename T> |
70 struct ExpectedSnippet { | 79 struct ExpectedSnippet { |
71 const char* code_snippet; | 80 const char* code_snippet; |
72 int frame_size; | 81 int frame_size; |
73 int parameter_count; | 82 int parameter_count; |
74 int bytecode_length; | 83 int bytecode_length; |
75 const uint8_t bytecode[512]; | 84 const uint8_t bytecode[512]; |
76 int constant_count; | 85 int constant_count; |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 675 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
667 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 676 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
668 } | 677 } |
669 } | 678 } |
670 | 679 |
671 | 680 |
672 TEST(LoadGlobal) { | 681 TEST(LoadGlobal) { |
673 InitializedHandleScope handle_scope; | 682 InitializedHandleScope handle_scope; |
674 BytecodeGeneratorHelper helper; | 683 BytecodeGeneratorHelper helper; |
675 | 684 |
676 ExpectedSnippet<const char*> snippets[] = { | 685 ExpectedSnippet<int> snippets[] = { |
677 {"var a = 1;\nfunction f() { return a; }\nf()", | 686 { |
678 0, 1, 3, | 687 "var a = 1;\nfunction f() { return a; }\nf()", |
679 { | 688 0, |
680 B(LdaGlobal), _, | 689 1, |
681 B(Return) | 690 3, |
682 }, | 691 { |
| 692 B(LdaGlobal), _, // |
| 693 B(Return) // |
| 694 }, |
683 }, | 695 }, |
684 {"function t() { }\nfunction f() { return t; }\nf()", | 696 { |
685 0, 1, 3, | 697 "function t() { }\nfunction f() { return t; }\nf()", |
686 { | 698 0, |
687 B(LdaGlobal), _, | 699 1, |
688 B(Return) | 700 3, |
689 }, | 701 { |
| 702 B(LdaGlobal), _, // |
| 703 B(Return) // |
| 704 }, |
690 }, | 705 }, |
691 }; | 706 }; |
692 | 707 |
693 for (size_t i = 0; i < arraysize(snippets); i++) { | 708 for (size_t i = 0; i < arraysize(snippets); i++) { |
694 Handle<BytecodeArray> bytecode_array = | 709 Handle<BytecodeArray> bytecode_array = |
695 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 710 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
696 bytecode_array->Print(); | |
697 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 711 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
698 } | 712 } |
699 } | 713 } |
700 | 714 |
701 | 715 |
702 TEST(CallGlobal) { | 716 TEST(CallGlobal) { |
703 InitializedHandleScope handle_scope; | 717 InitializedHandleScope handle_scope; |
704 BytecodeGeneratorHelper helper; | 718 BytecodeGeneratorHelper helper; |
705 | 719 |
706 ExpectedSnippet<const char*> snippets[] = { | 720 ExpectedSnippet<int> snippets[] = { |
707 {"function t() { }\nfunction f() { return t(); }\nf()", | 721 { |
708 2 * kPointerSize, 1, 12, | 722 "function t() { }\nfunction f() { return t(); }\nf()", |
709 { | 723 2 * kPointerSize, |
710 B(LdaUndefined), | 724 1, |
711 B(Star), R(1), | 725 12, |
712 B(LdaGlobal), _, | 726 { |
713 B(Star), R(0), | 727 B(LdaUndefined), // |
714 B(Call), R(0), R(1), U8(0), | 728 B(Star), R(1), // |
715 B(Return) | 729 B(LdaGlobal), _, // |
716 }, | 730 B(Star), R(0), // |
| 731 B(Call), R(0), R(1), U8(0), // |
| 732 B(Return) // |
| 733 }, |
717 }, | 734 }, |
718 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", | 735 { |
719 5 * kPointerSize, 1, 24, | 736 "function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", |
720 { | 737 5 * kPointerSize, |
721 B(LdaUndefined), | 738 1, |
722 B(Star), R(1), | 739 24, |
723 B(LdaGlobal), _, | 740 { |
724 B(Star), R(0), | 741 B(LdaUndefined), // |
725 B(LdaSmi8), U8(1), | 742 B(Star), R(1), // |
726 B(Star), R(2), | 743 B(LdaGlobal), _, // |
727 B(LdaSmi8), U8(2), | 744 B(Star), R(0), // |
728 B(Star), R(3), | 745 B(LdaSmi8), U8(1), // |
729 B(LdaSmi8), U8(3), | 746 B(Star), R(2), // |
730 B(Star), R(4), | 747 B(LdaSmi8), U8(2), // |
731 B(Call), R(0), R(1), U8(3), | 748 B(Star), R(3), // |
732 B(Return) | 749 B(LdaSmi8), U8(3), // |
733 }, | 750 B(Star), R(4), // |
| 751 B(Call), R(0), R(1), U8(3), // |
| 752 B(Return) // |
| 753 }, |
734 }, | 754 }, |
735 }; | 755 }; |
736 | 756 |
| 757 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 758 for (size_t i = 0; i < num_snippets; i++) { |
| 759 Handle<BytecodeArray> bytecode_array = |
| 760 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 761 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 762 } |
| 763 } |
| 764 |
| 765 |
| 766 TEST(CallRuntime) { |
| 767 InitializedHandleScope handle_scope; |
| 768 BytecodeGeneratorHelper helper; |
| 769 |
| 770 ExpectedSnippet<int> snippets[] = { |
| 771 { |
| 772 "function f() { %TheHole() }\nf()", |
| 773 1 * kPointerSize, |
| 774 1, |
| 775 7, |
| 776 { |
| 777 B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), // |
| 778 B(LdaUndefined), // |
| 779 B(Return) // |
| 780 }, |
| 781 }, |
| 782 { |
| 783 "function f(a) { return %IsArray(a) }\nf(undefined)", |
| 784 1 * kPointerSize, |
| 785 2, |
| 786 10, |
| 787 { |
| 788 B(Ldar), R(helper.kLastParamIndex), // |
| 789 B(Star), R(0), // |
| 790 B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), // |
| 791 B(Return) // |
| 792 }, |
| 793 }, |
| 794 { |
| 795 "function f() { return %Add(1, 2) }\nf()", |
| 796 2 * kPointerSize, |
| 797 1, |
| 798 14, |
| 799 { |
| 800 B(LdaSmi8), U8(1), // |
| 801 B(Star), R(0), // |
| 802 B(LdaSmi8), U8(2), // |
| 803 B(Star), R(1), // |
| 804 B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2), // |
| 805 B(Return) // |
| 806 }, |
| 807 }, |
| 808 }; |
| 809 |
737 for (size_t i = 0; i < arraysize(snippets); i++) { | 810 for (size_t i = 0; i < arraysize(snippets); i++) { |
738 Handle<BytecodeArray> bytecode_array = | 811 Handle<BytecodeArray> bytecode_array = |
739 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 812 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
740 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 813 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
741 } | 814 } |
742 } | 815 } |
743 | 816 |
744 | 817 |
745 TEST(IfConditions) { | 818 TEST(IfConditions) { |
746 InitializedHandleScope handle_scope; | 819 InitializedHandleScope handle_scope; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 Handle<BytecodeArray> bytecode_array = | 959 Handle<BytecodeArray> bytecode_array = |
887 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 960 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
888 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 961 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
889 } | 962 } |
890 } | 963 } |
891 | 964 |
892 | 965 |
893 } // namespace interpreter | 966 } // namespace interpreter |
894 } // namespace internal | 967 } // namespace internal |
895 } // namespance v8 | 968 } // namespance v8 |
OLD | NEW |