| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 IC::UtilityId id) { | 760 IC::UtilityId id) { |
| 761 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 761 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 762 __ CallExternalReference( | 762 __ CallExternalReference( |
| 763 ExternalReference(IC_Utility(id), masm->isolate()), | 763 ExternalReference(IC_Utility(id), masm->isolate()), |
| 764 StubCache::kInterceptorArgsLength); | 764 StubCache::kInterceptorArgsLength); |
| 765 } | 765 } |
| 766 | 766 |
| 767 | 767 |
| 768 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 768 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 769 | 769 |
| 770 // Reserves space for the extra arguments to API function in the | |
| 771 // caller's frame. | |
| 772 // | |
| 773 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. | |
| 774 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | |
| 775 Register scratch) { | |
| 776 ASSERT(Smi::FromInt(0) == 0); | |
| 777 for (int i = 0; i < kFastApiCallArguments; i++) { | |
| 778 __ push(zero_reg); | |
| 779 } | |
| 780 } | |
| 781 | 770 |
| 771 static void GenerateFastApiCallBody(MacroAssembler* masm, |
| 772 const CallOptimization& optimization, |
| 773 int argc, |
| 774 Register holder, |
| 775 Register scratch1, |
| 776 Register scratch2, |
| 777 Register scratch3, |
| 778 bool restore_context) { |
| 779 // ----------- S t a t e ------------- |
| 780 // -- sp[0] : last JS argument |
| 781 // -- ... |
| 782 // -- sp[(argc - 1) * 4] : first JS argument |
| 783 // -- sp[argc * 4] : receiver |
| 784 // ----------------------------------- |
| 785 ASSERT(optimization.is_simple_api_call()); |
| 782 | 786 |
| 783 // Undoes the effects of ReserveSpaceForFastApiCall. | 787 typedef FunctionCallbackArguments FCA; |
| 784 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | |
| 785 __ Drop(kFastApiCallArguments); | |
| 786 } | |
| 787 | 788 |
| 789 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| 790 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 791 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 792 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 793 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 794 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 795 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 796 STATIC_ASSERT(FCA::kArgsLength == 7); |
| 788 | 797 |
| 789 static void GenerateFastApiDirectCall(MacroAssembler* masm, | 798 ASSERT(!holder.is(cp)); |
| 790 const CallOptimization& optimization, | 799 |
| 791 int argc, | |
| 792 bool restore_context) { | |
| 793 // ----------- S t a t e ------------- | |
| 794 // -- sp[0] - sp[24] : FunctionCallbackInfo, incl. | |
| 795 // : holder (set by CheckPrototypes) | |
| 796 // -- sp[28] : last JS argument | |
| 797 // -- ... | |
| 798 // -- sp[(argc + 6) * 4] : first JS argument | |
| 799 // -- sp[(argc + 7) * 4] : receiver | |
| 800 // ----------------------------------- | |
| 801 typedef FunctionCallbackArguments FCA; | |
| 802 // Save calling context. | 800 // Save calling context. |
| 803 __ sw(cp, MemOperand(sp, FCA::kContextSaveIndex * kPointerSize)); | 801 __ push(cp); |
| 804 // Get the function and setup the context. | 802 // Get the function and setup the context. |
| 805 Handle<JSFunction> function = optimization.constant_function(); | 803 Handle<JSFunction> function = optimization.constant_function(); |
| 806 __ li(t1, function); | 804 __ li(scratch1, function); |
| 807 __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); | 805 __ lw(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset)); |
| 808 __ sw(t1, MemOperand(sp, FCA::kCalleeIndex * kPointerSize)); | 806 __ push(scratch1); |
| 809 | 807 |
| 810 // Construct the FunctionCallbackInfo. | 808 // Construct the FunctionCallbackInfo. |
| 811 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 809 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 812 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 810 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
| 811 bool call_data_undefined = false; |
| 813 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 812 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 814 __ li(a0, api_call_info); | 813 __ li(scratch1, api_call_info); |
| 815 __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset)); | 814 __ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); |
| 815 } else if (call_data->IsUndefined()) { |
| 816 call_data_undefined = true; |
| 817 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); |
| 816 } else { | 818 } else { |
| 817 __ li(t2, call_data); | 819 __ li(scratch1, call_data); |
| 818 } | 820 } |
| 819 // Store call data. | 821 // Store call data. |
| 820 __ sw(t2, MemOperand(sp, FCA::kDataIndex * kPointerSize)); | 822 __ push(scratch1); |
| 823 if (!call_data_undefined) { |
| 824 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); |
| 825 } |
| 826 // Store ReturnValue default and ReturnValue. |
| 827 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); |
| 828 __ Push(scratch1, scratch1); |
| 821 // Store isolate. | 829 // Store isolate. |
| 822 __ li(t3, Operand(ExternalReference::isolate_address(masm->isolate()))); | 830 __ li(scratch1, Operand(ExternalReference::isolate_address(masm->isolate()))); |
| 823 __ sw(t3, MemOperand(sp, FCA::kIsolateIndex * kPointerSize)); | 831 __ push(scratch1); |
| 824 // Store ReturnValue default and ReturnValue. | 832 // Store holder. |
| 825 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); | 833 __ push(holder); |
| 826 __ sw(t1, MemOperand(sp, FCA::kReturnValueOffset * kPointerSize)); | |
| 827 __ sw(t1, MemOperand(sp, FCA::kReturnValueDefaultValueIndex * kPointerSize)); | |
| 828 | 834 |
| 829 // Prepare arguments. | 835 // Prepare arguments. |
| 830 __ Move(a2, sp); | 836 __ Move(a2, sp); |
| 831 | 837 |
| 832 // Allocate the v8::Arguments structure in the arguments' space since | 838 // Allocate the v8::Arguments structure in the arguments' space since |
| 833 // it's not controlled by GC. | 839 // it's not controlled by GC. |
| 834 const int kApiStackSpace = 4; | 840 const int kApiStackSpace = 4; |
| 835 | 841 |
| 836 FrameScope frame_scope(masm, StackFrame::MANUAL); | 842 FrameScope frame_scope(masm, StackFrame::MANUAL); |
| 837 __ EnterExitFrame(false, kApiStackSpace); | 843 __ EnterExitFrame(false, kApiStackSpace); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 function_address, | 880 function_address, |
| 875 thunk_ref, | 881 thunk_ref, |
| 876 a1, | 882 a1, |
| 877 kStackUnwindSpace, | 883 kStackUnwindSpace, |
| 878 return_value_operand, | 884 return_value_operand, |
| 879 restore_context ? | 885 restore_context ? |
| 880 &context_restore_operand : NULL); | 886 &context_restore_operand : NULL); |
| 881 } | 887 } |
| 882 | 888 |
| 883 | 889 |
| 890 // Generates call to API function. |
| 891 static void GenerateFastApiCall(MacroAssembler* masm, |
| 892 const CallOptimization& optimization, |
| 893 int argc, |
| 894 Handle<Map> map_to_holder, |
| 895 CallOptimization::HolderLookup holder_lookup) { |
| 896 Counters* counters = masm->isolate()->counters(); |
| 897 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1); |
| 898 |
| 899 // Move holder to a register. |
| 900 Register holder_reg = a0; |
| 901 switch (holder_lookup) { |
| 902 case CallOptimization::kHolderIsReceiver: |
| 903 { |
| 904 ASSERT(map_to_holder.is_null()); |
| 905 __ lw(holder_reg, MemOperand(sp, argc * kPointerSize)); |
| 906 } |
| 907 break; |
| 908 case CallOptimization::kHolderIsPrototypeOfMap: |
| 909 { |
| 910 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype())); |
| 911 if (!masm->isolate()->heap()->InNewSpace(*holder)) { |
| 912 __ li(holder_reg, holder); |
| 913 } else { |
| 914 __ li(holder_reg, map_to_holder); |
| 915 __ lw(holder_reg, |
| 916 FieldMemOperand(holder_reg, Map::kPrototypeOffset)); |
| 917 } |
| 918 } |
| 919 break; |
| 920 case CallOptimization::kHolderNotFound: |
| 921 UNREACHABLE(); |
| 922 } |
| 923 GenerateFastApiCallBody(masm, |
| 924 optimization, |
| 925 argc, |
| 926 holder_reg, |
| 927 a1, |
| 928 a2, |
| 929 a3, |
| 930 false); |
| 931 } |
| 932 |
| 933 |
| 884 // Generate call to api function. | 934 // Generate call to api function. |
| 885 static void GenerateFastApiCall(MacroAssembler* masm, | 935 static void GenerateFastApiCall(MacroAssembler* masm, |
| 886 const CallOptimization& optimization, | 936 const CallOptimization& optimization, |
| 887 Register receiver, | 937 Register receiver, |
| 888 Register scratch, | 938 Register scratch, |
| 889 int argc, | 939 int argc, |
| 890 Register* values) { | 940 Register* values) { |
| 891 ASSERT(optimization.is_simple_api_call()); | |
| 892 ASSERT(!receiver.is(scratch)); | 941 ASSERT(!receiver.is(scratch)); |
| 893 | 942 __ push(receiver); |
| 894 typedef FunctionCallbackArguments FCA; | |
| 895 const int stack_space = kFastApiCallArguments + argc + 1; | |
| 896 // Assign stack space for the call arguments. | |
| 897 __ Subu(sp, sp, Operand(stack_space * kPointerSize)); | |
| 898 // Write holder to stack frame. | |
| 899 __ sw(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | |
| 900 // Write receiver to stack frame. | |
| 901 int index = stack_space - 1; | |
| 902 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); | |
| 903 // Write the arguments to stack frame. | 943 // Write the arguments to stack frame. |
| 904 for (int i = 0; i < argc; i++) { | 944 for (int i = 0; i < argc; i++) { |
| 905 ASSERT(!receiver.is(values[i])); | 945 Register arg = values[argc-1-i]; |
| 906 ASSERT(!scratch.is(values[i])); | 946 ASSERT(!receiver.is(arg)); |
| 907 __ sw(values[i], MemOperand(sp, index-- * kPointerSize)); | 947 ASSERT(!scratch.is(arg)); |
| 948 __ push(arg); |
| 908 } | 949 } |
| 909 | 950 |
| 910 GenerateFastApiDirectCall(masm, optimization, argc, true); | 951 Register scratch1 = a0; |
| 952 Register scratch2 = a1; |
| 953 Register scratch3 = a2; |
| 954 if (!a3.is(receiver)) { |
| 955 __ mov(a3, receiver); |
| 956 receiver = a3; |
| 957 } |
| 958 // Stack now matches JSFunction abi. |
| 959 GenerateFastApiCallBody(masm, |
| 960 optimization, |
| 961 argc, |
| 962 receiver, |
| 963 scratch1, |
| 964 scratch2, |
| 965 scratch3, |
| 966 true); |
| 911 } | 967 } |
| 912 | 968 |
| 913 | 969 |
| 914 class CallInterceptorCompiler BASE_EMBEDDED { | 970 class CallInterceptorCompiler BASE_EMBEDDED { |
| 915 public: | 971 public: |
| 916 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 972 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 917 const ParameterCount& arguments, | 973 const ParameterCount& arguments, |
| 918 Register name) | 974 Register name) |
| 919 : stub_compiler_(stub_compiler), | 975 : stub_compiler_(stub_compiler), |
| 920 arguments_(arguments), | 976 arguments_(arguments), |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 Register scratch2, | 1009 Register scratch2, |
| 954 Register scratch3, | 1010 Register scratch3, |
| 955 Handle<JSObject> interceptor_holder, | 1011 Handle<JSObject> interceptor_holder, |
| 956 LookupResult* lookup, | 1012 LookupResult* lookup, |
| 957 Handle<Name> name, | 1013 Handle<Name> name, |
| 958 const CallOptimization& optimization, | 1014 const CallOptimization& optimization, |
| 959 Label* miss_label) { | 1015 Label* miss_label) { |
| 960 ASSERT(optimization.is_constant_call()); | 1016 ASSERT(optimization.is_constant_call()); |
| 961 ASSERT(!lookup->holder()->IsGlobalObject()); | 1017 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 962 Counters* counters = masm->isolate()->counters(); | 1018 Counters* counters = masm->isolate()->counters(); |
| 963 int depth1 = kInvalidProtoDepth; | |
| 964 int depth2 = kInvalidProtoDepth; | |
| 965 bool can_do_fast_api_call = false; | |
| 966 if (optimization.is_simple_api_call() && | |
| 967 !lookup->holder()->IsGlobalObject()) { | |
| 968 depth1 = optimization.GetPrototypeDepthOfExpectedType( | |
| 969 object, interceptor_holder); | |
| 970 if (depth1 == kInvalidProtoDepth) { | |
| 971 depth2 = optimization.GetPrototypeDepthOfExpectedType( | |
| 972 interceptor_holder, Handle<JSObject>(lookup->holder())); | |
| 973 } | |
| 974 can_do_fast_api_call = | |
| 975 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; | |
| 976 } | |
| 977 | |
| 978 __ IncrementCounter(counters->call_const_interceptor(), 1, | 1019 __ IncrementCounter(counters->call_const_interceptor(), 1, |
| 979 scratch1, scratch2); | 1020 scratch1, scratch2); |
| 980 | 1021 |
| 981 if (can_do_fast_api_call) { | |
| 982 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | |
| 983 scratch1, scratch2); | |
| 984 ReserveSpaceForFastApiCall(masm, scratch1); | |
| 985 } | |
| 986 | |
| 987 // Check that the maps from receiver to interceptor's holder | 1022 // Check that the maps from receiver to interceptor's holder |
| 988 // haven't changed and thus we can invoke interceptor. | 1023 // haven't changed and thus we can invoke interceptor. |
| 989 Label miss_cleanup; | 1024 Label miss_cleanup; |
| 990 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | |
| 991 Register holder = | 1025 Register holder = |
| 992 stub_compiler_->CheckPrototypes( | 1026 stub_compiler_->CheckPrototypes( |
| 993 IC::CurrentTypeOf(object, masm->isolate()), receiver, | 1027 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 994 interceptor_holder, scratch1, scratch2, scratch3, | 1028 interceptor_holder, scratch1, scratch2, scratch3, |
| 995 name, depth1, miss); | 1029 name, miss_label); |
| 996 | 1030 |
| 997 // Invoke an interceptor and if it provides a value, | 1031 // Invoke an interceptor and if it provides a value, |
| 998 // branch to |regular_invoke|. | 1032 // branch to |regular_invoke|. |
| 999 Label regular_invoke; | 1033 Label regular_invoke; |
| 1000 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 1034 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
| 1001 ®ular_invoke); | 1035 ®ular_invoke); |
| 1002 | 1036 |
| 1003 // Interceptor returned nothing for this property. Try to use cached | 1037 // Interceptor returned nothing for this property. Try to use cached |
| 1004 // constant function. | 1038 // constant function. |
| 1005 | 1039 |
| 1006 // Check that the maps from interceptor's holder to constant function's | 1040 // Check that the maps from interceptor's holder to constant function's |
| 1007 // holder haven't changed and thus we can use cached constant function. | 1041 // holder haven't changed and thus we can use cached constant function. |
| 1008 if (*interceptor_holder != lookup->holder()) { | 1042 if (*interceptor_holder != lookup->holder()) { |
| 1009 stub_compiler_->CheckPrototypes( | 1043 stub_compiler_->CheckPrototypes( |
| 1010 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, | 1044 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, |
| 1011 handle(lookup->holder()), scratch1, scratch2, scratch3, | 1045 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 1012 name, depth2, miss); | 1046 name, miss_label); |
| 1013 } else { | 1047 } |
| 1014 // CheckPrototypes has a side effect of fetching a 'holder' | 1048 |
| 1015 // for API (object which is instanceof for the signature). It's | 1049 Handle<Map> lookup_map; |
| 1016 // safe to omit it here, as if present, it should be fetched | 1050 CallOptimization::HolderLookup holder_lookup = |
| 1017 // by the previous CheckPrototypes. | 1051 CallOptimization::kHolderNotFound; |
| 1018 ASSERT(depth2 == kInvalidProtoDepth); | 1052 if (optimization.is_simple_api_call() && |
| 1053 !lookup->holder()->IsGlobalObject()) { |
| 1054 lookup_map = optimization.LookupHolderOfExpectedType( |
| 1055 object, object, interceptor_holder, &holder_lookup); |
| 1056 if (holder_lookup == CallOptimization::kHolderNotFound) { |
| 1057 lookup_map = |
| 1058 optimization.LookupHolderOfExpectedType( |
| 1059 object, |
| 1060 interceptor_holder, |
| 1061 Handle<JSObject>(lookup->holder()), |
| 1062 &holder_lookup); |
| 1063 } |
| 1019 } | 1064 } |
| 1020 | 1065 |
| 1021 // Invoke function. | 1066 // Invoke function. |
| 1022 if (can_do_fast_api_call) { | 1067 if (holder_lookup != CallOptimization::kHolderNotFound) { |
| 1023 GenerateFastApiDirectCall( | 1068 int argc = arguments_.immediate(); |
| 1024 masm, optimization, arguments_.immediate(), false); | 1069 GenerateFastApiCall(masm, |
| 1070 optimization, |
| 1071 argc, |
| 1072 lookup_map, |
| 1073 holder_lookup); |
| 1025 } else { | 1074 } else { |
| 1026 Handle<JSFunction> function = optimization.constant_function(); | 1075 Handle<JSFunction> function = optimization.constant_function(); |
| 1027 __ Move(a0, receiver); | 1076 __ Move(a0, receiver); |
| 1028 stub_compiler_->GenerateJumpFunction(object, function); | 1077 stub_compiler_->GenerateJumpFunction(object, function); |
| 1029 } | 1078 } |
| 1030 | 1079 |
| 1031 // Deferred code for fast API call case---clean preallocated space. | |
| 1032 if (can_do_fast_api_call) { | |
| 1033 __ bind(&miss_cleanup); | |
| 1034 FreeSpaceForFastApiCall(masm); | |
| 1035 __ Branch(miss_label); | |
| 1036 } | |
| 1037 | |
| 1038 // Invoke a regular function. | 1080 // Invoke a regular function. |
| 1039 __ bind(®ular_invoke); | 1081 __ bind(®ular_invoke); |
| 1040 if (can_do_fast_api_call) { | |
| 1041 FreeSpaceForFastApiCall(masm); | |
| 1042 } | |
| 1043 } | 1082 } |
| 1044 | 1083 |
| 1045 void CompileRegular(MacroAssembler* masm, | 1084 void CompileRegular(MacroAssembler* masm, |
| 1046 Handle<JSObject> object, | 1085 Handle<JSObject> object, |
| 1047 Register receiver, | 1086 Register receiver, |
| 1048 Register scratch1, | 1087 Register scratch1, |
| 1049 Register scratch2, | 1088 Register scratch2, |
| 1050 Register scratch3, | 1089 Register scratch3, |
| 1051 Handle<Name> name, | 1090 Handle<Name> name, |
| 1052 Handle<JSObject> interceptor_holder, | 1091 Handle<JSObject> interceptor_holder, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 #define __ ACCESS_MASM(masm()) | 1146 #define __ ACCESS_MASM(masm()) |
| 1108 | 1147 |
| 1109 | 1148 |
| 1110 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 1149 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, |
| 1111 Register object_reg, | 1150 Register object_reg, |
| 1112 Handle<JSObject> holder, | 1151 Handle<JSObject> holder, |
| 1113 Register holder_reg, | 1152 Register holder_reg, |
| 1114 Register scratch1, | 1153 Register scratch1, |
| 1115 Register scratch2, | 1154 Register scratch2, |
| 1116 Handle<Name> name, | 1155 Handle<Name> name, |
| 1117 int save_at_depth, | |
| 1118 Label* miss, | 1156 Label* miss, |
| 1119 PrototypeCheckType check) { | 1157 PrototypeCheckType check) { |
| 1120 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 1158 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1121 // Make sure that the type feedback oracle harvests the receiver map. | 1159 // Make sure that the type feedback oracle harvests the receiver map. |
| 1122 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1160 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1123 __ li(scratch1, Operand(receiver_map)); | 1161 __ li(scratch1, Operand(receiver_map)); |
| 1124 | 1162 |
| 1125 // Make sure there's no overlap between holder and object registers. | 1163 // Make sure there's no overlap between holder and object registers. |
| 1126 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1164 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1127 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1165 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1128 && !scratch2.is(scratch1)); | 1166 && !scratch2.is(scratch1)); |
| 1129 | 1167 |
| 1130 // Keep track of the current object in register reg. | 1168 // Keep track of the current object in register reg. |
| 1131 Register reg = object_reg; | 1169 Register reg = object_reg; |
| 1132 int depth = 0; | 1170 int depth = 0; |
| 1133 | 1171 |
| 1134 typedef FunctionCallbackArguments FCA; | |
| 1135 if (save_at_depth == depth) { | |
| 1136 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | |
| 1137 } | |
| 1138 | |
| 1139 Handle<JSObject> current = Handle<JSObject>::null(); | 1172 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1140 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); | 1173 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1141 Handle<JSObject> prototype = Handle<JSObject>::null(); | 1174 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1142 Handle<Map> current_map = receiver_map; | 1175 Handle<Map> current_map = receiver_map; |
| 1143 Handle<Map> holder_map(holder->map()); | 1176 Handle<Map> holder_map(holder->map()); |
| 1144 // Traverse the prototype chain and check the maps in the prototype chain for | 1177 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1145 // fast and global objects or do negative lookup for normal objects. | 1178 // fast and global objects or do negative lookup for normal objects. |
| 1146 while (!current_map.is_identical_to(holder_map)) { | 1179 while (!current_map.is_identical_to(holder_map)) { |
| 1147 ++depth; | 1180 ++depth; |
| 1148 | 1181 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 if (heap()->InNewSpace(*prototype)) { | 1227 if (heap()->InNewSpace(*prototype)) { |
| 1195 // The prototype is in new space; we cannot store a reference to it | 1228 // The prototype is in new space; we cannot store a reference to it |
| 1196 // in the code. Load it from the map. | 1229 // in the code. Load it from the map. |
| 1197 __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 1230 __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| 1198 } else { | 1231 } else { |
| 1199 // The prototype is in old space; load it directly. | 1232 // The prototype is in old space; load it directly. |
| 1200 __ li(reg, Operand(prototype)); | 1233 __ li(reg, Operand(prototype)); |
| 1201 } | 1234 } |
| 1202 } | 1235 } |
| 1203 | 1236 |
| 1204 if (save_at_depth == depth) { | |
| 1205 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | |
| 1206 } | |
| 1207 | |
| 1208 // Go to the next object in the prototype chain. | 1237 // Go to the next object in the prototype chain. |
| 1209 current = prototype; | 1238 current = prototype; |
| 1210 current_map = handle(current->map()); | 1239 current_map = handle(current->map()); |
| 1211 } | 1240 } |
| 1212 | 1241 |
| 1213 // Log the check depth. | 1242 // Log the check depth. |
| 1214 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1243 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1215 | 1244 |
| 1216 if (depth != 0 || check == CHECK_ALL_MAPS) { | 1245 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1217 // Check the holder map. | 1246 // Check the holder map. |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 Handle<String> name) { | 1594 Handle<String> name) { |
| 1566 | 1595 |
| 1567 Counters* counters = isolate()->counters(); | 1596 Counters* counters = isolate()->counters(); |
| 1568 | 1597 |
| 1569 ASSERT(optimization.is_simple_api_call()); | 1598 ASSERT(optimization.is_simple_api_call()); |
| 1570 // Bail out if object is a global object as we don't want to | 1599 // Bail out if object is a global object as we don't want to |
| 1571 // repatch it to global receiver. | 1600 // repatch it to global receiver. |
| 1572 if (object->IsGlobalObject()) return Handle<Code>::null(); | 1601 if (object->IsGlobalObject()) return Handle<Code>::null(); |
| 1573 if (!cell.is_null()) return Handle<Code>::null(); | 1602 if (!cell.is_null()) return Handle<Code>::null(); |
| 1574 if (!object->IsJSObject()) return Handle<Code>::null(); | 1603 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 1575 int depth = optimization.GetPrototypeDepthOfExpectedType( | 1604 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1576 Handle<JSObject>::cast(object), holder); | 1605 CallOptimization::HolderLookup holder_lookup = |
| 1577 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); | 1606 CallOptimization::kHolderNotFound; |
| 1607 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType( |
| 1608 receiver, receiver, holder, &holder_lookup); |
| 1609 if (holder_lookup == CallOptimization::kHolderNotFound) { |
| 1610 return Handle<Code>::null(); |
| 1611 } |
| 1578 | 1612 |
| 1579 Label miss, miss_before_stack_reserved; | 1613 Label miss; |
| 1580 | 1614 GenerateNameCheck(name, &miss); |
| 1581 GenerateNameCheck(name, &miss_before_stack_reserved); | |
| 1582 | 1615 |
| 1583 // Get the receiver from the stack. | 1616 // Get the receiver from the stack. |
| 1584 const int argc = arguments().immediate(); | 1617 const int argc = arguments().immediate(); |
| 1585 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 1618 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 1586 | 1619 |
| 1587 // Check that the receiver isn't a smi. | 1620 // Check that the receiver isn't a smi. |
| 1588 __ JumpIfSmi(a1, &miss_before_stack_reserved); | 1621 __ JumpIfSmi(a1, &miss); |
| 1589 | 1622 |
| 1590 __ IncrementCounter(counters->call_const(), 1, a0, a3); | 1623 __ IncrementCounter(counters->call_const(), 1, a0, a3); |
| 1591 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); | |
| 1592 | |
| 1593 ReserveSpaceForFastApiCall(masm(), a0); | |
| 1594 | 1624 |
| 1595 // Check that the maps haven't changed and find a Holder as a side effect. | 1625 // Check that the maps haven't changed and find a Holder as a side effect. |
| 1596 CheckPrototypes( | 1626 CheckPrototypes( |
| 1597 IC::CurrentTypeOf(object, isolate()), | 1627 IC::CurrentTypeOf(object, isolate()), |
| 1598 a1, holder, a0, a3, t0, name, depth, &miss); | 1628 a1, holder, a0, a3, t0, name, &miss); |
| 1599 | 1629 |
| 1600 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 1630 GenerateFastApiCall( |
| 1631 masm(), optimization, argc, lookup_map, holder_lookup); |
| 1601 | 1632 |
| 1602 __ bind(&miss); | 1633 HandlerFrontendFooter(&miss); |
| 1603 FreeSpaceForFastApiCall(masm()); | |
| 1604 | |
| 1605 HandlerFrontendFooter(&miss_before_stack_reserved); | |
| 1606 | 1634 |
| 1607 // Return the generated code. | 1635 // Return the generated code. |
| 1608 return GetCode(function); | 1636 return GetCode(function); |
| 1609 } | 1637 } |
| 1610 | 1638 |
| 1611 | 1639 |
| 1612 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 1640 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 1613 Label success; | 1641 Label success; |
| 1614 // Check that the object is a boolean. | 1642 // Check that the object is a boolean. |
| 1615 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 1643 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2155 // ----------------------------------- | 2183 // ----------------------------------- |
| 2156 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2184 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2157 } | 2185 } |
| 2158 | 2186 |
| 2159 | 2187 |
| 2160 #undef __ | 2188 #undef __ |
| 2161 | 2189 |
| 2162 } } // namespace v8::internal | 2190 } } // namespace v8::internal |
| 2163 | 2191 |
| 2164 #endif // V8_TARGET_ARCH_MIPS | 2192 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |