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_ignition = true; | 26 i::FLAG_ignition = true; |
27 i::FLAG_ignition_fake_try_catch = true; | 27 i::FLAG_ignition_fake_try_catch = true; |
| 28 i::FLAG_ignition_fallback_on_eval_and_catch = false; |
28 i::FLAG_ignition_filter = StrDup(kFunctionName); | 29 i::FLAG_ignition_filter = StrDup(kFunctionName); |
29 i::FLAG_always_opt = false; | 30 i::FLAG_always_opt = false; |
30 i::FLAG_allow_natives_syntax = true; | 31 i::FLAG_allow_natives_syntax = true; |
31 CcTest::i_isolate()->interpreter()->Initialize(); | 32 CcTest::i_isolate()->interpreter()->Initialize(); |
32 } | 33 } |
33 | 34 |
34 Isolate* isolate() { return CcTest::i_isolate(); } | 35 Isolate* isolate() { return CcTest::i_isolate(); } |
35 Factory* factory() { return CcTest::i_isolate()->factory(); } | 36 Factory* factory() { return CcTest::i_isolate()->factory(); } |
36 | 37 |
37 Handle<BytecodeArray> MakeTopLevelBytecode(const char* source) { | 38 Handle<BytecodeArray> MakeTopLevelBytecode(const char* source) { |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 | 1235 |
1235 | 1236 |
1236 TEST(PropertyCall) { | 1237 TEST(PropertyCall) { |
1237 InitializedHandleScope handle_scope; | 1238 InitializedHandleScope handle_scope; |
1238 BytecodeGeneratorHelper helper; | 1239 BytecodeGeneratorHelper helper; |
1239 Zone zone; | 1240 Zone zone; |
1240 | 1241 |
1241 FeedbackVectorSpec feedback_spec(&zone); | 1242 FeedbackVectorSpec feedback_spec(&zone); |
1242 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); | 1243 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); |
1243 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); | 1244 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); |
1244 USE(slot1); | |
1245 | 1245 |
1246 Handle<i::TypeFeedbackVector> vector = | 1246 Handle<i::TypeFeedbackVector> vector = |
1247 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); | 1247 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); |
1248 | 1248 |
1249 // These are a hack used by the CallWide test below. | 1249 // These are a hack used by the CallWide test below. |
1250 int wide_idx = vector->GetIndex(slot1) - 2; | 1250 int wide_idx = vector->GetIndex(slot1) - 2; |
1251 | 1251 |
1252 ExpectedSnippet<const char*> snippets[] = { | 1252 ExpectedSnippet<const char*> snippets[] = { |
1253 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", | 1253 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", |
1254 2 * kPointerSize, | 1254 2 * kPointerSize, |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 | 1549 |
1550 | 1550 |
1551 TEST(CallGlobal) { | 1551 TEST(CallGlobal) { |
1552 InitializedHandleScope handle_scope; | 1552 InitializedHandleScope handle_scope; |
1553 BytecodeGeneratorHelper helper; | 1553 BytecodeGeneratorHelper helper; |
1554 Zone zone; | 1554 Zone zone; |
1555 | 1555 |
1556 FeedbackVectorSpec feedback_spec(&zone); | 1556 FeedbackVectorSpec feedback_spec(&zone); |
1557 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); | 1557 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); |
1558 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); | 1558 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); |
1559 USE(slot1); | |
1560 | 1559 |
1561 Handle<i::TypeFeedbackVector> vector = | 1560 Handle<i::TypeFeedbackVector> vector = |
1562 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); | 1561 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); |
1563 | 1562 |
1564 ExpectedSnippet<const char*> snippets[] = { | 1563 ExpectedSnippet<const char*> snippets[] = { |
1565 {"function t() { }\nfunction f() { return t(); }\nf()", | 1564 {"function t() { }\nfunction f() { return t(); }\nf()", |
1566 2 * kPointerSize, | 1565 2 * kPointerSize, |
1567 1, | 1566 1, |
1568 14, | 1567 14, |
1569 { | 1568 { |
(...skipping 4266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5836 0}}; | 5835 0}}; |
5837 | 5836 |
5838 for (size_t i = 0; i < arraysize(snippets); i++) { | 5837 for (size_t i = 0; i < arraysize(snippets); i++) { |
5839 Handle<BytecodeArray> bytecode_array = | 5838 Handle<BytecodeArray> bytecode_array = |
5840 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 5839 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
5841 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 5840 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
5842 } | 5841 } |
5843 } | 5842 } |
5844 | 5843 |
5845 | 5844 |
| 5845 TEST(Eval) { |
| 5846 InitializedHandleScope handle_scope; |
| 5847 BytecodeGeneratorHelper helper; |
| 5848 Zone zone; |
| 5849 |
| 5850 int closure = Register::function_closure().index(); |
| 5851 int context = Register::function_context().index(); |
| 5852 int new_target = Register::new_target().index(); |
| 5853 |
| 5854 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 5855 |
| 5856 ExpectedSnippet<const char*> snippets[] = { |
| 5857 {"return eval('1;');", |
| 5858 9 * kPointerSize, |
| 5859 1, |
| 5860 73, |
| 5861 { |
| 5862 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5863 U8(1), // |
| 5864 B(PushContext), R(0), // |
| 5865 B(Ldar), THIS(1), // |
| 5866 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5867 B(CreateMappedArguments), // |
| 5868 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5869 B(Ldar), R(new_target), // |
| 5870 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5871 B(Mov), R(context), R(3), // |
| 5872 B(LdaConstant), U8(0), // |
| 5873 B(Star), R(4), // |
| 5874 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // |
| 5875 R(3), U8(2), R(3), // |
| 5876 B(Mov), R(3), R(1), // |
| 5877 B(Mov), R(4), R(2), // |
| 5878 B(LdaConstant), U8(1), // |
| 5879 B(Star), R(3), // |
| 5880 B(Mov), R(1), R(4), // |
| 5881 B(Mov), R(3), R(5), // |
| 5882 B(Mov), R(closure), R(6), // |
| 5883 B(LdaZero), // |
| 5884 B(Star), R(7), // |
| 5885 B(LdaSmi8), U8(10), // |
| 5886 B(Star), R(8), // |
| 5887 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5888 U8(5), // |
| 5889 B(Star), R(1), // |
| 5890 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5891 B(Return), // |
| 5892 }, |
| 5893 2, |
| 5894 {"eval", "1;"}}, |
| 5895 }; |
| 5896 |
| 5897 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 5898 Handle<BytecodeArray> bytecode_array = |
| 5899 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 5900 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 5901 } |
| 5902 } |
| 5903 |
| 5904 |
| 5905 TEST(LookupSlot) { |
| 5906 InitializedHandleScope handle_scope; |
| 5907 BytecodeGeneratorHelper helper; |
| 5908 |
| 5909 int closure = Register::function_closure().index(); |
| 5910 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 5911 int context = Register::function_context().index(); |
| 5912 int new_target = Register::new_target().index(); |
| 5913 |
| 5914 ExpectedSnippet<const char*> snippets[] = { |
| 5915 {"eval('var x = 10;'); return x;", |
| 5916 9 * kPointerSize, |
| 5917 1, |
| 5918 75, |
| 5919 { |
| 5920 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5921 U8(1), // |
| 5922 B(PushContext), R(0), // |
| 5923 B(Ldar), THIS(1), // |
| 5924 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5925 B(CreateMappedArguments), // |
| 5926 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5927 B(Ldar), R(new_target), // |
| 5928 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5929 B(Mov), R(context), R(3), // |
| 5930 B(LdaConstant), U8(0), // |
| 5931 B(Star), R(4), // |
| 5932 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // |
| 5933 R(3), U8(2), R(3), // |
| 5934 B(Mov), R(3), R(1), // |
| 5935 B(Mov), R(4), R(2), // |
| 5936 B(LdaConstant), U8(1), // |
| 5937 B(Star), R(3), // |
| 5938 B(Mov), R(1), R(4), // |
| 5939 B(Mov), R(3), R(5), // |
| 5940 B(Mov), R(closure), R(6), // |
| 5941 B(LdaZero), // |
| 5942 B(Star), R(7), // |
| 5943 B(LdaSmi8), U8(10), // |
| 5944 B(Star), R(8), // |
| 5945 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5946 U8(5), // |
| 5947 B(Star), R(1), // |
| 5948 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5949 B(LdaLookupSlot), U8(2), // |
| 5950 B(Return), // |
| 5951 }, |
| 5952 3, |
| 5953 {"eval", "var x = 10;", "x"}}, |
| 5954 {"eval('var x = 10;'); return typeof x;", |
| 5955 9 * kPointerSize, |
| 5956 1, |
| 5957 76, |
| 5958 { |
| 5959 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5960 U8(1), // |
| 5961 B(PushContext), R(0), // |
| 5962 B(Ldar), THIS(1), // |
| 5963 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5964 B(CreateMappedArguments), // |
| 5965 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5966 B(Ldar), R(new_target), // |
| 5967 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5968 B(Mov), R(context), R(3), // |
| 5969 B(LdaConstant), U8(0), // |
| 5970 B(Star), R(4), // |
| 5971 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // |
| 5972 R(3), U8(2), R(3), // |
| 5973 B(Mov), R(3), R(1), // |
| 5974 B(Mov), R(4), R(2), // |
| 5975 B(LdaConstant), U8(1), // |
| 5976 B(Star), R(3), // |
| 5977 B(Mov), R(1), R(4), // |
| 5978 B(Mov), R(3), R(5), // |
| 5979 B(Mov), R(closure), R(6), // |
| 5980 B(LdaZero), // |
| 5981 B(Star), R(7), // |
| 5982 B(LdaSmi8), U8(10), // |
| 5983 B(Star), R(8), // |
| 5984 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5985 U8(5), // |
| 5986 B(Star), R(1), // |
| 5987 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5988 B(LdaLookupSlotInsideTypeof), U8(2), // |
| 5989 B(TypeOf), // |
| 5990 B(Return), // |
| 5991 }, |
| 5992 3, |
| 5993 {"eval", "var x = 10;", "x"}}, |
| 5994 {"x = 20; return eval('');", |
| 5995 9 * kPointerSize, |
| 5996 1, |
| 5997 77, |
| 5998 { |
| 5999 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 6000 U8(1), // |
| 6001 B(PushContext), R(0), // |
| 6002 B(Ldar), THIS(1), // |
| 6003 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 6004 B(CreateMappedArguments), // |
| 6005 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 6006 B(Ldar), R(new_target), // |
| 6007 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 6008 B(LdaSmi8), U8(20), // |
| 6009 B(StaLookupSlotSloppy), U8(0), // |
| 6010 B(Mov), R(context), R(3), // |
| 6011 B(LdaConstant), U8(1), // |
| 6012 B(Star), R(4), // |
| 6013 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // |
| 6014 R(3), U8(2), R(3), // |
| 6015 B(Mov), R(3), R(1), // |
| 6016 B(Mov), R(4), R(2), // |
| 6017 B(LdaConstant), U8(2), // |
| 6018 B(Star), R(3), // |
| 6019 B(Mov), R(1), R(4), // |
| 6020 B(Mov), R(3), R(5), // |
| 6021 B(Mov), R(closure), R(6), // |
| 6022 B(LdaZero), // |
| 6023 B(Star), R(7), // |
| 6024 B(LdaSmi8), U8(10), // |
| 6025 B(Star), R(8), // |
| 6026 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 6027 U8(5), // |
| 6028 B(Star), R(1), // |
| 6029 B(Call), R(1), R(2), U8(1), U8(0), // |
| 6030 B(Return), // |
| 6031 }, |
| 6032 3, |
| 6033 {"x", "eval", ""}}, |
| 6034 }; |
| 6035 |
| 6036 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 6037 Handle<BytecodeArray> bytecode_array = |
| 6038 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 6039 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 6040 } |
| 6041 } |
| 6042 |
| 6043 |
5846 TEST(LookupSlotInEval) { | 6044 TEST(LookupSlotInEval) { |
5847 InitializedHandleScope handle_scope; | 6045 InitializedHandleScope handle_scope; |
5848 BytecodeGeneratorHelper helper; | 6046 BytecodeGeneratorHelper helper; |
5849 | 6047 |
5850 const char* function_prologue = "var f;" | 6048 const char* function_prologue = "var f;" |
5851 "var x = 1;" | 6049 "var x = 1;" |
5852 "function f1() {" | 6050 "function f1() {" |
5853 " eval(\"function t() {"; | 6051 " eval(\"function t() {"; |
5854 const char* function_epilogue = " }; f = t; f();\");" | 6052 const char* function_epilogue = " }; f = t; f();\");" |
5855 "}" | 6053 "}" |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6006 std::string(function_epilogue); | 6204 std::string(function_epilogue); |
6007 // TODO(mythria): use * as filter when function declarations are supported | 6205 // TODO(mythria): use * as filter when function declarations are supported |
6008 // inside eval. | 6206 // inside eval. |
6009 Handle<BytecodeArray> bytecode_array = | 6207 Handle<BytecodeArray> bytecode_array = |
6010 helper.MakeBytecode(script.c_str(), "t", "f"); | 6208 helper.MakeBytecode(script.c_str(), "t", "f"); |
6011 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 6209 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
6012 } | 6210 } |
6013 } | 6211 } |
6014 | 6212 |
6015 | 6213 |
6016 TEST(DeleteLookupSlot) { | 6214 TEST(DeleteLookupSlotInEval) { |
6017 InitializedHandleScope handle_scope; | 6215 InitializedHandleScope handle_scope; |
6018 BytecodeGeneratorHelper helper; | 6216 BytecodeGeneratorHelper helper; |
6019 | 6217 |
6020 const char* function_prologue = "var f;" | 6218 const char* function_prologue = "var f;" |
6021 "var x = 1;" | 6219 "var x = 1;" |
6022 "z = 10;" | 6220 "z = 10;" |
6023 "function f1() {" | 6221 "function f1() {" |
6024 " var y;" | 6222 " var y;" |
6025 " eval(\"function t() {"; | 6223 " eval(\"function t() {"; |
6026 const char* function_epilogue = " }; f = t; f();\");" | 6224 const char* function_epilogue = " }; f = t; f();\");" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6068 std::string(function_epilogue); | 6266 std::string(function_epilogue); |
6069 Handle<BytecodeArray> bytecode_array = | 6267 Handle<BytecodeArray> bytecode_array = |
6070 helper.MakeBytecode(script.c_str(), "t", "f"); | 6268 helper.MakeBytecode(script.c_str(), "t", "f"); |
6071 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 6269 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
6072 } | 6270 } |
6073 } | 6271 } |
6074 | 6272 |
6075 } // namespace interpreter | 6273 } // namespace interpreter |
6076 } // namespace internal | 6274 } // namespace internal |
6077 } // namespace v8 | 6275 } // namespace v8 |
OLD | NEW |