Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 144143002: Revert "Unify calling to GenerateFastApiCallBody before stubbing it" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 761 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 IC::UtilityId id) { 772 IC::UtilityId id) {
773 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 773 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
774 __ CallExternalReference( 774 __ CallExternalReference(
775 ExternalReference(IC_Utility(id), masm->isolate()), 775 ExternalReference(IC_Utility(id), masm->isolate()),
776 StubCache::kInterceptorArgsLength); 776 StubCache::kInterceptorArgsLength);
777 } 777 }
778 778
779 779
780 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 780 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
781 781
782 // Reserves space for the extra arguments to API function in the
783 // caller's frame.
784 //
785 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall.
786 static void ReserveSpaceForFastApiCall(MacroAssembler* masm,
787 Register scratch) {
788 __ mov(scratch, Operand(Smi::FromInt(0)));
789 for (int i = 0; i < kFastApiCallArguments; i++) {
790 __ push(scratch);
791 }
792 }
782 793
783 static void GenerateFastApiCallBody(MacroAssembler* masm, 794
784 const CallOptimization& optimization, 795 // Undoes the effects of ReserveSpaceForFastApiCall.
785 int argc, 796 static void FreeSpaceForFastApiCall(MacroAssembler* masm) {
786 Register holder, 797 __ Drop(kFastApiCallArguments);
787 Register scratch1, 798 }
788 Register scratch2, 799
789 Register scratch3, 800
790 bool restore_context) { 801 static void GenerateFastApiDirectCall(MacroAssembler* masm,
802 const CallOptimization& optimization,
803 int argc,
804 bool restore_context) {
791 // ----------- S t a t e ------------- 805 // ----------- S t a t e -------------
792 // -- sp[0] : last JS argument 806 // -- sp[0] - sp[24] : FunctionCallbackInfo, incl.
807 // : holder (set by CheckPrototypes)
808 // -- sp[28] : last JS argument
793 // -- ... 809 // -- ...
794 // -- sp[(argc - 1) * 4] : first JS argument 810 // -- sp[(argc + 6) * 4] : first JS argument
795 // -- sp[argc * 4] : receiver 811 // -- sp[(argc + 7) * 4] : receiver
796 // ----------------------------------- 812 // -----------------------------------
797 ASSERT(optimization.is_simple_api_call());
798
799 typedef FunctionCallbackArguments FCA; 813 typedef FunctionCallbackArguments FCA;
800
801 STATIC_ASSERT(FCA::kHolderIndex == 0);
802 STATIC_ASSERT(FCA::kIsolateIndex == 1);
803 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
804 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
805 STATIC_ASSERT(FCA::kDataIndex == 4);
806 STATIC_ASSERT(FCA::kCalleeIndex == 5);
807 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
808 STATIC_ASSERT(FCA::kArgsLength == 7);
809
810 ASSERT(!holder.is(cp));
811
812 // Save calling context. 814 // Save calling context.
813 __ push(cp); 815 __ str(cp, MemOperand(sp, FCA::kContextSaveIndex * kPointerSize));
814 // Get the function and setup the context. 816 // Get the function and setup the context.
815 Handle<JSFunction> function = optimization.constant_function(); 817 Handle<JSFunction> function = optimization.constant_function();
816 __ Move(scratch1, function); 818 __ Move(r5, function);
817 __ ldr(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset)); 819 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
818 __ push(scratch1); 820 __ str(r5, MemOperand(sp, FCA::kCalleeIndex * kPointerSize));
819 821
820 // Construct the FunctionCallbackInfo. 822 // Construct the FunctionCallbackInfo.
821 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 823 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
822 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 824 Handle<Object> call_data(api_call_info->data(), masm->isolate());
823 bool call_data_undefined = false;
824 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 825 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
825 __ Move(scratch1, api_call_info); 826 __ Move(r0, api_call_info);
826 __ ldr(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); 827 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
827 } else if (call_data->IsUndefined()) {
828 call_data_undefined = true;
829 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
830 } else { 828 } else {
831 __ Move(scratch1, call_data); 829 __ Move(r6, call_data);
832 } 830 }
833 // Store call data. 831 // Store call data.
834 __ push(scratch1); 832 __ str(r6, MemOperand(sp, FCA::kDataIndex * kPointerSize));
835 if (!call_data_undefined) { 833 // Store isolate.
836 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); 834 __ mov(r5, Operand(ExternalReference::isolate_address(masm->isolate())));
837 } 835 __ str(r5, MemOperand(sp, FCA::kIsolateIndex * kPointerSize));
838 // Store ReturnValue default and ReturnValue. 836 // Store ReturnValue default and ReturnValue.
839 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); 837 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
840 __ push(scratch1); 838 __ str(r5, MemOperand(sp, FCA::kReturnValueOffset * kPointerSize));
841 __ push(scratch1); 839 __ str(r5, MemOperand(sp, FCA::kReturnValueDefaultValueIndex * kPointerSize));
842 // Store isolate.
843 __ mov(scratch1,
844 Operand(ExternalReference::isolate_address(masm->isolate())));
845 __ push(scratch1);
846 // holder
847 __ push(holder);
848 840
849 // Prepare arguments. 841 // Prepare arguments.
850 __ mov(r2, sp); 842 __ mov(r2, sp);
851 843
852 // Allocate the v8::Arguments structure in the arguments' space since 844 // Allocate the v8::Arguments structure in the arguments' space since
853 // it's not controlled by GC. 845 // it's not controlled by GC.
854 const int kApiStackSpace = 4; 846 const int kApiStackSpace = 4;
855 847
856 FrameScope frame_scope(masm, StackFrame::MANUAL); 848 FrameScope frame_scope(masm, StackFrame::MANUAL);
857 __ EnterExitFrame(false, kApiStackSpace); 849 __ EnterExitFrame(false, kApiStackSpace);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 function_address, 886 function_address,
895 thunk_ref, 887 thunk_ref,
896 r1, 888 r1,
897 kStackUnwindSpace, 889 kStackUnwindSpace,
898 return_value_operand, 890 return_value_operand,
899 restore_context ? 891 restore_context ?
900 &context_restore_operand : NULL); 892 &context_restore_operand : NULL);
901 } 893 }
902 894
903 895
904 // Generates call to API function.
905 static void GenerateFastApiCall(MacroAssembler* masm,
906 const CallOptimization& optimization,
907 int argc,
908 Handle<Map> map_to_holder,
909 CallOptimization::HolderLookup holder_lookup) {
910 Counters* counters = masm->isolate()->counters();
911 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r1);
912
913 // Move holder to a register
914 Register holder_reg = r0;
915 switch (holder_lookup) {
916 case CallOptimization::kHolderIsReceiver:
917 {
918 ASSERT(map_to_holder.is_null());
919 __ ldr(holder_reg, MemOperand(sp, argc * kPointerSize));
920 }
921 break;
922 case CallOptimization::kHolderIsPrototypeOfMap:
923 {
924 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
925 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
926 __ Move(holder_reg, holder);
927 } else {
928 __ Move(holder_reg, map_to_holder);
929 __ ldr(holder_reg,
930 FieldMemOperand(holder_reg, Map::kPrototypeOffset));
931 }
932 }
933 break;
934 case CallOptimization::kHolderNotFound:
935 UNREACHABLE();
936 }
937 GenerateFastApiCallBody(masm,
938 optimization,
939 argc,
940 holder_reg,
941 r1,
942 r2,
943 r3,
944 false);
945 }
946
947
948 // Generate call to api function. 896 // Generate call to api function.
949 static void GenerateFastApiCall(MacroAssembler* masm, 897 static void GenerateFastApiCall(MacroAssembler* masm,
950 const CallOptimization& optimization, 898 const CallOptimization& optimization,
951 Register receiver, 899 Register receiver,
952 Register scratch, 900 Register scratch,
953 int argc, 901 int argc,
954 Register* values) { 902 Register* values) {
903 ASSERT(optimization.is_simple_api_call());
955 ASSERT(!receiver.is(scratch)); 904 ASSERT(!receiver.is(scratch));
956 __ push(receiver); 905
906 typedef FunctionCallbackArguments FCA;
907 const int stack_space = kFastApiCallArguments + argc + 1;
908 // Assign stack space for the call arguments.
909 __ sub(sp, sp, Operand(stack_space * kPointerSize));
910 // Write holder to stack frame.
911 __ str(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
912 // Write receiver to stack frame.
913 int index = stack_space - 1;
914 __ str(receiver, MemOperand(sp, index-- * kPointerSize));
957 // Write the arguments to stack frame. 915 // Write the arguments to stack frame.
958 for (int i = 0; i < argc; i++) { 916 for (int i = 0; i < argc; i++) {
959 Register arg = values[argc-1-i]; 917 ASSERT(!receiver.is(values[i]));
960 ASSERT(!receiver.is(arg)); 918 ASSERT(!scratch.is(values[i]));
961 ASSERT(!scratch.is(arg)); 919 __ str(values[i], MemOperand(sp, index-- * kPointerSize));
962 __ push(arg);
963 } 920 }
964 Register scratch1 = r0; 921
965 Register scratch2 = r1; 922 GenerateFastApiDirectCall(masm, optimization, argc, true);
966 Register scratch3 = r2;
967 if (!r3.is(receiver)) {
968 __ mov(r3, receiver);
969 receiver = r3;
970 }
971 // Stack now matches JSFunction abi.
972 GenerateFastApiCallBody(masm,
973 optimization,
974 argc,
975 receiver,
976 scratch1,
977 scratch2,
978 scratch3,
979 true);
980 } 923 }
981 924
982 925
983 class CallInterceptorCompiler BASE_EMBEDDED { 926 class CallInterceptorCompiler BASE_EMBEDDED {
984 public: 927 public:
985 CallInterceptorCompiler(CallStubCompiler* stub_compiler, 928 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
986 const ParameterCount& arguments, 929 const ParameterCount& arguments,
987 Register name) 930 Register name)
988 : stub_compiler_(stub_compiler), 931 : stub_compiler_(stub_compiler),
989 arguments_(arguments), 932 arguments_(arguments),
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 Register scratch2, 965 Register scratch2,
1023 Register scratch3, 966 Register scratch3,
1024 Handle<JSObject> interceptor_holder, 967 Handle<JSObject> interceptor_holder,
1025 LookupResult* lookup, 968 LookupResult* lookup,
1026 Handle<Name> name, 969 Handle<Name> name,
1027 const CallOptimization& optimization, 970 const CallOptimization& optimization,
1028 Label* miss_label) { 971 Label* miss_label) {
1029 ASSERT(optimization.is_constant_call()); 972 ASSERT(optimization.is_constant_call());
1030 ASSERT(!lookup->holder()->IsGlobalObject()); 973 ASSERT(!lookup->holder()->IsGlobalObject());
1031 Counters* counters = masm->isolate()->counters(); 974 Counters* counters = masm->isolate()->counters();
975 int depth1 = kInvalidProtoDepth;
976 int depth2 = kInvalidProtoDepth;
977 bool can_do_fast_api_call = false;
978 if (optimization.is_simple_api_call() &&
979 !lookup->holder()->IsGlobalObject()) {
980 depth1 = optimization.GetPrototypeDepthOfExpectedType(
981 object, interceptor_holder);
982 if (depth1 == kInvalidProtoDepth) {
983 depth2 = optimization.GetPrototypeDepthOfExpectedType(
984 interceptor_holder, Handle<JSObject>(lookup->holder()));
985 }
986 can_do_fast_api_call =
987 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
988 }
989
1032 __ IncrementCounter(counters->call_const_interceptor(), 1, 990 __ IncrementCounter(counters->call_const_interceptor(), 1,
1033 scratch1, scratch2); 991 scratch1, scratch2);
1034 992
993 if (can_do_fast_api_call) {
994 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
995 scratch1, scratch2);
996 ReserveSpaceForFastApiCall(masm, scratch1);
997 }
998
1035 // Check that the maps from receiver to interceptor's holder 999 // Check that the maps from receiver to interceptor's holder
1036 // haven't changed and thus we can invoke interceptor. 1000 // haven't changed and thus we can invoke interceptor.
1037 Label miss_cleanup; 1001 Label miss_cleanup;
1002 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
1038 Register holder = 1003 Register holder =
1039 stub_compiler_->CheckPrototypes( 1004 stub_compiler_->CheckPrototypes(
1040 IC::CurrentTypeOf(object, masm->isolate()), receiver, 1005 IC::CurrentTypeOf(object, masm->isolate()), receiver,
1041 interceptor_holder, scratch1, scratch2, scratch3, 1006 interceptor_holder, scratch1, scratch2, scratch3,
1042 name, miss_label); 1007 name, depth1, miss);
1043 1008
1044 // Invoke an interceptor and if it provides a value, 1009 // Invoke an interceptor and if it provides a value,
1045 // branch to |regular_invoke|. 1010 // branch to |regular_invoke|.
1046 Label regular_invoke; 1011 Label regular_invoke;
1047 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, 1012 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
1048 &regular_invoke); 1013 &regular_invoke);
1049 1014
1050 // Interceptor returned nothing for this property. Try to use cached 1015 // Interceptor returned nothing for this property. Try to use cached
1051 // constant function. 1016 // constant function.
1052 1017
1053 // Check that the maps from interceptor's holder to constant function's 1018 // Check that the maps from interceptor's holder to constant function's
1054 // holder haven't changed and thus we can use cached constant function. 1019 // holder haven't changed and thus we can use cached constant function.
1055 if (*interceptor_holder != lookup->holder()) { 1020 if (*interceptor_holder != lookup->holder()) {
1056 stub_compiler_->CheckPrototypes( 1021 stub_compiler_->CheckPrototypes(
1057 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 1022 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
1058 handle(lookup->holder()), scratch1, scratch2, scratch3, 1023 handle(lookup->holder()), scratch1, scratch2, scratch3,
1059 name, miss_label); 1024 name, depth2, miss);
1060 } 1025 } else {
1061 1026 // CheckPrototypes has a side effect of fetching a 'holder'
1062 Handle<Map> lookup_map; 1027 // for API (object which is instanceof for the signature). It's
1063 CallOptimization::HolderLookup holder_lookup = 1028 // safe to omit it here, as if present, it should be fetched
1064 CallOptimization::kHolderNotFound; 1029 // by the previous CheckPrototypes.
1065 if (optimization.is_simple_api_call() && 1030 ASSERT(depth2 == kInvalidProtoDepth);
1066 !lookup->holder()->IsGlobalObject()) {
1067 lookup_map = optimization.LookupHolderOfExpectedType(
1068 object, object, interceptor_holder, &holder_lookup);
1069 if (holder_lookup == CallOptimization::kHolderNotFound) {
1070 lookup_map =
1071 optimization.LookupHolderOfExpectedType(
1072 object,
1073 interceptor_holder,
1074 Handle<JSObject>(lookup->holder()),
1075 &holder_lookup);
1076 }
1077 } 1031 }
1078 1032
1079 // Invoke function. 1033 // Invoke function.
1080 if (holder_lookup != CallOptimization::kHolderNotFound) { 1034 if (can_do_fast_api_call) {
1081 int argc = arguments_.immediate(); 1035 GenerateFastApiDirectCall(
1082 GenerateFastApiCall(masm, 1036 masm, optimization, arguments_.immediate(), false);
1083 optimization,
1084 argc,
1085 lookup_map,
1086 holder_lookup);
1087 } else { 1037 } else {
1088 Handle<JSFunction> function = optimization.constant_function(); 1038 Handle<JSFunction> function = optimization.constant_function();
1089 __ Move(r0, receiver); 1039 __ Move(r0, receiver);
1090 stub_compiler_->GenerateJumpFunction(object, function); 1040 stub_compiler_->GenerateJumpFunction(object, function);
1091 } 1041 }
1092 1042
1043 // Deferred code for fast API call case---clean preallocated space.
1044 if (can_do_fast_api_call) {
1045 __ bind(&miss_cleanup);
1046 FreeSpaceForFastApiCall(masm);
1047 __ b(miss_label);
1048 }
1049
1093 // Invoke a regular function. 1050 // Invoke a regular function.
1094 __ bind(&regular_invoke); 1051 __ bind(&regular_invoke);
1052 if (can_do_fast_api_call) {
1053 FreeSpaceForFastApiCall(masm);
1054 }
1095 } 1055 }
1096 1056
1097 void CompileRegular(MacroAssembler* masm, 1057 void CompileRegular(MacroAssembler* masm,
1098 Handle<JSObject> object, 1058 Handle<JSObject> object,
1099 Register receiver, 1059 Register receiver,
1100 Register scratch1, 1060 Register scratch1,
1101 Register scratch2, 1061 Register scratch2,
1102 Register scratch3, 1062 Register scratch3,
1103 Handle<Name> name, 1063 Handle<Name> name,
1104 Handle<JSObject> interceptor_holder, 1064 Handle<JSObject> interceptor_holder,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 #define __ ACCESS_MASM(masm()) 1120 #define __ ACCESS_MASM(masm())
1161 1121
1162 1122
1163 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 1123 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1164 Register object_reg, 1124 Register object_reg,
1165 Handle<JSObject> holder, 1125 Handle<JSObject> holder,
1166 Register holder_reg, 1126 Register holder_reg,
1167 Register scratch1, 1127 Register scratch1,
1168 Register scratch2, 1128 Register scratch2,
1169 Handle<Name> name, 1129 Handle<Name> name,
1130 int save_at_depth,
1170 Label* miss, 1131 Label* miss,
1171 PrototypeCheckType check) { 1132 PrototypeCheckType check) {
1172 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 1133 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1173 // Make sure that the type feedback oracle harvests the receiver map. 1134 // Make sure that the type feedback oracle harvests the receiver map.
1174 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1135 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1175 __ mov(scratch1, Operand(receiver_map)); 1136 __ mov(scratch1, Operand(receiver_map));
1176 1137
1177 // Make sure there's no overlap between holder and object registers. 1138 // Make sure there's no overlap between holder and object registers.
1178 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1139 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1179 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1140 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1180 && !scratch2.is(scratch1)); 1141 && !scratch2.is(scratch1));
1181 1142
1182 // Keep track of the current object in register reg. 1143 // Keep track of the current object in register reg.
1183 Register reg = object_reg; 1144 Register reg = object_reg;
1184 int depth = 0; 1145 int depth = 0;
1185 1146
1147 typedef FunctionCallbackArguments FCA;
1148 if (save_at_depth == depth) {
1149 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
1150 }
1151
1186 Handle<JSObject> current = Handle<JSObject>::null(); 1152 Handle<JSObject> current = Handle<JSObject>::null();
1187 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 1153 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1188 Handle<JSObject> prototype = Handle<JSObject>::null(); 1154 Handle<JSObject> prototype = Handle<JSObject>::null();
1189 Handle<Map> current_map = receiver_map; 1155 Handle<Map> current_map = receiver_map;
1190 Handle<Map> holder_map(holder->map()); 1156 Handle<Map> holder_map(holder->map());
1191 // Traverse the prototype chain and check the maps in the prototype chain for 1157 // Traverse the prototype chain and check the maps in the prototype chain for
1192 // fast and global objects or do negative lookup for normal objects. 1158 // fast and global objects or do negative lookup for normal objects.
1193 while (!current_map.is_identical_to(holder_map)) { 1159 while (!current_map.is_identical_to(holder_map)) {
1194 ++depth; 1160 ++depth;
1195 1161
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 if (heap()->InNewSpace(*prototype)) { 1207 if (heap()->InNewSpace(*prototype)) {
1242 // The prototype is in new space; we cannot store a reference to it 1208 // The prototype is in new space; we cannot store a reference to it
1243 // in the code. Load it from the map. 1209 // in the code. Load it from the map.
1244 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); 1210 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
1245 } else { 1211 } else {
1246 // The prototype is in old space; load it directly. 1212 // The prototype is in old space; load it directly.
1247 __ mov(reg, Operand(prototype)); 1213 __ mov(reg, Operand(prototype));
1248 } 1214 }
1249 } 1215 }
1250 1216
1217 if (save_at_depth == depth) {
1218 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
1219 }
1220
1251 // Go to the next object in the prototype chain. 1221 // Go to the next object in the prototype chain.
1252 current = prototype; 1222 current = prototype;
1253 current_map = handle(current->map()); 1223 current_map = handle(current->map());
1254 } 1224 }
1255 1225
1256 // Log the check depth. 1226 // Log the check depth.
1257 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1227 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1258 1228
1259 if (depth != 0 || check == CHECK_ALL_MAPS) { 1229 if (depth != 0 || check == CHECK_ALL_MAPS) {
1260 // Check the holder map. 1230 // Check the holder map.
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 Handle<JSFunction> function, 1579 Handle<JSFunction> function,
1610 Handle<String> name) { 1580 Handle<String> name) {
1611 Counters* counters = isolate()->counters(); 1581 Counters* counters = isolate()->counters();
1612 1582
1613 ASSERT(optimization.is_simple_api_call()); 1583 ASSERT(optimization.is_simple_api_call());
1614 // Bail out if object is a global object as we don't want to 1584 // Bail out if object is a global object as we don't want to
1615 // repatch it to global receiver. 1585 // repatch it to global receiver.
1616 if (object->IsGlobalObject()) return Handle<Code>::null(); 1586 if (object->IsGlobalObject()) return Handle<Code>::null();
1617 if (!cell.is_null()) return Handle<Code>::null(); 1587 if (!cell.is_null()) return Handle<Code>::null();
1618 if (!object->IsJSObject()) return Handle<Code>::null(); 1588 if (!object->IsJSObject()) return Handle<Code>::null();
1619 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1589 int depth = optimization.GetPrototypeDepthOfExpectedType(
1620 CallOptimization::HolderLookup holder_lookup = 1590 Handle<JSObject>::cast(object), holder);
1621 CallOptimization::kHolderNotFound; 1591 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
1622 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1623 receiver, receiver, holder, &holder_lookup);
1624 if (holder_lookup == CallOptimization::kHolderNotFound) {
1625 return Handle<Code>::null();
1626 }
1627 1592
1628 Label miss; 1593 Label miss, miss_before_stack_reserved;
1629 GenerateNameCheck(name, &miss); 1594 GenerateNameCheck(name, &miss_before_stack_reserved);
1630 1595
1631 // Get the receiver from the stack. 1596 // Get the receiver from the stack.
1632 const int argc = arguments().immediate(); 1597 const int argc = arguments().immediate();
1633 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 1598 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1634 1599
1635 // Check that the receiver isn't a smi. 1600 // Check that the receiver isn't a smi.
1636 __ JumpIfSmi(r1, &miss); 1601 __ JumpIfSmi(r1, &miss_before_stack_reserved);
1637 1602
1638 __ IncrementCounter(counters->call_const(), 1, r0, r3); 1603 __ IncrementCounter(counters->call_const(), 1, r0, r3);
1604 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
1605
1606 ReserveSpaceForFastApiCall(masm(), r0);
1639 1607
1640 // Check that the maps haven't changed and find a Holder as a side effect. 1608 // Check that the maps haven't changed and find a Holder as a side effect.
1641 CheckPrototypes( 1609 CheckPrototypes(
1642 IC::CurrentTypeOf(object, isolate()), 1610 IC::CurrentTypeOf(object, isolate()),
1643 r1, holder, r0, r3, r4, name, &miss); 1611 r1, holder, r0, r3, r4, name, depth, &miss);
1644 1612
1645 GenerateFastApiCall( 1613 GenerateFastApiDirectCall(masm(), optimization, argc, false);
1646 masm(), optimization, argc, lookup_map, holder_lookup);
1647 1614
1648 HandlerFrontendFooter(&miss); 1615 __ bind(&miss);
1616 FreeSpaceForFastApiCall(masm());
1617
1618 HandlerFrontendFooter(&miss_before_stack_reserved);
1649 1619
1650 // Return the generated code. 1620 // Return the generated code.
1651 return GetCode(function); 1621 return GetCode(function);
1652 } 1622 }
1653 1623
1654 1624
1655 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1625 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1656 Label success; 1626 Label success;
1657 // Check that the object is a boolean. 1627 // Check that the object is a boolean.
1658 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1628 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
2201 // ----------------------------------- 2171 // -----------------------------------
2202 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2172 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2203 } 2173 }
2204 2174
2205 2175
2206 #undef __ 2176 #undef __
2207 2177
2208 } } // namespace v8::internal 2178 } } // namespace v8::internal
2209 2179
2210 #endif // V8_TARGET_ARCH_ARM 2180 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698