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" |
(...skipping 16 matching lines...) Expand all Loading... |
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 i::FLAG_allow_natives_syntax = true; |
30 CcTest::i_isolate()->interpreter()->Initialize(); | 30 CcTest::i_isolate()->interpreter()->Initialize(); |
31 } | 31 } |
32 | 32 |
33 | 33 |
34 Factory* factory() { return CcTest::i_isolate()->factory(); } | 34 Factory* factory() { return CcTest::i_isolate()->factory(); } |
35 | 35 |
36 | 36 |
| 37 Handle<BytecodeArray> MakeTopLevelBytecode(const char* source) { |
| 38 const char* old_ignition_filter = i::FLAG_ignition_filter; |
| 39 i::FLAG_ignition_filter = "*"; |
| 40 Local<v8::Script> script = v8_compile(source); |
| 41 i::FLAG_ignition_filter = old_ignition_filter; |
| 42 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script); |
| 43 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
| 44 } |
| 45 |
| 46 |
37 Handle<BytecodeArray> MakeBytecode(const char* script, | 47 Handle<BytecodeArray> MakeBytecode(const char* script, |
38 const char* function_name) { | 48 const char* function_name) { |
39 CompileRun(script); | 49 CompileRun(script); |
40 Local<Function> function = | 50 Local<Function> function = |
41 Local<Function>::Cast(CcTest::global()->Get(v8_str(function_name))); | 51 Local<Function>::Cast(CcTest::global()->Get(v8_str(function_name))); |
42 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*function); | 52 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*function); |
43 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); | 53 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
44 } | 54 } |
45 | 55 |
46 | 56 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 119 } |
110 | 120 |
111 | 121 |
112 template <typename T> | 122 template <typename T> |
113 static void CheckBytecodeArrayEqual(struct ExpectedSnippet<T> expected, | 123 static void CheckBytecodeArrayEqual(struct ExpectedSnippet<T> expected, |
114 Handle<BytecodeArray> actual, | 124 Handle<BytecodeArray> actual, |
115 bool has_unknown = false) { | 125 bool has_unknown = false) { |
116 CHECK_EQ(actual->frame_size(), expected.frame_size); | 126 CHECK_EQ(actual->frame_size(), expected.frame_size); |
117 CHECK_EQ(actual->parameter_count(), expected.parameter_count); | 127 CHECK_EQ(actual->parameter_count(), expected.parameter_count); |
118 CHECK_EQ(actual->length(), expected.bytecode_length); | 128 CHECK_EQ(actual->length(), expected.bytecode_length); |
119 if (expected.constant_count == 0) { | 129 if (expected.constant_count != -1) { |
120 CHECK_EQ(actual->constant_pool(), CcTest::heap()->empty_fixed_array()); | 130 if (expected.constant_count == 0) { |
121 } else { | 131 CHECK_EQ(actual->constant_pool(), CcTest::heap()->empty_fixed_array()); |
122 CHECK_EQ(actual->constant_pool()->length(), expected.constant_count); | 132 } else { |
123 for (int i = 0; i < expected.constant_count; i++) { | 133 CHECK_EQ(actual->constant_pool()->length(), expected.constant_count); |
124 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); | 134 for (int i = 0; i < expected.constant_count; i++) { |
| 135 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); |
| 136 } |
125 } | 137 } |
126 } | 138 } |
127 | 139 |
128 BytecodeArrayIterator iterator(actual); | 140 BytecodeArrayIterator iterator(actual); |
129 int i = 0; | 141 int i = 0; |
130 while (!iterator.done()) { | 142 while (!iterator.done()) { |
131 int bytecode_index = i++; | 143 int bytecode_index = i++; |
132 Bytecode bytecode = iterator.current_bytecode(); | 144 Bytecode bytecode = iterator.current_bytecode(); |
133 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { | 145 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { |
134 std::ostringstream stream; | 146 std::ostringstream stream; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 ExpectedSnippet<int> snippets[] = { | 263 ExpectedSnippet<int> snippets[] = { |
252 {"function f() { return this; }", | 264 {"function f() { return this; }", |
253 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 265 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
254 {"function f(arg1) { return arg1; }", | 266 {"function f(arg1) { return arg1; }", |
255 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 267 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
256 {"function f(arg1) { return this; }", | 268 {"function f(arg1) { return this; }", |
257 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, | 269 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, |
258 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", | 270 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", |
259 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, | 271 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, |
260 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", | 272 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", |
261 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0} | 273 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0}, |
| 274 {"function f(arg1) { arg1 = 1; }", |
| 275 0, 2, 6, |
| 276 {B(LdaSmi8), U8(1), // |
| 277 B(Star), R(helper.kLastParamIndex), // |
| 278 B(LdaUndefined), // |
| 279 B(Return)}, |
| 280 0}, |
| 281 {"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }", |
| 282 0, 5, 6, |
| 283 {B(LdaSmi8), U8(1), // |
| 284 B(Star), R(helper.kLastParamIndex - 2), // |
| 285 B(LdaUndefined), // |
| 286 B(Return)}, |
| 287 0}, |
262 }; | 288 }; |
263 | 289 |
264 for (size_t i = 0; i < arraysize(snippets); i++) { | 290 for (size_t i = 0; i < arraysize(snippets); i++) { |
265 Handle<BytecodeArray> bytecode_array = | 291 Handle<BytecodeArray> bytecode_array = |
266 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 292 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
267 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 293 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
268 } | 294 } |
269 } | 295 } |
270 | 296 |
271 | 297 |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 }; | 732 }; |
707 | 733 |
708 for (size_t i = 0; i < arraysize(snippets); i++) { | 734 for (size_t i = 0; i < arraysize(snippets); i++) { |
709 Handle<BytecodeArray> bytecode_array = | 735 Handle<BytecodeArray> bytecode_array = |
710 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 736 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
711 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 737 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
712 } | 738 } |
713 } | 739 } |
714 | 740 |
715 | 741 |
| 742 TEST(StoreGlobal) { |
| 743 InitializedHandleScope handle_scope; |
| 744 BytecodeGeneratorHelper helper; |
| 745 |
| 746 ExpectedSnippet<int> snippets[] = { |
| 747 { |
| 748 "var a = 1;\nfunction f() { a = 2; }\nf()", |
| 749 0, |
| 750 1, |
| 751 6, |
| 752 { |
| 753 B(LdaSmi8), U8(2), // |
| 754 B(StaGlobal), _, // |
| 755 B(LdaUndefined), // |
| 756 B(Return) // |
| 757 }, |
| 758 }, |
| 759 { |
| 760 "var a = \"test\"; function f(b) { a = b; }\nf(\"global\")", |
| 761 0, |
| 762 2, |
| 763 6, |
| 764 { |
| 765 B(Ldar), R(helper.kLastParamIndex), // |
| 766 B(StaGlobal), _, // |
| 767 B(LdaUndefined), // |
| 768 B(Return) // |
| 769 }, |
| 770 }, |
| 771 }; |
| 772 |
| 773 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 774 Handle<BytecodeArray> bytecode_array = |
| 775 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 776 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 777 } |
| 778 } |
| 779 |
| 780 |
716 TEST(CallGlobal) { | 781 TEST(CallGlobal) { |
717 InitializedHandleScope handle_scope; | 782 InitializedHandleScope handle_scope; |
718 BytecodeGeneratorHelper helper; | 783 BytecodeGeneratorHelper helper; |
719 | 784 |
720 ExpectedSnippet<int> snippets[] = { | 785 ExpectedSnippet<int> snippets[] = { |
721 { | 786 { |
722 "function t() { }\nfunction f() { return t(); }\nf()", | 787 "function t() { }\nfunction f() { return t(); }\nf()", |
723 2 * kPointerSize, | 788 2 * kPointerSize, |
724 1, | 789 1, |
725 12, | 790 12, |
(...skipping 30 matching lines...) Expand all Loading... |
756 | 821 |
757 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 822 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
758 for (size_t i = 0; i < num_snippets; i++) { | 823 for (size_t i = 0; i < num_snippets; i++) { |
759 Handle<BytecodeArray> bytecode_array = | 824 Handle<BytecodeArray> bytecode_array = |
760 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 825 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
761 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); | 826 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
762 } | 827 } |
763 } | 828 } |
764 | 829 |
765 | 830 |
| 831 TEST(LoadUnallocated) { |
| 832 InitializedHandleScope handle_scope; |
| 833 BytecodeGeneratorHelper helper; |
| 834 |
| 835 int context_reg = Register::function_context().index(); |
| 836 int global_index = Context::GLOBAL_OBJECT_INDEX; |
| 837 Code::Kind ic_kinds[] = {i::Code::LOAD_IC}; |
| 838 FeedbackVectorSpec feedback_spec(0, 1, ic_kinds); |
| 839 Handle<i::TypeFeedbackVector> vector = |
| 840 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
| 841 |
| 842 ExpectedSnippet<const char*> snippets[] = { |
| 843 {"a = 1;\nfunction f() { return a; }\nf()", |
| 844 1 * kPointerSize, |
| 845 1, |
| 846 11, |
| 847 {B(LdaContextSlot), R(context_reg), U8(global_index), // |
| 848 B(Star), R(0), // |
| 849 B(LdaConstant), U8(0), // |
| 850 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), // |
| 851 B(Return)}, |
| 852 1, |
| 853 {"a"}}, |
| 854 {"function f() { return t; }\nf()\nt = 1;", |
| 855 1 * kPointerSize, |
| 856 1, |
| 857 11, |
| 858 {B(LdaContextSlot), R(context_reg), U8(global_index), // |
| 859 B(Star), R(0), // |
| 860 B(LdaConstant), U8(0), // |
| 861 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), // |
| 862 B(Return)}, |
| 863 1, |
| 864 {"t"}}, |
| 865 }; |
| 866 |
| 867 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 868 Handle<BytecodeArray> bytecode_array = |
| 869 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 870 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 871 } |
| 872 } |
| 873 |
| 874 |
| 875 TEST(StoreUnallocated) { |
| 876 InitializedHandleScope handle_scope; |
| 877 BytecodeGeneratorHelper helper; |
| 878 |
| 879 int context_reg = Register::function_context().index(); |
| 880 int global_index = Context::GLOBAL_OBJECT_INDEX; |
| 881 Code::Kind ic_kinds[] = {i::Code::LOAD_IC}; |
| 882 FeedbackVectorSpec feedback_spec(0, 1, ic_kinds); |
| 883 Handle<i::TypeFeedbackVector> vector = |
| 884 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
| 885 |
| 886 ExpectedSnippet<const char*> snippets[] = { |
| 887 {"a = 1;\nfunction f() { a = 2; }\nf()", |
| 888 3 * kPointerSize, |
| 889 1, |
| 890 21, |
| 891 {B(LdaSmi8), U8(2), // |
| 892 B(Star), R(0), // |
| 893 B(LdaContextSlot), R(context_reg), U8(global_index), // |
| 894 B(Star), R(1), // |
| 895 B(LdaConstant), U8(0), // |
| 896 B(Star), R(2), // |
| 897 B(Ldar), R(0), // |
| 898 B(StoreIC), R(1), R(2), U8(vector->first_ic_slot_index()), // |
| 899 B(LdaUndefined), // |
| 900 B(Return)}, |
| 901 1, |
| 902 {"a"}}, |
| 903 {"function f() { t = 4; }\nf()\nt = 1;", |
| 904 3 * kPointerSize, |
| 905 1, |
| 906 21, |
| 907 {B(LdaSmi8), U8(4), // |
| 908 B(Star), R(0), // |
| 909 B(LdaContextSlot), R(context_reg), U8(global_index), // |
| 910 B(Star), R(1), // |
| 911 B(LdaConstant), U8(0), // |
| 912 B(Star), R(2), // |
| 913 B(Ldar), R(0), // |
| 914 B(StoreIC), R(1), R(2), U8(vector->first_ic_slot_index()), // |
| 915 B(LdaUndefined), // |
| 916 B(Return)}, |
| 917 1, |
| 918 {"t"}}, |
| 919 }; |
| 920 |
| 921 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 922 Handle<BytecodeArray> bytecode_array = |
| 923 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 924 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 925 } |
| 926 } |
| 927 |
| 928 |
766 TEST(CallRuntime) { | 929 TEST(CallRuntime) { |
767 InitializedHandleScope handle_scope; | 930 InitializedHandleScope handle_scope; |
768 BytecodeGeneratorHelper helper; | 931 BytecodeGeneratorHelper helper; |
769 | 932 |
770 ExpectedSnippet<int> snippets[] = { | 933 ExpectedSnippet<int> snippets[] = { |
771 { | 934 { |
772 "function f() { %TheHole() }\nf()", | 935 "function f() { %TheHole() }\nf()", |
773 1 * kPointerSize, | 936 1 * kPointerSize, |
774 1, | 937 1, |
775 7, | 938 7, |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 B(Return), // | 1109 B(Return), // |
947 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | 1110 B(Jump), U8(5), // TODO(oth): Unreachable jump after return |
948 B(LdaConstant), U8(3), // | 1111 B(LdaConstant), U8(3), // |
949 B(Return), // | 1112 B(Return), // |
950 B(LdaUndefined), // | 1113 B(LdaUndefined), // |
951 B(Return)}, // | 1114 B(Return)}, // |
952 4, | 1115 4, |
953 {helper.factory()->NewHeapNumber(0.01), | 1116 {helper.factory()->NewHeapNumber(0.01), |
954 helper.factory()->NewNumberFromInt(200), | 1117 helper.factory()->NewNumberFromInt(200), |
955 helper.factory()->NewNumberFromInt(199), | 1118 helper.factory()->NewNumberFromInt(199), |
956 helper.factory()->NewNumberFromInt(-200)}}}; | 1119 helper.factory()->NewNumberFromInt(-200)}} |
| 1120 }; |
957 | 1121 |
958 for (size_t i = 0; i < arraysize(snippets); i++) { | 1122 for (size_t i = 0; i < arraysize(snippets); i++) { |
959 Handle<BytecodeArray> bytecode_array = | 1123 Handle<BytecodeArray> bytecode_array = |
960 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 1124 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
961 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 1125 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
962 } | 1126 } |
963 } | 1127 } |
964 | 1128 |
965 | 1129 |
| 1130 TEST(DeclareGlobals) { |
| 1131 InitializedHandleScope handle_scope; |
| 1132 BytecodeGeneratorHelper helper; |
| 1133 |
| 1134 ExpectedSnippet<int> snippets[] = { |
| 1135 {"var a = 1;", |
| 1136 4 * kPointerSize, |
| 1137 1, |
| 1138 30, |
| 1139 { |
| 1140 B(LdaConstant), U8(0), // |
| 1141 B(Star), R(1), // |
| 1142 B(LdaZero), // |
| 1143 B(Star), R(2), // |
| 1144 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // |
| 1145 B(LdaConstant), U8(1), // |
| 1146 B(Star), R(1), // |
| 1147 B(LdaZero), // |
| 1148 B(Star), R(2), // |
| 1149 B(LdaSmi8), U8(1), // |
| 1150 B(Star), R(3), // |
| 1151 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), // |
| 1152 U8(3), // |
| 1153 B(LdaUndefined), // |
| 1154 B(Return) // |
| 1155 }, |
| 1156 -1}, |
| 1157 {"function f() {}", |
| 1158 2 * kPointerSize, |
| 1159 1, |
| 1160 14, |
| 1161 { |
| 1162 B(LdaConstant), U8(0), // |
| 1163 B(Star), R(0), // |
| 1164 B(LdaZero), // |
| 1165 B(Star), R(1), // |
| 1166 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2), // |
| 1167 B(LdaUndefined), // |
| 1168 B(Return) // |
| 1169 }, |
| 1170 -1}, |
| 1171 }; |
| 1172 |
| 1173 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 1174 Handle<BytecodeArray> bytecode_array = |
| 1175 helper.MakeTopLevelBytecode(snippets[i].code_snippet); |
| 1176 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 1177 } |
| 1178 } |
| 1179 |
| 1180 |
966 } // namespace interpreter | 1181 } // namespace interpreter |
967 } // namespace internal | 1182 } // namespace internal |
968 } // namespance v8 | 1183 } // namespance v8 |
OLD | NEW |