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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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 | « src/arm/macro-assembler-arm.cc ('k') | src/ast.h » ('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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 1153
1114 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 1154 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1115 __ Jump(code, RelocInfo::CODE_TARGET); 1155 __ Jump(code, RelocInfo::CODE_TARGET);
1116 } 1156 }
1117 1157
1118 1158
1119 #undef __ 1159 #undef __
1120 #define __ ACCESS_MASM(masm()) 1160 #define __ ACCESS_MASM(masm())
1121 1161
1122 1162
1123 Register StubCompiler::CheckPrototypes(Handle<Type> 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 28 matching lines...) Expand all
1259 Label success; 1289 Label success;
1260 __ b(&success); 1290 __ b(&success);
1261 GenerateRestoreName(masm(), miss, name); 1291 GenerateRestoreName(masm(), miss, name);
1262 TailCallBuiltin(masm(), MissBuiltin(kind())); 1292 TailCallBuiltin(masm(), MissBuiltin(kind()));
1263 __ bind(&success); 1293 __ bind(&success);
1264 } 1294 }
1265 } 1295 }
1266 1296
1267 1297
1268 Register LoadStubCompiler::CallbackHandlerFrontend( 1298 Register LoadStubCompiler::CallbackHandlerFrontend(
1269 Handle<Type> type, 1299 Handle<HeapType> type,
1270 Register object_reg, 1300 Register object_reg,
1271 Handle<JSObject> holder, 1301 Handle<JSObject> holder,
1272 Handle<Name> name, 1302 Handle<Name> name,
1273 Handle<Object> callback) { 1303 Handle<Object> callback) {
1274 Label miss; 1304 Label miss;
1275 1305
1276 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); 1306 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1277 1307
1278 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1308 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1279 ASSERT(!reg.is(scratch2())); 1309 ASSERT(!reg.is(scratch2()));
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1564 index.translate(holder), Representation::Tagged()); 1594 index.translate(holder), Representation::Tagged());
1565 GenerateJumpFunction(object, r1, &miss); 1595 GenerateJumpFunction(object, r1, &miss);
1566 1596
1567 HandlerFrontendFooter(&miss); 1597 HandlerFrontendFooter(&miss);
1568 1598
1569 // Return the generated code. 1599 // Return the generated code.
1570 return GetCode(Code::FAST, name); 1600 return GetCode(Code::FAST, name);
1571 } 1601 }
1572 1602
1573 1603
1574 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1575 Handle<Object> object,
1576 Handle<JSObject> holder,
1577 Handle<Cell> cell,
1578 Handle<JSFunction> function,
1579 Handle<String> name,
1580 Code::StubType type) {
1581 Label miss;
1582
1583 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1584 if (!cell.is_null()) {
1585 ASSERT(cell->value() == *function);
1586 GenerateLoadFunctionFromCell(cell, function, &miss);
1587 }
1588
1589 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1590 site->SetElementsKind(GetInitialFastElementsKind());
1591 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1592 const int argc = arguments().immediate();
1593 __ mov(r0, Operand(argc));
1594 __ mov(r2, Operand(site_feedback_cell));
1595 __ mov(r1, Operand(function));
1596
1597 ArrayConstructorStub stub(isolate());
1598 __ TailCallStub(&stub);
1599
1600 HandlerFrontendFooter(&miss);
1601
1602 // Return the generated code.
1603 return GetCode(type, name);
1604 }
1605
1606
1607 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1608 Handle<Object> object,
1609 Handle<JSObject> holder,
1610 Handle<Cell> cell,
1611 Handle<JSFunction> function,
1612 Handle<String> name,
1613 Code::StubType type) {
1614 // If object is not an array or is observed or sealed, bail out to regular
1615 // call.
1616 if (!object->IsJSArray() ||
1617 !cell.is_null() ||
1618 Handle<JSArray>::cast(object)->map()->is_observed() ||
1619 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1620 return Handle<Code>::null();
1621 }
1622
1623 Label miss;
1624
1625 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1626 Register receiver = r0;
1627 Register scratch = r1;
1628
1629 const int argc = arguments().immediate();
1630 if (argc == 0) {
1631 // Nothing to do, just return the length.
1632 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1633 __ Drop(argc + 1);
1634 __ Ret();
1635 } else {
1636 Label call_builtin;
1637
1638 if (argc == 1) { // Otherwise fall through to call the builtin.
1639 Label attempt_to_grow_elements, with_write_barrier, check_double;
1640
1641 Register elements = r6;
1642 Register end_elements = r5;
1643 // Get the elements array of the object.
1644 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1645
1646 // Check that the elements are in fast mode and writable.
1647 __ CheckMap(elements,
1648 scratch,
1649 Heap::kFixedArrayMapRootIndex,
1650 &check_double,
1651 DONT_DO_SMI_CHECK);
1652
1653 // Get the array's length into scratch and calculate new length.
1654 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1655 __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
1656
1657 // Get the elements' length.
1658 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1659
1660 // Check if we could survive without allocation.
1661 __ cmp(scratch, r4);
1662 __ b(gt, &attempt_to_grow_elements);
1663
1664 // Check if value is a smi.
1665 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
1666 __ JumpIfNotSmi(r4, &with_write_barrier);
1667
1668 // Save new length.
1669 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1670
1671 // Store the value.
1672 // We may need a register containing the address end_elements below,
1673 // so write back the value in end_elements.
1674 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1675 const int kEndElementsOffset =
1676 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
1677 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
1678
1679 // Check for a smi.
1680 __ Drop(argc + 1);
1681 __ mov(r0, scratch);
1682 __ Ret();
1683
1684 __ bind(&check_double);
1685
1686 // Check that the elements are in fast mode and writable.
1687 __ CheckMap(elements,
1688 scratch,
1689 Heap::kFixedDoubleArrayMapRootIndex,
1690 &call_builtin,
1691 DONT_DO_SMI_CHECK);
1692
1693 // Get the array's length into scratch and calculate new length.
1694 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1695 __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
1696
1697 // Get the elements' length.
1698 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1699
1700 // Check if we could survive without allocation.
1701 __ cmp(scratch, r4);
1702 __ b(gt, &call_builtin);
1703
1704 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
1705 __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
1706 &call_builtin, argc * kDoubleSize);
1707
1708 // Save new length.
1709 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1710
1711 __ Drop(argc + 1);
1712 __ mov(r0, scratch);
1713 __ Ret();
1714
1715 __ bind(&with_write_barrier);
1716
1717 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
1718
1719 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1720 Label fast_object, not_fast_object;
1721 __ CheckFastObjectElements(r3, r9, &not_fast_object);
1722 __ jmp(&fast_object);
1723 // In case of fast smi-only, convert to fast object, otherwise bail out.
1724 __ bind(&not_fast_object);
1725 __ CheckFastSmiElements(r3, r9, &call_builtin);
1726
1727 __ ldr(r9, FieldMemOperand(r4, HeapObject::kMapOffset));
1728 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1729 __ cmp(r9, ip);
1730 __ b(eq, &call_builtin);
1731 // edx: receiver
1732 // r3: map
1733 Label try_holey_map;
1734 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1735 FAST_ELEMENTS,
1736 r3,
1737 r9,
1738 &try_holey_map);
1739 __ mov(r2, receiver);
1740 ElementsTransitionGenerator::
1741 GenerateMapChangeElementsTransition(masm(),
1742 DONT_TRACK_ALLOCATION_SITE,
1743 NULL);
1744 __ jmp(&fast_object);
1745
1746 __ bind(&try_holey_map);
1747 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1748 FAST_HOLEY_ELEMENTS,
1749 r3,
1750 r9,
1751 &call_builtin);
1752 __ mov(r2, receiver);
1753 ElementsTransitionGenerator::
1754 GenerateMapChangeElementsTransition(masm(),
1755 DONT_TRACK_ALLOCATION_SITE,
1756 NULL);
1757 __ bind(&fast_object);
1758 } else {
1759 __ CheckFastObjectElements(r3, r3, &call_builtin);
1760 }
1761
1762 // Save new length.
1763 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1764
1765 // Store the value.
1766 // We may need a register containing the address end_elements below,
1767 // so write back the value in end_elements.
1768 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1769 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
1770
1771 __ RecordWrite(elements,
1772 end_elements,
1773 r4,
1774 kLRHasNotBeenSaved,
1775 kDontSaveFPRegs,
1776 EMIT_REMEMBERED_SET,
1777 OMIT_SMI_CHECK);
1778 __ Drop(argc + 1);
1779 __ mov(r0, scratch);
1780 __ Ret();
1781
1782 __ bind(&attempt_to_grow_elements);
1783 // scratch: array's length + 1.
1784
1785 if (!FLAG_inline_new) {
1786 __ b(&call_builtin);
1787 }
1788
1789 __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
1790 // Growing elements that are SMI-only requires special handling in case
1791 // the new element is non-Smi. For now, delegate to the builtin.
1792 Label no_fast_elements_check;
1793 __ JumpIfSmi(r2, &no_fast_elements_check);
1794 __ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset));
1795 __ CheckFastObjectElements(r9, r9, &call_builtin);
1796 __ bind(&no_fast_elements_check);
1797
1798 ExternalReference new_space_allocation_top =
1799 ExternalReference::new_space_allocation_top_address(isolate());
1800 ExternalReference new_space_allocation_limit =
1801 ExternalReference::new_space_allocation_limit_address(isolate());
1802
1803 const int kAllocationDelta = 4;
1804 // Load top and check if it is the end of elements.
1805 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1806 __ add(end_elements, end_elements, Operand(kEndElementsOffset));
1807 __ mov(r4, Operand(new_space_allocation_top));
1808 __ ldr(r3, MemOperand(r4));
1809 __ cmp(end_elements, r3);
1810 __ b(ne, &call_builtin);
1811
1812 __ mov(r9, Operand(new_space_allocation_limit));
1813 __ ldr(r9, MemOperand(r9));
1814 __ add(r3, r3, Operand(kAllocationDelta * kPointerSize));
1815 __ cmp(r3, r9);
1816 __ b(hi, &call_builtin);
1817
1818 // We fit and could grow elements.
1819 // Update new_space_allocation_top.
1820 __ str(r3, MemOperand(r4));
1821 // Push the argument.
1822 __ str(r2, MemOperand(end_elements));
1823 // Fill the rest with holes.
1824 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
1825 for (int i = 1; i < kAllocationDelta; i++) {
1826 __ str(r3, MemOperand(end_elements, i * kPointerSize));
1827 }
1828
1829 // Update elements' and array's sizes.
1830 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1831 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1832 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
1833 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1834
1835 // Elements are in new space, so write barrier is not required.
1836 __ Drop(argc + 1);
1837 __ mov(r0, scratch);
1838 __ Ret();
1839 }
1840 __ bind(&call_builtin);
1841 __ TailCallExternalReference(
1842 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
1843 }
1844
1845 HandlerFrontendFooter(&miss);
1846
1847 // Return the generated code.
1848 return GetCode(type, name);
1849 }
1850
1851
1852 Handle<Code> CallStubCompiler::CompileArrayPopCall(
1853 Handle<Object> object,
1854 Handle<JSObject> holder,
1855 Handle<Cell> cell,
1856 Handle<JSFunction> function,
1857 Handle<String> name,
1858 Code::StubType type) {
1859 // If object is not an array or is observed or sealed, bail out to regular
1860 // call.
1861 if (!object->IsJSArray() ||
1862 !cell.is_null() ||
1863 Handle<JSArray>::cast(object)->map()->is_observed() ||
1864 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1865 return Handle<Code>::null();
1866 }
1867
1868 Label miss, return_undefined, call_builtin;
1869 Register receiver = r0;
1870 Register scratch = r1;
1871 Register elements = r3;
1872
1873 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1874
1875 // Get the elements array of the object.
1876 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1877
1878 // Check that the elements are in fast mode and writable.
1879 __ CheckMap(elements,
1880 scratch,
1881 Heap::kFixedArrayMapRootIndex,
1882 &call_builtin,
1883 DONT_DO_SMI_CHECK);
1884
1885 // Get the array's length into r4 and calculate new length.
1886 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
1887 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
1888 __ b(lt, &return_undefined);
1889
1890 // Get the last element.
1891 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
1892 // We can't address the last element in one operation. Compute the more
1893 // expensive shift first, and use an offset later on.
1894 __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4));
1895 __ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
1896 __ cmp(scratch, r6);
1897 __ b(eq, &call_builtin);
1898
1899 // Set the array's length.
1900 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
1901
1902 // Fill with the hole.
1903 __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize));
1904 const int argc = arguments().immediate();
1905 __ Drop(argc + 1);
1906 __ mov(r0, scratch);
1907 __ Ret();
1908
1909 __ bind(&return_undefined);
1910 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1911 __ Drop(argc + 1);
1912 __ Ret();
1913
1914 __ bind(&call_builtin);
1915 __ TailCallExternalReference(
1916 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
1917
1918 HandlerFrontendFooter(&miss);
1919
1920 // Return the generated code.
1921 return GetCode(type, name);
1922 }
1923
1924
1925 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
1926 Handle<Object> object,
1927 Handle<JSObject> holder,
1928 Handle<Cell> cell,
1929 Handle<JSFunction> function,
1930 Handle<String> name,
1931 Code::StubType type) {
1932 // If object is not a string, bail out to regular call.
1933 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1934
1935 Label miss;
1936 Label name_miss;
1937 Label index_out_of_range;
1938 Label* index_out_of_range_label = &index_out_of_range;
1939
1940 if (kind_ == Code::CALL_IC &&
1941 (CallICBase::StringStubState::decode(extra_state()) ==
1942 DEFAULT_STRING_STUB)) {
1943 index_out_of_range_label = &miss;
1944 }
1945
1946 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
1947
1948 Register receiver = r0;
1949 Register index = r4;
1950 Register result = r1;
1951 const int argc = arguments().immediate();
1952 __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1953 if (argc > 0) {
1954 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
1955 } else {
1956 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1957 }
1958
1959 StringCharCodeAtGenerator generator(receiver,
1960 index,
1961 result,
1962 &miss, // When not a string.
1963 &miss, // When not a number.
1964 index_out_of_range_label,
1965 STRING_INDEX_IS_NUMBER);
1966 generator.GenerateFast(masm());
1967 __ Drop(argc + 1);
1968 __ mov(r0, result);
1969 __ Ret();
1970
1971 StubRuntimeCallHelper call_helper;
1972 generator.GenerateSlow(masm(), call_helper);
1973
1974 if (index_out_of_range.is_linked()) {
1975 __ bind(&index_out_of_range);
1976 __ LoadRoot(r0, Heap::kNanValueRootIndex);
1977 __ Drop(argc + 1);
1978 __ Ret();
1979 }
1980
1981 __ bind(&miss);
1982 // Restore function name in r2.
1983 __ Move(r2, name);
1984 HandlerFrontendFooter(&name_miss);
1985
1986 // Return the generated code.
1987 return GetCode(type, name);
1988 }
1989
1990
1991 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
1992 Handle<Object> object,
1993 Handle<JSObject> holder,
1994 Handle<Cell> cell,
1995 Handle<JSFunction> function,
1996 Handle<String> name,
1997 Code::StubType type) {
1998 // If object is not a string, bail out to regular call.
1999 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
2000
2001 const int argc = arguments().immediate();
2002 Label miss;
2003 Label name_miss;
2004 Label index_out_of_range;
2005 Label* index_out_of_range_label = &index_out_of_range;
2006 if (kind_ == Code::CALL_IC &&
2007 (CallICBase::StringStubState::decode(extra_state()) ==
2008 DEFAULT_STRING_STUB)) {
2009 index_out_of_range_label = &miss;
2010 }
2011
2012 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2013
2014 Register receiver = r0;
2015 Register index = r4;
2016 Register scratch = r3;
2017 Register result = r1;
2018 if (argc > 0) {
2019 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
2020 } else {
2021 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2022 }
2023
2024 StringCharAtGenerator generator(receiver,
2025 index,
2026 scratch,
2027 result,
2028 &miss, // When not a string.
2029 &miss, // When not a number.
2030 index_out_of_range_label,
2031 STRING_INDEX_IS_NUMBER);
2032 generator.GenerateFast(masm());
2033 __ Drop(argc + 1);
2034 __ mov(r0, result);
2035 __ Ret();
2036
2037 StubRuntimeCallHelper call_helper;
2038 generator.GenerateSlow(masm(), call_helper);
2039
2040 if (index_out_of_range.is_linked()) {
2041 __ bind(&index_out_of_range);
2042 __ LoadRoot(r0, Heap::kempty_stringRootIndex);
2043 __ Drop(argc + 1);
2044 __ Ret();
2045 }
2046
2047 __ bind(&miss);
2048 // Restore function name in r2.
2049 __ Move(r2, name);
2050 HandlerFrontendFooter(&name_miss);
2051
2052 // Return the generated code.
2053 return GetCode(type, name);
2054 }
2055
2056
2057 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
2058 Handle<Object> object,
2059 Handle<JSObject> holder,
2060 Handle<Cell> cell,
2061 Handle<JSFunction> function,
2062 Handle<String> name,
2063 Code::StubType type) {
2064 const int argc = arguments().immediate();
2065
2066 // If the object is not a JSObject or we got an unexpected number of
2067 // arguments, bail out to the regular call.
2068 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2069
2070 Label miss;
2071
2072 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2073 if (!cell.is_null()) {
2074 ASSERT(cell->value() == *function);
2075 GenerateLoadFunctionFromCell(cell, function, &miss);
2076 }
2077
2078 // Load the char code argument.
2079 Register code = r1;
2080 __ ldr(code, MemOperand(sp, 0 * kPointerSize));
2081
2082 // Check the code is a smi.
2083 Label slow;
2084 __ JumpIfNotSmi(code, &slow);
2085
2086 // Convert the smi code to uint16.
2087 __ and_(code, code, Operand(Smi::FromInt(0xffff)));
2088
2089 StringCharFromCodeGenerator generator(code, r0);
2090 generator.GenerateFast(masm());
2091 __ Drop(argc + 1);
2092 __ Ret();
2093
2094 StubRuntimeCallHelper call_helper;
2095 generator.GenerateSlow(masm(), call_helper);
2096
2097 __ bind(&slow);
2098 // We do not have to patch the receiver because the function makes no use of
2099 // it.
2100 GenerateJumpFunctionIgnoreReceiver(function);
2101
2102 HandlerFrontendFooter(&miss);
2103
2104 // Return the generated code.
2105 return GetCode(type, name);
2106 }
2107
2108
2109 Handle<Code> CallStubCompiler::CompileMathFloorCall(
2110 Handle<Object> object,
2111 Handle<JSObject> holder,
2112 Handle<Cell> cell,
2113 Handle<JSFunction> function,
2114 Handle<String> name,
2115 Code::StubType type) {
2116 const int argc = arguments().immediate();
2117 // If the object is not a JSObject or we got an unexpected number of
2118 // arguments, bail out to the regular call.
2119 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2120
2121 Label miss, slow;
2122
2123 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2124 if (!cell.is_null()) {
2125 ASSERT(cell->value() == *function);
2126 GenerateLoadFunctionFromCell(cell, function, &miss);
2127 }
2128
2129 // Load the (only) argument into r0.
2130 __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2131
2132 // If the argument is a smi, just return.
2133 __ SmiTst(r0);
2134 __ Drop(argc + 1, eq);
2135 __ Ret(eq);
2136
2137 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2138
2139 Label smi_check, just_return;
2140
2141 // Load the HeapNumber value.
2142 // We will need access to the value in the core registers, so we load it
2143 // with ldrd and move it to the fpu. It also spares a sub instruction for
2144 // updating the HeapNumber value address, as vldr expects a multiple
2145 // of 4 offset.
2146 __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
2147 __ vmov(d1, r4, r5);
2148
2149 // Check for NaN, Infinities and -0.
2150 // They are invariant through a Math.Floor call, so just
2151 // return the original argument.
2152 __ Sbfx(r3, r5, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
2153 __ cmp(r3, Operand(-1));
2154 __ b(eq, &just_return);
2155 __ eor(r3, r5, Operand(0x80000000u));
2156 __ orr(r3, r3, r4, SetCC);
2157 __ b(eq, &just_return);
2158 // Test for values that can be exactly represented as a
2159 // signed 32-bit integer.
2160 __ TryDoubleToInt32Exact(r0, d1, d2);
2161 // If exact, check smi
2162 __ b(eq, &smi_check);
2163 __ cmp(r5, Operand(0));
2164
2165 // If input is in ]+0, +inf[, the cmp has cleared overflow and negative
2166 // (V=0 and N=0), the two following instructions won't execute and
2167 // we fall through smi_check to check if the result can fit into a smi.
2168
2169 // If input is in ]-inf, -0[, sub one and, go to slow if we have
2170 // an overflow. Else we fall through smi check.
2171 // Hint: if x is a negative, non integer number,
2172 // floor(x) <=> round_to_zero(x) - 1.
2173 __ sub(r0, r0, Operand(1), SetCC, mi);
2174 __ b(vs, &slow);
2175
2176 __ bind(&smi_check);
2177 // Check if the result can fit into an smi. If we had an overflow,
2178 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi.
2179 // If result doesn't fit into an smi, branch to slow.
2180 __ SmiTag(r0, SetCC);
2181 __ b(vs, &slow);
2182
2183 __ bind(&just_return);
2184 __ Drop(argc + 1);
2185 __ Ret();
2186
2187 __ bind(&slow);
2188 // We do not have to patch the receiver because the function makes no use of
2189 // it.
2190 GenerateJumpFunctionIgnoreReceiver(function);
2191
2192 HandlerFrontendFooter(&miss);
2193
2194 // Return the generated code.
2195 return GetCode(type, name);
2196 }
2197
2198
2199 Handle<Code> CallStubCompiler::CompileMathAbsCall(
2200 Handle<Object> object,
2201 Handle<JSObject> holder,
2202 Handle<Cell> cell,
2203 Handle<JSFunction> function,
2204 Handle<String> name,
2205 Code::StubType type) {
2206 const int argc = arguments().immediate();
2207 // If the object is not a JSObject or we got an unexpected number of
2208 // arguments, bail out to the regular call.
2209 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2210
2211 Label miss;
2212
2213 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2214 if (!cell.is_null()) {
2215 ASSERT(cell->value() == *function);
2216 GenerateLoadFunctionFromCell(cell, function, &miss);
2217 }
2218
2219 // Load the (only) argument into r0.
2220 __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2221
2222 // Check if the argument is a smi.
2223 Label not_smi;
2224 __ JumpIfNotSmi(r0, &not_smi);
2225
2226 // Do bitwise not or do nothing depending on the sign of the
2227 // argument.
2228 __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1));
2229
2230 // Add 1 or do nothing depending on the sign of the argument.
2231 __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC);
2232
2233 // If the result is still negative, go to the slow case.
2234 // This only happens for the most negative smi.
2235 Label slow;
2236 __ b(mi, &slow);
2237
2238 // Smi case done.
2239 __ Drop(argc + 1);
2240 __ Ret();
2241
2242 // Check if the argument is a heap number and load its exponent and
2243 // sign.
2244 __ bind(&not_smi);
2245 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2246 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2247
2248 // Check the sign of the argument. If the argument is positive,
2249 // just return it.
2250 Label negative_sign;
2251 __ tst(r1, Operand(HeapNumber::kSignMask));
2252 __ b(ne, &negative_sign);
2253 __ Drop(argc + 1);
2254 __ Ret();
2255
2256 // If the argument is negative, clear the sign, and return a new
2257 // number.
2258 __ bind(&negative_sign);
2259 __ eor(r1, r1, Operand(HeapNumber::kSignMask));
2260 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2261 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2262 __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
2263 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2264 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2265 __ Drop(argc + 1);
2266 __ Ret();
2267
2268 __ bind(&slow);
2269 // We do not have to patch the receiver because the function makes no use of
2270 // it.
2271 GenerateJumpFunctionIgnoreReceiver(function);
2272
2273 HandlerFrontendFooter(&miss);
2274
2275 // Return the generated code.
2276 return GetCode(type, name);
2277 }
2278
2279
2280 Handle<Code> CallStubCompiler::CompileFastApiCall( 1604 Handle<Code> CallStubCompiler::CompileFastApiCall(
2281 const CallOptimization& optimization, 1605 const CallOptimization& optimization,
2282 Handle<Object> object, 1606 Handle<Object> object,
2283 Handle<JSObject> holder, 1607 Handle<JSObject> holder,
2284 Handle<Cell> cell, 1608 Handle<Cell> cell,
2285 Handle<JSFunction> function, 1609 Handle<JSFunction> function,
2286 Handle<String> name) { 1610 Handle<String> name) {
2287 Counters* counters = isolate()->counters(); 1611 Counters* counters = isolate()->counters();
2288 1612
2289 ASSERT(optimization.is_simple_api_call()); 1613 ASSERT(optimization.is_simple_api_call());
2290 // 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
2291 // repatch it to global receiver. 1615 // repatch it to global receiver.
2292 if (object->IsGlobalObject()) return Handle<Code>::null(); 1616 if (object->IsGlobalObject()) return Handle<Code>::null();
2293 if (!cell.is_null()) return Handle<Code>::null(); 1617 if (!cell.is_null()) return Handle<Code>::null();
2294 if (!object->IsJSObject()) return Handle<Code>::null(); 1618 if (!object->IsJSObject()) return Handle<Code>::null();
2295 int depth = optimization.GetPrototypeDepthOfExpectedType( 1619 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
2296 Handle<JSObject>::cast(object), holder); 1620 CallOptimization::HolderLookup holder_lookup =
2297 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 }
2298 1627
2299 Label miss, miss_before_stack_reserved; 1628 Label miss;
2300 GenerateNameCheck(name, &miss_before_stack_reserved); 1629 GenerateNameCheck(name, &miss);
2301 1630
2302 // Get the receiver from the stack. 1631 // Get the receiver from the stack.
2303 const int argc = arguments().immediate(); 1632 const int argc = arguments().immediate();
2304 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 1633 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2305 1634
2306 // Check that the receiver isn't a smi. 1635 // Check that the receiver isn't a smi.
2307 __ JumpIfSmi(r1, &miss_before_stack_reserved); 1636 __ JumpIfSmi(r1, &miss);
2308 1637
2309 __ IncrementCounter(counters->call_const(), 1, r0, r3); 1638 __ IncrementCounter(counters->call_const(), 1, r0, r3);
2310 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
2311
2312 ReserveSpaceForFastApiCall(masm(), r0);
2313 1639
2314 // 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.
2315 CheckPrototypes( 1641 CheckPrototypes(
2316 IC::CurrentTypeOf(object, isolate()), 1642 IC::CurrentTypeOf(object, isolate()),
2317 r1, holder, r0, r3, r4, name, depth, &miss); 1643 r1, holder, r0, r3, r4, name, &miss);
2318 1644
2319 GenerateFastApiDirectCall(masm(), optimization, argc, false); 1645 GenerateFastApiCall(
1646 masm(), optimization, argc, lookup_map, holder_lookup);
2320 1647
2321 __ bind(&miss); 1648 HandlerFrontendFooter(&miss);
2322 FreeSpaceForFastApiCall(masm());
2323
2324 HandlerFrontendFooter(&miss_before_stack_reserved);
2325 1649
2326 // Return the generated code. 1650 // Return the generated code.
2327 return GetCode(function); 1651 return GetCode(function);
2328 } 1652 }
2329 1653
2330 1654
2331 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1655 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2332 Label success; 1656 Label success;
2333 // Check that the object is a boolean. 1657 // Check that the object is a boolean.
2334 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1658 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
2511 // Return the generated code. 1835 // Return the generated code.
2512 return GetCode(Code::NORMAL, name); 1836 return GetCode(Code::NORMAL, name);
2513 } 1837 }
2514 1838
2515 1839
2516 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1840 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2517 Handle<JSObject> object, 1841 Handle<JSObject> object,
2518 Handle<JSObject> holder, 1842 Handle<JSObject> holder,
2519 Handle<Name> name, 1843 Handle<Name> name,
2520 Handle<ExecutableAccessorInfo> callback) { 1844 Handle<ExecutableAccessorInfo> callback) {
2521 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), 1845 Register holder_reg = HandlerFrontend(
2522 receiver(), holder, name); 1846 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
2523 1847
2524 // Stub never generated for non-global objects that require access checks. 1848 // Stub never generated for non-global objects that require access checks.
2525 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1849 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2526 1850
2527 __ push(receiver()); // receiver 1851 __ push(receiver()); // receiver
1852 __ push(holder_reg);
2528 __ mov(ip, Operand(callback)); // callback info 1853 __ mov(ip, Operand(callback)); // callback info
2529 __ push(ip); 1854 __ push(ip);
2530 __ mov(ip, Operand(name)); 1855 __ mov(ip, Operand(name));
2531 __ Push(ip, value()); 1856 __ Push(ip, value());
2532 1857
2533 // Do tail-call to the runtime system. 1858 // Do tail-call to the runtime system.
2534 ExternalReference store_callback_property = 1859 ExternalReference store_callback_property =
2535 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 1860 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2536 __ TailCallExternalReference(store_callback_property, 4, 1); 1861 __ TailCallExternalReference(store_callback_property, 5, 1);
2537 1862
2538 // Return the generated code. 1863 // Return the generated code.
2539 return GetCode(kind(), Code::FAST, name); 1864 return GetCode(kind(), Code::FAST, name);
2540 } 1865 }
2541 1866
2542 1867
2543 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1868 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2544 Handle<JSObject> object, 1869 Handle<JSObject> object,
2545 Handle<JSObject> holder, 1870 Handle<JSObject> holder,
2546 Handle<Name> name, 1871 Handle<Name> name,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
2630 1955
2631 // Handle store cache miss. 1956 // Handle store cache miss.
2632 __ bind(&miss); 1957 __ bind(&miss);
2633 TailCallBuiltin(masm(), MissBuiltin(kind())); 1958 TailCallBuiltin(masm(), MissBuiltin(kind()));
2634 1959
2635 // Return the generated code. 1960 // Return the generated code.
2636 return GetCode(kind(), Code::FAST, name); 1961 return GetCode(kind(), Code::FAST, name);
2637 } 1962 }
2638 1963
2639 1964
2640 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, 1965 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
2641 Handle<JSObject> last, 1966 Handle<JSObject> last,
2642 Handle<Name> name) { 1967 Handle<Name> name) {
2643 NonexistentHandlerFrontend(type, last, name); 1968 NonexistentHandlerFrontend(type, last, name);
2644 1969
2645 // Return undefined if maps of the full prototype chain are still the 1970 // Return undefined if maps of the full prototype chain are still the
2646 // same and no global property with this name contains a value. 1971 // same and no global property with this name contains a value.
2647 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 1972 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2648 __ Ret(); 1973 __ Ret();
2649 1974
2650 // Return the generated code. 1975 // Return the generated code.
(...skipping 22 matching lines...) Expand all
2673 } 1998 }
2674 1999
2675 2000
2676 Register* KeyedStoreStubCompiler::registers() { 2001 Register* KeyedStoreStubCompiler::registers() {
2677 // receiver, name, value, scratch1, scratch2, scratch3. 2002 // receiver, name, value, scratch1, scratch2, scratch3.
2678 static Register registers[] = { r2, r1, r0, r3, r4, r5 }; 2003 static Register registers[] = { r2, r1, r0, r3, r4, r5 };
2679 return registers; 2004 return registers;
2680 } 2005 }
2681 2006
2682 2007
2683 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
2684 Register name_reg,
2685 Label* miss) {
2686 __ cmp(name_reg, Operand(name));
2687 __ b(ne, miss);
2688 }
2689
2690
2691 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
2692 Register name_reg,
2693 Label* miss) {
2694 __ cmp(name_reg, Operand(name));
2695 __ b(ne, miss);
2696 }
2697
2698
2699 #undef __ 2008 #undef __
2700 #define __ ACCESS_MASM(masm) 2009 #define __ ACCESS_MASM(masm)
2701 2010
2702 2011
2703 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, 2012 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
2704 Register receiver, 2013 Register receiver,
2705 Handle<JSFunction> getter) { 2014 Handle<JSFunction> getter) {
2706 // ----------- S t a t e ------------- 2015 // ----------- S t a t e -------------
2707 // -- r0 : receiver 2016 // -- r0 : receiver
2708 // -- r2 : name 2017 // -- r2 : name
(...skipping 20 matching lines...) Expand all
2729 } 2038 }
2730 __ Ret(); 2039 __ Ret();
2731 } 2040 }
2732 2041
2733 2042
2734 #undef __ 2043 #undef __
2735 #define __ ACCESS_MASM(masm()) 2044 #define __ ACCESS_MASM(masm())
2736 2045
2737 2046
2738 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2047 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
2739 Handle<Type> type, 2048 Handle<HeapType> type,
2740 Handle<GlobalObject> global, 2049 Handle<GlobalObject> global,
2741 Handle<PropertyCell> cell, 2050 Handle<PropertyCell> cell,
2742 Handle<Name> name, 2051 Handle<Name> name,
2743 bool is_dont_delete) { 2052 bool is_dont_delete) {
2744 Label miss; 2053 Label miss;
2745 2054
2746 HandlerFrontendHeader(type, receiver(), global, name, &miss); 2055 HandlerFrontendHeader(type, receiver(), global, name, &miss);
2747 2056
2748 // Get the value from the cell. 2057 // Get the value from the cell.
2749 __ mov(r3, Operand(cell)); 2058 __ mov(r3, Operand(cell));
(...skipping 19 matching lines...) Expand all
2769 2078
2770 2079
2771 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 2080 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2772 TypeHandleList* types, 2081 TypeHandleList* types,
2773 CodeHandleList* handlers, 2082 CodeHandleList* handlers,
2774 Handle<Name> name, 2083 Handle<Name> name,
2775 Code::StubType type, 2084 Code::StubType type,
2776 IcCheckType check) { 2085 IcCheckType check) {
2777 Label miss; 2086 Label miss;
2778 2087
2779 if (check == PROPERTY) { 2088 if (check == PROPERTY &&
2780 GenerateNameCheck(name, this->name(), &miss); 2089 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
2090 __ cmp(this->name(), Operand(name));
2091 __ b(ne, &miss);
2781 } 2092 }
2782 2093
2783 Label number_case; 2094 Label number_case;
2784 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 2095 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2785 __ JumpIfSmi(receiver(), smi_target); 2096 __ JumpIfSmi(receiver(), smi_target);
2786 2097
2787 Register map_reg = scratch1(); 2098 Register map_reg = scratch1();
2788 2099
2789 int receiver_count = types->length(); 2100 int receiver_count = types->length();
2790 int number_of_handled_maps = 0; 2101 int number_of_handled_maps = 0;
2791 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); 2102 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
2792 for (int current = 0; current < receiver_count; ++current) { 2103 for (int current = 0; current < receiver_count; ++current) {
2793 Handle<Type> type = types->at(current); 2104 Handle<HeapType> type = types->at(current);
2794 Handle<Map> map = IC::TypeToMap(*type, isolate()); 2105 Handle<Map> map = IC::TypeToMap(*type, isolate());
2795 if (!map->is_deprecated()) { 2106 if (!map->is_deprecated()) {
2796 number_of_handled_maps++; 2107 number_of_handled_maps++;
2797 __ mov(ip, Operand(map)); 2108 __ mov(ip, Operand(map));
2798 __ cmp(map_reg, ip); 2109 __ cmp(map_reg, ip);
2799 if (type->Is(Type::Number())) { 2110 if (type->Is(HeapType::Number())) {
2800 ASSERT(!number_case.is_unused()); 2111 ASSERT(!number_case.is_unused());
2801 __ bind(&number_case); 2112 __ bind(&number_case);
2802 } 2113 }
2803 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); 2114 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq);
2804 } 2115 }
2805 } 2116 }
2806 ASSERT(number_of_handled_maps != 0); 2117 ASSERT(number_of_handled_maps != 0);
2807 2118
2808 __ bind(&miss); 2119 __ bind(&miss);
2809 TailCallBuiltin(masm(), MissBuiltin(kind())); 2120 TailCallBuiltin(masm(), MissBuiltin(kind()));
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2890 // ----------------------------------- 2201 // -----------------------------------
2891 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2202 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2892 } 2203 }
2893 2204
2894 2205
2895 #undef __ 2206 #undef __
2896 2207
2897 } } // namespace v8::internal 2208 } } // namespace v8::internal
2898 2209
2899 #endif // V8_TARGET_ARCH_ARM 2210 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698