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