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