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

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

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