| 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 |