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/bytecode-array-iterator.h" | 10 #include "src/interpreter/bytecode-array-iterator.h" |
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); | 783 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); |
784 | 784 |
785 // Test transition to megamorphic IC. | 785 // Test transition to megamorphic IC. |
786 Handle<Object> object2 = | 786 Handle<Object> object2 = |
787 InterpreterTester::NewObject("({ val : 456, other : 123 })"); | 787 InterpreterTester::NewObject("({ val : 456, other : 123 })"); |
788 callable(object2).ToHandleChecked(); | 788 callable(object2).ToHandleChecked(); |
789 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); | 789 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); |
790 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); | 790 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); |
791 } | 791 } |
792 | 792 |
793 static void TestInterpreterCall(TailCallMode tail_call_mode) { | 793 static void TestInterpreterCall(TailCallMode tail_call_mode, |
| 794 bool has_feedback_slot) { |
794 HandleAndZoneScope handles; | 795 HandleAndZoneScope handles; |
795 i::Isolate* isolate = handles.main_isolate(); | 796 i::Isolate* isolate = handles.main_isolate(); |
796 i::Factory* factory = isolate->factory(); | 797 i::Factory* factory = isolate->factory(); |
797 i::Zone zone(isolate->allocator()); | 798 i::Zone zone(isolate->allocator()); |
798 | 799 |
799 i::FeedbackVectorSpec feedback_spec(&zone); | 800 i::FeedbackVectorSpec feedback_spec(&zone); |
800 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); | 801 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); |
| 802 i::FeedbackVectorSlot call_slot = feedback_spec.AddCallICSlot(); |
801 | 803 |
802 Handle<i::TypeFeedbackVector> vector = | 804 Handle<i::TypeFeedbackVector> vector = |
803 i::NewTypeFeedbackVector(isolate, &feedback_spec); | 805 i::NewTypeFeedbackVector(isolate, &feedback_spec); |
804 int slot_index = vector->GetIndex(slot); | 806 int slot_index = vector->GetIndex(slot); |
| 807 int call_slot_index = -1; |
| 808 if (has_feedback_slot) { |
| 809 call_slot_index = vector->GetIndex(call_slot); |
| 810 } |
805 | 811 |
806 Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); | 812 Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); |
807 name = factory->string_table()->LookupString(isolate, name); | 813 name = factory->string_table()->LookupString(isolate, name); |
808 | 814 |
809 // Check with no args. | 815 // Check with no args. |
810 { | 816 { |
811 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 817 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
812 0, 1); | 818 0, 1); |
813 | 819 |
814 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) | 820 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) |
815 .StoreAccumulatorInRegister(Register(0)) | 821 .StoreAccumulatorInRegister(Register(0)); |
816 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) | 822 |
817 .Return(); | 823 if (has_feedback_slot) { |
| 824 builder.CallWithFeedback(Register(0), builder.Parameter(0), 1, |
| 825 call_slot_index, tail_call_mode); |
| 826 } else { |
| 827 builder.Call(Register(0), builder.Parameter(0), 1, tail_call_mode); |
| 828 } |
| 829 |
| 830 builder.Return(); |
818 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 831 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
819 | 832 |
820 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 833 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
821 auto callable = tester.GetCallable<Handle<Object>>(); | 834 auto callable = tester.GetCallable<Handle<Object>>(); |
822 | 835 |
823 Handle<Object> object = InterpreterTester::NewObject( | 836 Handle<Object> object = InterpreterTester::NewObject( |
824 "new (function Obj() { this.func = function() { return 0x265; }})()"); | 837 "new (function Obj() { this.func = function() { return 0x265; }})()"); |
825 Handle<Object> return_val = callable(object).ToHandleChecked(); | 838 Handle<Object> return_val = callable(object).ToHandleChecked(); |
826 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); | 839 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); |
827 } | 840 } |
828 | 841 |
829 // Check that receiver is passed properly. | 842 // Check that receiver is passed properly. |
830 { | 843 { |
831 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 844 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
832 0, 1); | 845 0, 1); |
833 | 846 |
834 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) | 847 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) |
835 .StoreAccumulatorInRegister(Register(0)) | 848 .StoreAccumulatorInRegister(Register(0)); |
836 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) | 849 if (has_feedback_slot) { |
837 .Return(); | 850 builder.CallWithFeedback(Register(0), builder.Parameter(0), 1, |
| 851 call_slot_index, tail_call_mode); |
| 852 } else { |
| 853 builder.Call(Register(0), builder.Parameter(0), 1, tail_call_mode); |
| 854 } |
| 855 builder.Return(); |
838 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 856 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
839 | 857 |
840 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 858 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
841 auto callable = tester.GetCallable<Handle<Object>>(); | 859 auto callable = tester.GetCallable<Handle<Object>>(); |
842 | 860 |
843 Handle<Object> object = InterpreterTester::NewObject( | 861 Handle<Object> object = InterpreterTester::NewObject( |
844 "new (function Obj() {" | 862 "new (function Obj() {" |
845 " this.val = 1234;" | 863 " this.val = 1234;" |
846 " this.func = function() { return this.val; };" | 864 " this.func = function() { return this.val; };" |
847 "})()"); | 865 "})()"); |
848 Handle<Object> return_val = callable(object).ToHandleChecked(); | 866 Handle<Object> return_val = callable(object).ToHandleChecked(); |
849 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); | 867 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); |
850 } | 868 } |
851 | 869 |
852 // Check with two parameters (+ receiver). | 870 // Check with two parameters (+ receiver). |
853 { | 871 { |
854 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, | 872 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
855 0, 4); | 873 0, 4); |
856 | 874 |
857 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) | 875 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) |
858 .StoreAccumulatorInRegister(Register(0)) | 876 .StoreAccumulatorInRegister(Register(0)) |
859 .LoadAccumulatorWithRegister(builder.Parameter(0)) | 877 .LoadAccumulatorWithRegister(builder.Parameter(0)) |
860 .StoreAccumulatorInRegister(Register(1)) | 878 .StoreAccumulatorInRegister(Register(1)) |
861 .LoadLiteral(Smi::FromInt(51)) | 879 .LoadLiteral(Smi::FromInt(51)) |
862 .StoreAccumulatorInRegister(Register(2)) | 880 .StoreAccumulatorInRegister(Register(2)) |
863 .LoadLiteral(Smi::FromInt(11)) | 881 .LoadLiteral(Smi::FromInt(11)) |
864 .StoreAccumulatorInRegister(Register(3)) | 882 .StoreAccumulatorInRegister(Register(3)); |
865 .Call(Register(0), Register(1), 3, 0, tail_call_mode) | 883 |
866 .Return(); | 884 if (has_feedback_slot) { |
| 885 builder.CallWithFeedback(Register(0), Register(1), 3, call_slot_index, |
| 886 tail_call_mode); |
| 887 } else { |
| 888 builder.Call(Register(0), Register(1), 3, tail_call_mode); |
| 889 } |
| 890 |
| 891 builder.Return(); |
| 892 |
867 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 893 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
868 | 894 |
869 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 895 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
870 auto callable = tester.GetCallable<Handle<Object>>(); | 896 auto callable = tester.GetCallable<Handle<Object>>(); |
871 | 897 |
872 Handle<Object> object = InterpreterTester::NewObject( | 898 Handle<Object> object = InterpreterTester::NewObject( |
873 "new (function Obj() { " | 899 "new (function Obj() { " |
874 " this.func = function(a, b) { return a - b; }" | 900 " this.func = function(a, b) { return a - b; }" |
875 "})()"); | 901 "})()"); |
876 Handle<Object> return_val = callable(object).ToHandleChecked(); | 902 Handle<Object> return_val = callable(object).ToHandleChecked(); |
(...skipping 21 matching lines...) Expand all Loading... |
898 .StoreAccumulatorInRegister(Register(6)) | 924 .StoreAccumulatorInRegister(Register(6)) |
899 .LoadLiteral(factory->NewStringFromAsciiChecked("f")) | 925 .LoadLiteral(factory->NewStringFromAsciiChecked("f")) |
900 .StoreAccumulatorInRegister(Register(7)) | 926 .StoreAccumulatorInRegister(Register(7)) |
901 .LoadLiteral(factory->NewStringFromAsciiChecked("g")) | 927 .LoadLiteral(factory->NewStringFromAsciiChecked("g")) |
902 .StoreAccumulatorInRegister(Register(8)) | 928 .StoreAccumulatorInRegister(Register(8)) |
903 .LoadLiteral(factory->NewStringFromAsciiChecked("h")) | 929 .LoadLiteral(factory->NewStringFromAsciiChecked("h")) |
904 .StoreAccumulatorInRegister(Register(9)) | 930 .StoreAccumulatorInRegister(Register(9)) |
905 .LoadLiteral(factory->NewStringFromAsciiChecked("i")) | 931 .LoadLiteral(factory->NewStringFromAsciiChecked("i")) |
906 .StoreAccumulatorInRegister(Register(10)) | 932 .StoreAccumulatorInRegister(Register(10)) |
907 .LoadLiteral(factory->NewStringFromAsciiChecked("j")) | 933 .LoadLiteral(factory->NewStringFromAsciiChecked("j")) |
908 .StoreAccumulatorInRegister(Register(11)) | 934 .StoreAccumulatorInRegister(Register(11)); |
909 .Call(Register(0), Register(1), 11, 0, tail_call_mode) | 935 |
910 .Return(); | 936 if (has_feedback_slot) { |
| 937 builder.CallWithFeedback(Register(0), Register(1), 11, call_slot_index, |
| 938 tail_call_mode); |
| 939 } else { |
| 940 builder.Call(Register(0), Register(1), 11, tail_call_mode); |
| 941 } |
| 942 |
| 943 builder.Return(); |
| 944 |
911 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); | 945 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
912 | 946 |
913 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); | 947 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
914 auto callable = tester.GetCallable<Handle<Object>>(); | 948 auto callable = tester.GetCallable<Handle<Object>>(); |
915 | 949 |
916 Handle<Object> object = InterpreterTester::NewObject( | 950 Handle<Object> object = InterpreterTester::NewObject( |
917 "new (function Obj() { " | 951 "new (function Obj() { " |
918 " this.prefix = \"prefix_\";" | 952 " this.prefix = \"prefix_\";" |
919 " this.func = function(a, b, c, d, e, f, g, h, i, j) {" | 953 " this.func = function(a, b, c, d, e, f, g, h, i, j) {" |
920 " return this.prefix + a + b + c + d + e + f + g + h + i + j;" | 954 " return this.prefix + a + b + c + d + e + f + g + h + i + j;" |
921 " }" | 955 " }" |
922 "})()"); | 956 "})()"); |
923 Handle<Object> return_val = callable(object).ToHandleChecked(); | 957 Handle<Object> return_val = callable(object).ToHandleChecked(); |
924 Handle<i::String> expected = | 958 Handle<i::String> expected = |
925 factory->NewStringFromAsciiChecked("prefix_abcdefghij"); | 959 factory->NewStringFromAsciiChecked("prefix_abcdefghij"); |
926 CHECK(i::String::cast(*return_val)->Equals(*expected)); | 960 CHECK(i::String::cast(*return_val)->Equals(*expected)); |
927 } | 961 } |
928 } | 962 } |
929 | 963 |
930 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); } | 964 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow, false); } |
931 | 965 |
932 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); } | 966 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow, false); } |
| 967 |
| 968 TEST(InterpreterCallWithFeedback) { |
| 969 TestInterpreterCall(TailCallMode::kDisallow, true); |
| 970 } |
| 971 |
| 972 TEST(InterpreterTailCallWithFeedback) { |
| 973 TestInterpreterCall(TailCallMode::kAllow, true); |
| 974 } |
933 | 975 |
934 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder, | 976 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder, |
935 Register reg, int value, | 977 Register reg, int value, |
936 Register scratch) { | 978 Register scratch) { |
937 return builder.StoreAccumulatorInRegister(scratch) | 979 return builder.StoreAccumulatorInRegister(scratch) |
938 .LoadLiteral(Smi::FromInt(value)) | 980 .LoadLiteral(Smi::FromInt(value)) |
939 .StoreAccumulatorInRegister(reg) | 981 .StoreAccumulatorInRegister(reg) |
940 .LoadAccumulatorWithRegister(scratch); | 982 .LoadAccumulatorWithRegister(scratch); |
941 } | 983 } |
942 | 984 |
(...skipping 3251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4194 Handle<i::Object> return_value = callable().ToHandleChecked(); | 4236 Handle<i::Object> return_value = callable().ToHandleChecked(); |
4195 CHECK(return_value->SameValue(*tests[i].second)); | 4237 CHECK(return_value->SameValue(*tests[i].second)); |
4196 } | 4238 } |
4197 | 4239 |
4198 FLAG_ignition_generators = old_flag; | 4240 FLAG_ignition_generators = old_flag; |
4199 } | 4241 } |
4200 | 4242 |
4201 } // namespace interpreter | 4243 } // namespace interpreter |
4202 } // namespace internal | 4244 } // namespace internal |
4203 } // namespace v8 | 4245 } // namespace v8 |
OLD | NEW |