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/execution.h" | 7 #include "src/execution.h" |
8 #include "src/handles.h" | 8 #include "src/handles.h" |
9 #include "src/interpreter/bytecode-array-builder.h" | 9 #include "src/interpreter/bytecode-array-builder.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); | 923 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); |
924 | 924 |
925 // Test transition to megamorphic IC. | 925 // Test transition to megamorphic IC. |
926 Handle<Object> object2 = | 926 Handle<Object> object2 = |
927 InterpreterTester::NewObject("({ val : 456, other : 123 })"); | 927 InterpreterTester::NewObject("({ val : 456, other : 123 })"); |
928 callable(object2).ToHandleChecked(); | 928 callable(object2).ToHandleChecked(); |
929 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); | 929 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); |
930 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); | 930 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); |
931 } | 931 } |
932 | 932 |
933 | 933 static void TestInterpreterCall(TailCallMode tail_call_mode) { |
934 TEST(InterpreterCall) { | |
935 HandleAndZoneScope handles; | 934 HandleAndZoneScope handles; |
936 i::Isolate* isolate = handles.main_isolate(); | 935 i::Isolate* isolate = handles.main_isolate(); |
937 i::Factory* factory = isolate->factory(); | 936 i::Factory* factory = isolate->factory(); |
938 i::Zone zone; | 937 i::Zone zone; |
939 | 938 |
940 i::FeedbackVectorSpec feedback_spec(&zone); | 939 i::FeedbackVectorSpec feedback_spec(&zone); |
941 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); | 940 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); |
942 | 941 |
943 Handle<i::TypeFeedbackVector> vector = | 942 Handle<i::TypeFeedbackVector> vector = |
944 i::NewTypeFeedbackVector(isolate, &feedback_spec); | 943 i::NewTypeFeedbackVector(isolate, &feedback_spec); |
945 int slot_index = vector->GetIndex(slot); | 944 int slot_index = vector->GetIndex(slot); |
946 | 945 |
947 Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); | 946 Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); |
948 name = factory->string_table()->LookupString(isolate, name); | 947 name = factory->string_table()->LookupString(isolate, name); |
949 | 948 |
950 // Check with no args. | 949 // Check with no args. |
951 { | 950 { |
952 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 951 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
953 0, 1); | 952 0, 1); |
954 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) | 953 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) |
955 .StoreAccumulatorInRegister(Register(0)) | 954 .StoreAccumulatorInRegister(Register(0)) |
956 .Call(Register(0), builder.Parameter(0), 1, 0) | 955 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) |
957 .Return(); | 956 .Return(); |
958 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 957 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
959 | 958 |
960 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 959 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
961 auto callable = tester.GetCallable<Handle<Object>>(); | 960 auto callable = tester.GetCallable<Handle<Object>>(); |
962 | 961 |
963 Handle<Object> object = InterpreterTester::NewObject( | 962 Handle<Object> object = InterpreterTester::NewObject( |
964 "new (function Obj() { this.func = function() { return 0x265; }})()"); | 963 "new (function Obj() { this.func = function() { return 0x265; }})()"); |
965 Handle<Object> return_val = callable(object).ToHandleChecked(); | 964 Handle<Object> return_val = callable(object).ToHandleChecked(); |
966 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); | 965 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); |
967 } | 966 } |
968 | 967 |
969 // Check that receiver is passed properly. | 968 // Check that receiver is passed properly. |
970 { | 969 { |
971 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 970 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
972 0, 1); | 971 0, 1); |
973 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) | 972 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) |
974 .StoreAccumulatorInRegister(Register(0)) | 973 .StoreAccumulatorInRegister(Register(0)) |
975 .Call(Register(0), builder.Parameter(0), 1, 0) | 974 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) |
976 .Return(); | 975 .Return(); |
977 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 976 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
978 | 977 |
979 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 978 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
980 auto callable = tester.GetCallable<Handle<Object>>(); | 979 auto callable = tester.GetCallable<Handle<Object>>(); |
981 | 980 |
982 Handle<Object> object = InterpreterTester::NewObject( | 981 Handle<Object> object = InterpreterTester::NewObject( |
983 "new (function Obj() {" | 982 "new (function Obj() {" |
984 " this.val = 1234;" | 983 " this.val = 1234;" |
985 " this.func = function() { return this.val; };" | 984 " this.func = function() { return this.val; };" |
986 "})()"); | 985 "})()"); |
987 Handle<Object> return_val = callable(object).ToHandleChecked(); | 986 Handle<Object> return_val = callable(object).ToHandleChecked(); |
988 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); | 987 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); |
989 } | 988 } |
990 | 989 |
991 // Check with two parameters (+ receiver). | 990 // Check with two parameters (+ receiver). |
992 { | 991 { |
993 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 992 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
994 0, 4); | 993 0, 4); |
995 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) | 994 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) |
996 .StoreAccumulatorInRegister(Register(0)) | 995 .StoreAccumulatorInRegister(Register(0)) |
997 .LoadAccumulatorWithRegister(builder.Parameter(0)) | 996 .LoadAccumulatorWithRegister(builder.Parameter(0)) |
998 .StoreAccumulatorInRegister(Register(1)) | 997 .StoreAccumulatorInRegister(Register(1)) |
999 .LoadLiteral(Smi::FromInt(51)) | 998 .LoadLiteral(Smi::FromInt(51)) |
1000 .StoreAccumulatorInRegister(Register(2)) | 999 .StoreAccumulatorInRegister(Register(2)) |
1001 .LoadLiteral(Smi::FromInt(11)) | 1000 .LoadLiteral(Smi::FromInt(11)) |
1002 .StoreAccumulatorInRegister(Register(3)) | 1001 .StoreAccumulatorInRegister(Register(3)) |
1003 .Call(Register(0), Register(1), 3, 0) | 1002 .Call(Register(0), Register(1), 3, 0, tail_call_mode) |
1004 .Return(); | 1003 .Return(); |
1005 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 1004 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
1006 | 1005 |
1007 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 1006 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
1008 auto callable = tester.GetCallable<Handle<Object>>(); | 1007 auto callable = tester.GetCallable<Handle<Object>>(); |
1009 | 1008 |
1010 Handle<Object> object = InterpreterTester::NewObject( | 1009 Handle<Object> object = InterpreterTester::NewObject( |
1011 "new (function Obj() { " | 1010 "new (function Obj() { " |
1012 " this.func = function(a, b) { return a - b; }" | 1011 " this.func = function(a, b) { return a - b; }" |
1013 "})()"); | 1012 "})()"); |
(...skipping 22 matching lines...) Expand all Loading... |
1036 .LoadLiteral(factory->NewStringFromAsciiChecked("f")) | 1035 .LoadLiteral(factory->NewStringFromAsciiChecked("f")) |
1037 .StoreAccumulatorInRegister(Register(7)) | 1036 .StoreAccumulatorInRegister(Register(7)) |
1038 .LoadLiteral(factory->NewStringFromAsciiChecked("g")) | 1037 .LoadLiteral(factory->NewStringFromAsciiChecked("g")) |
1039 .StoreAccumulatorInRegister(Register(8)) | 1038 .StoreAccumulatorInRegister(Register(8)) |
1040 .LoadLiteral(factory->NewStringFromAsciiChecked("h")) | 1039 .LoadLiteral(factory->NewStringFromAsciiChecked("h")) |
1041 .StoreAccumulatorInRegister(Register(9)) | 1040 .StoreAccumulatorInRegister(Register(9)) |
1042 .LoadLiteral(factory->NewStringFromAsciiChecked("i")) | 1041 .LoadLiteral(factory->NewStringFromAsciiChecked("i")) |
1043 .StoreAccumulatorInRegister(Register(10)) | 1042 .StoreAccumulatorInRegister(Register(10)) |
1044 .LoadLiteral(factory->NewStringFromAsciiChecked("j")) | 1043 .LoadLiteral(factory->NewStringFromAsciiChecked("j")) |
1045 .StoreAccumulatorInRegister(Register(11)) | 1044 .StoreAccumulatorInRegister(Register(11)) |
1046 .Call(Register(0), Register(1), 11, 0) | 1045 .Call(Register(0), Register(1), 11, 0, tail_call_mode) |
1047 .Return(); | 1046 .Return(); |
1048 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 1047 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
1049 | 1048 |
1050 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 1049 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
1051 auto callable = tester.GetCallable<Handle<Object>>(); | 1050 auto callable = tester.GetCallable<Handle<Object>>(); |
1052 | 1051 |
1053 Handle<Object> object = InterpreterTester::NewObject( | 1052 Handle<Object> object = InterpreterTester::NewObject( |
1054 "new (function Obj() { " | 1053 "new (function Obj() { " |
1055 " this.prefix = \"prefix_\";" | 1054 " this.prefix = \"prefix_\";" |
1056 " this.func = function(a, b, c, d, e, f, g, h, i, j) {" | 1055 " this.func = function(a, b, c, d, e, f, g, h, i, j) {" |
1057 " return this.prefix + a + b + c + d + e + f + g + h + i + j;" | 1056 " return this.prefix + a + b + c + d + e + f + g + h + i + j;" |
1058 " }" | 1057 " }" |
1059 "})()"); | 1058 "})()"); |
1060 Handle<Object> return_val = callable(object).ToHandleChecked(); | 1059 Handle<Object> return_val = callable(object).ToHandleChecked(); |
1061 Handle<i::String> expected = | 1060 Handle<i::String> expected = |
1062 factory->NewStringFromAsciiChecked("prefix_abcdefghij"); | 1061 factory->NewStringFromAsciiChecked("prefix_abcdefghij"); |
1063 CHECK(i::String::cast(*return_val)->Equals(*expected)); | 1062 CHECK(i::String::cast(*return_val)->Equals(*expected)); |
1064 } | 1063 } |
1065 } | 1064 } |
1066 | 1065 |
| 1066 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); } |
| 1067 |
| 1068 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); } |
1067 | 1069 |
1068 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder, | 1070 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder, |
1069 Register reg, int value, | 1071 Register reg, int value, |
1070 Register scratch) { | 1072 Register scratch) { |
1071 return builder.StoreAccumulatorInRegister(scratch) | 1073 return builder.StoreAccumulatorInRegister(scratch) |
1072 .LoadLiteral(Smi::FromInt(value)) | 1074 .LoadLiteral(Smi::FromInt(value)) |
1073 .StoreAccumulatorInRegister(reg) | 1075 .StoreAccumulatorInRegister(reg) |
1074 .LoadAccumulatorWithRegister(scratch); | 1076 .LoadAccumulatorWithRegister(scratch); |
1075 } | 1077 } |
1076 | 1078 |
(...skipping 3081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4158 Handle<i::Object> return_value = callable().ToHandleChecked(); | 4160 Handle<i::Object> return_value = callable().ToHandleChecked(); |
4159 CHECK(return_value->SameValue(*const_decl[i].second)); | 4161 CHECK(return_value->SameValue(*const_decl[i].second)); |
4160 } | 4162 } |
4161 | 4163 |
4162 FLAG_legacy_const = old_flag_legacy_const; | 4164 FLAG_legacy_const = old_flag_legacy_const; |
4163 } | 4165 } |
4164 | 4166 |
4165 } // namespace interpreter | 4167 } // namespace interpreter |
4166 } // namespace internal | 4168 } // namespace internal |
4167 } // namespace v8 | 4169 } // namespace v8 |
OLD | NEW |