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

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

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 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/simulator-arm.cc ('k') | src/array.js » ('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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
289 } 289 }
290 290
291 291
292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
293 MacroAssembler* masm, 293 MacroAssembler* masm,
294 int index, 294 int index,
295 Register prototype, 295 Register prototype,
296 Label* miss) { 296 Label* miss) {
297 Isolate* isolate = masm->isolate(); 297 Isolate* isolate = masm->isolate();
298 // Check we're still in the same context.
299 __ ldr(prototype,
300 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
301 __ Move(ip, isolate->global_object());
302 __ cmp(prototype, ip);
303 __ b(ne, miss);
304 // Get the global function with the given index. 298 // Get the global function with the given index.
305 Handle<JSFunction> function( 299 Handle<JSFunction> function(
306 JSFunction::cast(isolate->native_context()->get(index))); 300 JSFunction::cast(isolate->native_context()->get(index)));
301
302 // Check we're still in the same context.
303 Register scratch = prototype;
304 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
305 __ ldr(scratch, MemOperand(cp, offset));
306 __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
307 __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index)));
308 __ Move(ip, function);
309 __ cmp(ip, scratch);
310 __ b(ne, miss);
311
307 // Load its initial map. The global functions all have initial maps. 312 // Load its initial map. The global functions all have initial maps.
308 __ Move(prototype, Handle<Map>(function->initial_map())); 313 __ Move(prototype, Handle<Map>(function->initial_map()));
309 // Load the prototype from the initial map. 314 // Load the prototype from the initial map.
310 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 315 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
311 } 316 }
312 317
313 318
314 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 319 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
315 Register dst, 320 Register dst,
316 Register src, 321 Register src,
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 Register name, 775 Register name,
771 Handle<JSObject> holder_obj, 776 Handle<JSObject> holder_obj,
772 IC::UtilityId id) { 777 IC::UtilityId id) {
773 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 778 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
774 __ CallExternalReference( 779 __ CallExternalReference(
775 ExternalReference(IC_Utility(id), masm->isolate()), 780 ExternalReference(IC_Utility(id), masm->isolate()),
776 StubCache::kInterceptorArgsLength); 781 StubCache::kInterceptorArgsLength);
777 } 782 }
778 783
779 784
780 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 785 // Generate call to api function.
786 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm,
787 const CallOptimization& optimization,
788 Handle<Map> receiver_map,
789 Register receiver,
790 Register scratch_in,
791 bool is_store,
792 int argc,
793 Register* values) {
794 ASSERT(!receiver.is(scratch_in));
795 __ push(receiver);
796 // Write the arguments to stack frame.
797 for (int i = 0; i < argc; i++) {
798 Register arg = values[argc-1-i];
799 ASSERT(!receiver.is(arg));
800 ASSERT(!scratch_in.is(arg));
801 __ push(arg);
802 }
803 ASSERT(optimization.is_simple_api_call());
781 804
782 // Reserves space for the extra arguments to API function in the 805 // Abi for CallApiFunctionStub.
783 // caller's frame. 806 Register callee = r0;
784 // 807 Register call_data = r4;
785 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. 808 Register holder = r2;
786 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, 809 Register api_function_address = r1;
787 Register scratch) { 810
788 __ mov(scratch, Operand(Smi::FromInt(0))); 811 // Put holder in place.
789 for (int i = 0; i < kFastApiCallArguments; i++) { 812 CallOptimization::HolderLookup holder_lookup;
790 __ push(scratch); 813 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
814 receiver_map,
815 &holder_lookup);
816 switch (holder_lookup) {
817 case CallOptimization::kHolderIsReceiver:
818 __ Move(holder, receiver);
819 break;
820 case CallOptimization::kHolderFound:
821 __ Move(holder, api_holder);
822 break;
823 case CallOptimization::kHolderNotFound:
824 UNREACHABLE();
825 break;
791 } 826 }
792 }
793 827
828 Isolate* isolate = masm->isolate();
829 Handle<JSFunction> function = optimization.constant_function();
830 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
831 Handle<Object> call_data_obj(api_call_info->data(), isolate);
794 832
795 // Undoes the effects of ReserveSpaceForFastApiCall. 833 // Put callee in place.
796 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { 834 __ Move(callee, function);
797 __ Drop(kFastApiCallArguments);
798 }
799 835
836 bool call_data_undefined = false;
837 // Put call_data in place.
838 if (isolate->heap()->InNewSpace(*call_data_obj)) {
839 __ Move(call_data, api_call_info);
840 __ ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset));
841 } else if (call_data_obj->IsUndefined()) {
842 call_data_undefined = true;
843 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
844 } else {
845 __ Move(call_data, call_data_obj);
846 }
800 847
801 static void GenerateFastApiDirectCall(MacroAssembler* masm, 848 // Put api_function_address in place.
802 const CallOptimization& optimization,
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.
815 __ str(cp, MemOperand(sp, FCA::kContextSaveIndex * kPointerSize));
816 // Get the function and setup the context.
817 Handle<JSFunction> function = optimization.constant_function();
818 __ Move(r5, function);
819 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
820 __ str(r5, MemOperand(sp, FCA::kCalleeIndex * kPointerSize));
821
822 // Construct the FunctionCallbackInfo.
823 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
824 Handle<Object> call_data(api_call_info->data(), masm->isolate());
825 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
826 __ Move(r0, api_call_info);
827 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
828 } else {
829 __ Move(r6, call_data);
830 }
831 // Store call data.
832 __ str(r6, MemOperand(sp, FCA::kDataIndex * kPointerSize));
833 // Store isolate.
834 __ mov(r5, Operand(ExternalReference::isolate_address(masm->isolate())));
835 __ str(r5, MemOperand(sp, FCA::kIsolateIndex * kPointerSize));
836 // Store ReturnValue default and ReturnValue.
837 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
838 __ str(r5, MemOperand(sp, FCA::kReturnValueOffset * kPointerSize));
839 __ str(r5, MemOperand(sp, FCA::kReturnValueDefaultValueIndex * kPointerSize));
840
841 // Prepare arguments.
842 __ mov(r2, sp);
843
844 // Allocate the v8::Arguments structure in the arguments' space since
845 // it's not controlled by GC.
846 const int kApiStackSpace = 4;
847
848 FrameScope frame_scope(masm, StackFrame::MANUAL);
849 __ EnterExitFrame(false, kApiStackSpace);
850
851 // r0 = FunctionCallbackInfo&
852 // Arguments is after the return address.
853 __ add(r0, sp, Operand(1 * kPointerSize));
854 // FunctionCallbackInfo::implicit_args_
855 __ str(r2, MemOperand(r0, 0 * kPointerSize));
856 // FunctionCallbackInfo::values_
857 __ add(ip, r2, Operand((kFastApiCallArguments - 1 + argc) * kPointerSize));
858 __ str(ip, MemOperand(r0, 1 * kPointerSize));
859 // FunctionCallbackInfo::length_ = argc
860 __ mov(ip, Operand(argc));
861 __ str(ip, MemOperand(r0, 2 * kPointerSize));
862 // FunctionCallbackInfo::is_construct_call = 0
863 __ mov(ip, Operand::Zero());
864 __ str(ip, MemOperand(r0, 3 * kPointerSize));
865
866 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
867 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 849 Address function_address = v8::ToCData<Address>(api_call_info->callback());
868 ApiFunction fun(function_address); 850 ApiFunction fun(function_address);
869 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 851 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
870 ExternalReference ref = ExternalReference(&fun, 852 ExternalReference ref = ExternalReference(&fun,
871 type, 853 type,
872 masm->isolate()); 854 masm->isolate());
873 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); 855 __ mov(api_function_address, Operand(ref));
874 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
875 ApiFunction thunk_fun(thunk_address);
876 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
877 masm->isolate());
878 856
879 AllowExternalCallThatCantCauseGC scope(masm); 857 // Jump to stub.
880 MemOperand context_restore_operand( 858 CallApiFunctionStub stub(is_store, call_data_undefined, argc);
881 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 859 __ TailCallStub(&stub);
882 MemOperand return_value_operand(fp,
883 (2 + FCA::kReturnValueOffset) * kPointerSize);
884
885 __ CallApiFunctionAndReturn(ref,
886 function_address,
887 thunk_ref,
888 r1,
889 kStackUnwindSpace,
890 return_value_operand,
891 restore_context ?
892 &context_restore_operand : NULL);
893 } 860 }
894 861
895 862
896 // Generate call to api function.
897 static void GenerateFastApiCall(MacroAssembler* masm,
898 const CallOptimization& optimization,
899 Register receiver,
900 Register scratch,
901 int argc,
902 Register* values) {
903 ASSERT(optimization.is_simple_api_call());
904 ASSERT(!receiver.is(scratch));
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));
915 // Write the arguments to stack frame.
916 for (int i = 0; i < argc; i++) {
917 ASSERT(!receiver.is(values[i]));
918 ASSERT(!scratch.is(values[i]));
919 __ str(values[i], MemOperand(sp, index-- * kPointerSize));
920 }
921
922 GenerateFastApiDirectCall(masm, optimization, argc, true);
923 }
924
925
926 class CallInterceptorCompiler BASE_EMBEDDED {
927 public:
928 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
929 const ParameterCount& arguments,
930 Register name)
931 : stub_compiler_(stub_compiler),
932 arguments_(arguments),
933 name_(name) {}
934
935 void Compile(MacroAssembler* masm,
936 Handle<JSObject> object,
937 Handle<JSObject> holder,
938 Handle<Name> name,
939 LookupResult* lookup,
940 Register receiver,
941 Register scratch1,
942 Register scratch2,
943 Register scratch3,
944 Label* miss) {
945 ASSERT(holder->HasNamedInterceptor());
946 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
947
948 // Check that the receiver isn't a smi.
949 __ JumpIfSmi(receiver, miss);
950 CallOptimization optimization(lookup);
951 if (optimization.is_constant_call()) {
952 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
953 holder, lookup, name, optimization, miss);
954 } else {
955 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
956 name, holder, miss);
957 }
958 }
959
960 private:
961 void CompileCacheable(MacroAssembler* masm,
962 Handle<JSObject> object,
963 Register receiver,
964 Register scratch1,
965 Register scratch2,
966 Register scratch3,
967 Handle<JSObject> interceptor_holder,
968 LookupResult* lookup,
969 Handle<Name> name,
970 const CallOptimization& optimization,
971 Label* miss_label) {
972 ASSERT(optimization.is_constant_call());
973 ASSERT(!lookup->holder()->IsGlobalObject());
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
990 __ IncrementCounter(counters->call_const_interceptor(), 1,
991 scratch1, scratch2);
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
999 // Check that the maps from receiver to interceptor's holder
1000 // haven't changed and thus we can invoke interceptor.
1001 Label miss_cleanup;
1002 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
1003 Register holder =
1004 stub_compiler_->CheckPrototypes(
1005 IC::CurrentTypeOf(object, masm->isolate()), receiver,
1006 interceptor_holder, scratch1, scratch2, scratch3,
1007 name, depth1, miss);
1008
1009 // Invoke an interceptor and if it provides a value,
1010 // branch to |regular_invoke|.
1011 Label regular_invoke;
1012 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
1013 &regular_invoke);
1014
1015 // Interceptor returned nothing for this property. Try to use cached
1016 // constant function.
1017
1018 // 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.
1020 if (*interceptor_holder != lookup->holder()) {
1021 stub_compiler_->CheckPrototypes(
1022 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
1023 handle(lookup->holder()), scratch1, scratch2, scratch3,
1024 name, depth2, miss);
1025 } else {
1026 // CheckPrototypes has a side effect of fetching a 'holder'
1027 // for API (object which is instanceof for the signature). It's
1028 // safe to omit it here, as if present, it should be fetched
1029 // by the previous CheckPrototypes.
1030 ASSERT(depth2 == kInvalidProtoDepth);
1031 }
1032
1033 // Invoke function.
1034 if (can_do_fast_api_call) {
1035 GenerateFastApiDirectCall(
1036 masm, optimization, arguments_.immediate(), false);
1037 } else {
1038 Handle<JSFunction> function = optimization.constant_function();
1039 __ Move(r0, receiver);
1040 stub_compiler_->GenerateJumpFunction(object, function);
1041 }
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
1050 // Invoke a regular function.
1051 __ bind(&regular_invoke);
1052 if (can_do_fast_api_call) {
1053 FreeSpaceForFastApiCall(masm);
1054 }
1055 }
1056
1057 void CompileRegular(MacroAssembler* masm,
1058 Handle<JSObject> object,
1059 Register receiver,
1060 Register scratch1,
1061 Register scratch2,
1062 Register scratch3,
1063 Handle<Name> name,
1064 Handle<JSObject> interceptor_holder,
1065 Label* miss_label) {
1066 Register holder =
1067 stub_compiler_->CheckPrototypes(
1068 IC::CurrentTypeOf(object, masm->isolate()), receiver,
1069 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
1070
1071 // Call a runtime function to load the interceptor property.
1072 FrameScope scope(masm, StackFrame::INTERNAL);
1073 // Save the name_ register across the call.
1074 __ push(name_);
1075
1076 CompileCallLoadPropertyWithInterceptor(
1077 masm, receiver, holder, name_, interceptor_holder,
1078 IC::kLoadPropertyWithInterceptorForCall);
1079
1080 // Restore the name_ register.
1081 __ pop(name_);
1082 // Leave the internal frame.
1083 }
1084
1085 void LoadWithInterceptor(MacroAssembler* masm,
1086 Register receiver,
1087 Register holder,
1088 Handle<JSObject> holder_obj,
1089 Register scratch,
1090 Label* interceptor_succeeded) {
1091 {
1092 FrameScope scope(masm, StackFrame::INTERNAL);
1093 __ Push(receiver);
1094 __ Push(holder, name_);
1095 CompileCallLoadPropertyWithInterceptor(
1096 masm, receiver, holder, name_, holder_obj,
1097 IC::kLoadPropertyWithInterceptorOnly);
1098 __ pop(name_);
1099 __ pop(holder);
1100 __ pop(receiver);
1101 }
1102 // If interceptor returns no-result sentinel, call the constant function.
1103 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1104 __ cmp(r0, scratch);
1105 __ b(ne, interceptor_succeeded);
1106 }
1107
1108 CallStubCompiler* stub_compiler_;
1109 const ParameterCount& arguments_;
1110 Register name_;
1111 };
1112
1113
1114 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 863 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1115 __ Jump(code, RelocInfo::CODE_TARGET); 864 __ Jump(code, RelocInfo::CODE_TARGET);
1116 } 865 }
1117 866
1118 867
1119 #undef __ 868 #undef __
1120 #define __ ACCESS_MASM(masm()) 869 #define __ ACCESS_MASM(masm())
1121 870
1122 871
1123 Register StubCompiler::CheckPrototypes(Handle<Type> type, 872 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1124 Register object_reg, 873 Register object_reg,
1125 Handle<JSObject> holder, 874 Handle<JSObject> holder,
1126 Register holder_reg, 875 Register holder_reg,
1127 Register scratch1, 876 Register scratch1,
1128 Register scratch2, 877 Register scratch2,
1129 Handle<Name> name, 878 Handle<Name> name,
1130 int save_at_depth,
1131 Label* miss, 879 Label* miss,
1132 PrototypeCheckType check) { 880 PrototypeCheckType check) {
1133 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 881 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1134 // Make sure that the type feedback oracle harvests the receiver map.
1135 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1136 __ mov(scratch1, Operand(receiver_map));
1137 882
1138 // Make sure there's no overlap between holder and object registers. 883 // Make sure there's no overlap between holder and object registers.
1139 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 884 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1140 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 885 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1141 && !scratch2.is(scratch1)); 886 && !scratch2.is(scratch1));
1142 887
1143 // Keep track of the current object in register reg. 888 // Keep track of the current object in register reg.
1144 Register reg = object_reg; 889 Register reg = object_reg;
1145 int depth = 0; 890 int depth = 0;
1146 891
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(); 892 Handle<JSObject> current = Handle<JSObject>::null();
1153 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 893 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1154 Handle<JSObject> prototype = Handle<JSObject>::null(); 894 Handle<JSObject> prototype = Handle<JSObject>::null();
1155 Handle<Map> current_map = receiver_map; 895 Handle<Map> current_map = receiver_map;
1156 Handle<Map> holder_map(holder->map()); 896 Handle<Map> holder_map(holder->map());
1157 // Traverse the prototype chain and check the maps in the prototype chain for 897 // 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. 898 // fast and global objects or do negative lookup for normal objects.
1159 while (!current_map.is_identical_to(holder_map)) { 899 while (!current_map.is_identical_to(holder_map)) {
1160 ++depth; 900 ++depth;
1161 901
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 if (heap()->InNewSpace(*prototype)) { 947 if (heap()->InNewSpace(*prototype)) {
1208 // The prototype is in new space; we cannot store a reference to it 948 // The prototype is in new space; we cannot store a reference to it
1209 // in the code. Load it from the map. 949 // in the code. Load it from the map.
1210 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); 950 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
1211 } else { 951 } else {
1212 // The prototype is in old space; load it directly. 952 // The prototype is in old space; load it directly.
1213 __ mov(reg, Operand(prototype)); 953 __ mov(reg, Operand(prototype));
1214 } 954 }
1215 } 955 }
1216 956
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. 957 // Go to the next object in the prototype chain.
1222 current = prototype; 958 current = prototype;
1223 current_map = handle(current->map()); 959 current_map = handle(current->map());
1224 } 960 }
1225 961
1226 // Log the check depth. 962 // Log the check depth.
1227 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 963 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1228 964
1229 if (depth != 0 || check == CHECK_ALL_MAPS) { 965 if (depth != 0 || check == CHECK_ALL_MAPS) {
1230 // Check the holder map. 966 // Check the holder map.
(...skipping 28 matching lines...) Expand all
1259 Label success; 995 Label success;
1260 __ b(&success); 996 __ b(&success);
1261 GenerateRestoreName(masm(), miss, name); 997 GenerateRestoreName(masm(), miss, name);
1262 TailCallBuiltin(masm(), MissBuiltin(kind())); 998 TailCallBuiltin(masm(), MissBuiltin(kind()));
1263 __ bind(&success); 999 __ bind(&success);
1264 } 1000 }
1265 } 1001 }
1266 1002
1267 1003
1268 Register LoadStubCompiler::CallbackHandlerFrontend( 1004 Register LoadStubCompiler::CallbackHandlerFrontend(
1269 Handle<Type> type, 1005 Handle<HeapType> type,
1270 Register object_reg, 1006 Register object_reg,
1271 Handle<JSObject> holder, 1007 Handle<JSObject> holder,
1272 Handle<Name> name, 1008 Handle<Name> name,
1273 Handle<Object> callback) { 1009 Handle<Object> callback) {
1274 Label miss; 1010 Label miss;
1275 1011
1276 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); 1012 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1277 1013
1278 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1014 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1279 ASSERT(!reg.is(scratch2())); 1015 ASSERT(!reg.is(scratch2()));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 1067
1332 1068
1333 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { 1069 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
1334 // Return the constant value. 1070 // Return the constant value.
1335 __ Move(r0, value); 1071 __ Move(r0, value);
1336 __ Ret(); 1072 __ Ret();
1337 } 1073 }
1338 1074
1339 1075
1340 void LoadStubCompiler::GenerateLoadCallback( 1076 void LoadStubCompiler::GenerateLoadCallback(
1341 const CallOptimization& call_optimization) {
1342 GenerateFastApiCall(
1343 masm(), call_optimization, receiver(), scratch3(), 0, NULL);
1344 }
1345
1346
1347 void LoadStubCompiler::GenerateLoadCallback(
1348 Register reg, 1077 Register reg,
1349 Handle<ExecutableAccessorInfo> callback) { 1078 Handle<ExecutableAccessorInfo> callback) {
1350 // Build AccessorInfo::args_ list on the stack and push property name below 1079 // Build AccessorInfo::args_ list on the stack and push property name below
1351 // the exit frame to make GC aware of them and store pointers to them. 1080 // the exit frame to make GC aware of them and store pointers to them.
1352 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 1081 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
1353 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 1082 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
1354 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 1083 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
1355 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 1084 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
1356 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 1085 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
1357 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 1086 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
(...skipping 11 matching lines...) Expand all
1369 } 1098 }
1370 __ push(scratch3()); 1099 __ push(scratch3());
1371 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); 1100 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
1372 __ mov(scratch4(), scratch3()); 1101 __ mov(scratch4(), scratch3());
1373 __ Push(scratch3(), scratch4()); 1102 __ Push(scratch3(), scratch4());
1374 __ mov(scratch4(), 1103 __ mov(scratch4(),
1375 Operand(ExternalReference::isolate_address(isolate()))); 1104 Operand(ExternalReference::isolate_address(isolate())));
1376 __ Push(scratch4(), reg); 1105 __ Push(scratch4(), reg);
1377 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ 1106 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_
1378 __ push(name()); 1107 __ push(name());
1379 __ mov(r0, sp); // r0 = Handle<Name>
1380 1108
1381 const int kApiStackSpace = 1; 1109 // Abi for CallApiGetter
1382 FrameScope frame_scope(masm(), StackFrame::MANUAL); 1110 Register getter_address_reg = r2;
1383 __ EnterExitFrame(false, kApiStackSpace);
1384 1111
1385 // Create PropertyAccessorInfo instance on the stack above the exit frame with
1386 // scratch2 (internal::Object** args_) as the data.
1387 __ str(scratch2(), MemOperand(sp, 1 * kPointerSize));
1388 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo&
1389
1390 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
1391 Address getter_address = v8::ToCData<Address>(callback->getter()); 1112 Address getter_address = v8::ToCData<Address>(callback->getter());
1392
1393 ApiFunction fun(getter_address); 1113 ApiFunction fun(getter_address);
1394 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 1114 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1395 ExternalReference ref = ExternalReference(&fun, type, isolate()); 1115 ExternalReference ref = ExternalReference(&fun, type, isolate());
1116 __ mov(getter_address_reg, Operand(ref));
1396 1117
1397 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); 1118 CallApiGetterStub stub;
1398 ExternalReference::Type thunk_type = 1119 __ TailCallStub(&stub);
1399 ExternalReference::PROFILING_GETTER_CALL;
1400 ApiFunction thunk_fun(thunk_address);
1401 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
1402 isolate());
1403 __ CallApiFunctionAndReturn(ref,
1404 getter_address,
1405 thunk_ref,
1406 r2,
1407 kStackUnwindSpace,
1408 MemOperand(fp, 6 * kPointerSize),
1409 NULL);
1410 } 1120 }
1411 1121
1412 1122
1413 void LoadStubCompiler::GenerateLoadInterceptor( 1123 void LoadStubCompiler::GenerateLoadInterceptor(
1414 Register holder_reg, 1124 Register holder_reg,
1415 Handle<Object> object, 1125 Handle<Object> object,
1416 Handle<JSObject> interceptor_holder, 1126 Handle<JSObject> interceptor_holder,
1417 LookupResult* lookup, 1127 LookupResult* lookup,
1418 Handle<Name> name) { 1128 Handle<Name> name) {
1419 ASSERT(interceptor_holder->HasNamedInterceptor()); 1129 ASSERT(interceptor_holder->HasNamedInterceptor());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 this->name(), interceptor_holder); 1201 this->name(), interceptor_holder);
1492 1202
1493 ExternalReference ref = 1203 ExternalReference ref =
1494 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1204 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1495 isolate()); 1205 isolate());
1496 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1206 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1497 } 1207 }
1498 } 1208 }
1499 1209
1500 1210
1501 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1502 if (kind_ == Code::KEYED_CALL_IC) {
1503 __ cmp(r2, Operand(name));
1504 __ b(ne, miss);
1505 }
1506 }
1507
1508
1509 void CallStubCompiler::GenerateFunctionCheck(Register function,
1510 Register scratch,
1511 Label* miss) {
1512 __ JumpIfSmi(function, miss);
1513 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
1514 __ b(ne, miss);
1515 }
1516
1517
1518 void CallStubCompiler::GenerateLoadFunctionFromCell(
1519 Handle<Cell> cell,
1520 Handle<JSFunction> function,
1521 Label* miss) {
1522 // Get the value from the cell.
1523 __ mov(r3, Operand(cell));
1524 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset));
1525
1526 // Check that the cell contains the same function.
1527 if (heap()->InNewSpace(*function)) {
1528 // We can't embed a pointer to a function in new space so we have
1529 // to verify that the shared function info is unchanged. This has
1530 // the nice side effect that multiple closures based on the same
1531 // function can all use this call IC. Before we load through the
1532 // function, we have to verify that it still is a function.
1533 GenerateFunctionCheck(r1, r3, miss);
1534
1535 // Check the shared function info. Make sure it hasn't changed.
1536 __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
1537 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1538 __ cmp(r4, r3);
1539 } else {
1540 __ cmp(r1, Operand(function));
1541 }
1542 __ b(ne, miss);
1543 }
1544
1545
1546 void CallStubCompiler::GenerateMissBranch() {
1547 Handle<Code> code =
1548 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1549 kind_,
1550 extra_state());
1551 __ Jump(code, RelocInfo::CODE_TARGET);
1552 }
1553
1554
1555 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1556 Handle<JSObject> holder,
1557 PropertyIndex index,
1558 Handle<Name> name) {
1559 Label miss;
1560
1561 Register reg = HandlerFrontendHeader(
1562 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1563 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
1564 index.translate(holder), Representation::Tagged());
1565 GenerateJumpFunction(object, r1, &miss);
1566
1567 HandlerFrontendFooter(&miss);
1568
1569 // Return the generated code.
1570 return GetCode(Code::FAST, name);
1571 }
1572
1573
1574 Handle<Code> CallStubCompiler::CompileArrayPushCall(
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 // If object is not an array or is observed or sealed, bail out to regular
1582 // call.
1583 if (!object->IsJSArray() ||
1584 !cell.is_null() ||
1585 Handle<JSArray>::cast(object)->map()->is_observed() ||
1586 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1587 return Handle<Code>::null();
1588 }
1589
1590 Label miss;
1591
1592 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1593 Register receiver = r0;
1594 Register scratch = r1;
1595
1596 const int argc = arguments().immediate();
1597 if (argc == 0) {
1598 // Nothing to do, just return the length.
1599 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1600 __ Drop(argc + 1);
1601 __ Ret();
1602 } else {
1603 Label call_builtin;
1604
1605 if (argc == 1) { // Otherwise fall through to call the builtin.
1606 Label attempt_to_grow_elements, with_write_barrier, check_double;
1607
1608 Register elements = r6;
1609 Register end_elements = r5;
1610 // Get the elements array of the object.
1611 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1612
1613 // Check that the elements are in fast mode and writable.
1614 __ CheckMap(elements,
1615 scratch,
1616 Heap::kFixedArrayMapRootIndex,
1617 &check_double,
1618 DONT_DO_SMI_CHECK);
1619
1620 // Get the array's length into scratch and calculate new length.
1621 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1622 __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
1623
1624 // Get the elements' length.
1625 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1626
1627 // Check if we could survive without allocation.
1628 __ cmp(scratch, r4);
1629 __ b(gt, &attempt_to_grow_elements);
1630
1631 // Check if value is a smi.
1632 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
1633 __ JumpIfNotSmi(r4, &with_write_barrier);
1634
1635 // Save new length.
1636 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1637
1638 // Store the value.
1639 // We may need a register containing the address end_elements below,
1640 // so write back the value in end_elements.
1641 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1642 const int kEndElementsOffset =
1643 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
1644 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
1645
1646 // Check for a smi.
1647 __ Drop(argc + 1);
1648 __ mov(r0, scratch);
1649 __ Ret();
1650
1651 __ bind(&check_double);
1652
1653 // Check that the elements are in fast mode and writable.
1654 __ CheckMap(elements,
1655 scratch,
1656 Heap::kFixedDoubleArrayMapRootIndex,
1657 &call_builtin,
1658 DONT_DO_SMI_CHECK);
1659
1660 // Get the array's length into scratch and calculate new length.
1661 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1662 __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
1663
1664 // Get the elements' length.
1665 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1666
1667 // Check if we could survive without allocation.
1668 __ cmp(scratch, r4);
1669 __ b(gt, &call_builtin);
1670
1671 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
1672 __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
1673 &call_builtin, argc * kDoubleSize);
1674
1675 // Save new length.
1676 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1677
1678 __ Drop(argc + 1);
1679 __ mov(r0, scratch);
1680 __ Ret();
1681
1682 __ bind(&with_write_barrier);
1683
1684 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
1685
1686 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1687 Label fast_object, not_fast_object;
1688 __ CheckFastObjectElements(r3, r9, &not_fast_object);
1689 __ jmp(&fast_object);
1690 // In case of fast smi-only, convert to fast object, otherwise bail out.
1691 __ bind(&not_fast_object);
1692 __ CheckFastSmiElements(r3, r9, &call_builtin);
1693
1694 __ ldr(r9, FieldMemOperand(r4, HeapObject::kMapOffset));
1695 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1696 __ cmp(r9, ip);
1697 __ b(eq, &call_builtin);
1698 // edx: receiver
1699 // r3: map
1700 Label try_holey_map;
1701 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1702 FAST_ELEMENTS,
1703 r3,
1704 r9,
1705 &try_holey_map);
1706 __ mov(r2, receiver);
1707 ElementsTransitionGenerator::
1708 GenerateMapChangeElementsTransition(masm(),
1709 DONT_TRACK_ALLOCATION_SITE,
1710 NULL);
1711 __ jmp(&fast_object);
1712
1713 __ bind(&try_holey_map);
1714 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1715 FAST_HOLEY_ELEMENTS,
1716 r3,
1717 r9,
1718 &call_builtin);
1719 __ mov(r2, receiver);
1720 ElementsTransitionGenerator::
1721 GenerateMapChangeElementsTransition(masm(),
1722 DONT_TRACK_ALLOCATION_SITE,
1723 NULL);
1724 __ bind(&fast_object);
1725 } else {
1726 __ CheckFastObjectElements(r3, r3, &call_builtin);
1727 }
1728
1729 // Save new length.
1730 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1731
1732 // Store the value.
1733 // We may need a register containing the address end_elements below,
1734 // so write back the value in end_elements.
1735 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1736 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
1737
1738 __ RecordWrite(elements,
1739 end_elements,
1740 r4,
1741 kLRHasNotBeenSaved,
1742 kDontSaveFPRegs,
1743 EMIT_REMEMBERED_SET,
1744 OMIT_SMI_CHECK);
1745 __ Drop(argc + 1);
1746 __ mov(r0, scratch);
1747 __ Ret();
1748
1749 __ bind(&attempt_to_grow_elements);
1750 // scratch: array's length + 1.
1751
1752 if (!FLAG_inline_new) {
1753 __ b(&call_builtin);
1754 }
1755
1756 __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
1757 // Growing elements that are SMI-only requires special handling in case
1758 // the new element is non-Smi. For now, delegate to the builtin.
1759 Label no_fast_elements_check;
1760 __ JumpIfSmi(r2, &no_fast_elements_check);
1761 __ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset));
1762 __ CheckFastObjectElements(r9, r9, &call_builtin);
1763 __ bind(&no_fast_elements_check);
1764
1765 ExternalReference new_space_allocation_top =
1766 ExternalReference::new_space_allocation_top_address(isolate());
1767 ExternalReference new_space_allocation_limit =
1768 ExternalReference::new_space_allocation_limit_address(isolate());
1769
1770 const int kAllocationDelta = 4;
1771 // Load top and check if it is the end of elements.
1772 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
1773 __ add(end_elements, end_elements, Operand(kEndElementsOffset));
1774 __ mov(r4, Operand(new_space_allocation_top));
1775 __ ldr(r3, MemOperand(r4));
1776 __ cmp(end_elements, r3);
1777 __ b(ne, &call_builtin);
1778
1779 __ mov(r9, Operand(new_space_allocation_limit));
1780 __ ldr(r9, MemOperand(r9));
1781 __ add(r3, r3, Operand(kAllocationDelta * kPointerSize));
1782 __ cmp(r3, r9);
1783 __ b(hi, &call_builtin);
1784
1785 // We fit and could grow elements.
1786 // Update new_space_allocation_top.
1787 __ str(r3, MemOperand(r4));
1788 // Push the argument.
1789 __ str(r2, MemOperand(end_elements));
1790 // Fill the rest with holes.
1791 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
1792 for (int i = 1; i < kAllocationDelta; i++) {
1793 __ str(r3, MemOperand(end_elements, i * kPointerSize));
1794 }
1795
1796 // Update elements' and array's sizes.
1797 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1798 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1799 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
1800 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
1801
1802 // Elements are in new space, so write barrier is not required.
1803 __ Drop(argc + 1);
1804 __ mov(r0, scratch);
1805 __ Ret();
1806 }
1807 __ bind(&call_builtin);
1808 __ TailCallExternalReference(
1809 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
1810 }
1811
1812 HandlerFrontendFooter(&miss);
1813
1814 // Return the generated code.
1815 return GetCode(type, name);
1816 }
1817
1818
1819 Handle<Code> CallStubCompiler::CompileArrayPopCall(
1820 Handle<Object> object,
1821 Handle<JSObject> holder,
1822 Handle<Cell> cell,
1823 Handle<JSFunction> function,
1824 Handle<String> name,
1825 Code::StubType type) {
1826 // If object is not an array or is observed or sealed, bail out to regular
1827 // call.
1828 if (!object->IsJSArray() ||
1829 !cell.is_null() ||
1830 Handle<JSArray>::cast(object)->map()->is_observed() ||
1831 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1832 return Handle<Code>::null();
1833 }
1834
1835 Label miss, return_undefined, call_builtin;
1836 Register receiver = r0;
1837 Register scratch = r1;
1838 Register elements = r3;
1839
1840 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1841
1842 // Get the elements array of the object.
1843 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1844
1845 // Check that the elements are in fast mode and writable.
1846 __ CheckMap(elements,
1847 scratch,
1848 Heap::kFixedArrayMapRootIndex,
1849 &call_builtin,
1850 DONT_DO_SMI_CHECK);
1851
1852 // Get the array's length into r4 and calculate new length.
1853 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
1854 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
1855 __ b(lt, &return_undefined);
1856
1857 // Get the last element.
1858 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
1859 // We can't address the last element in one operation. Compute the more
1860 // expensive shift first, and use an offset later on.
1861 __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4));
1862 __ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
1863 __ cmp(scratch, r6);
1864 __ b(eq, &call_builtin);
1865
1866 // Set the array's length.
1867 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
1868
1869 // Fill with the hole.
1870 __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize));
1871 const int argc = arguments().immediate();
1872 __ Drop(argc + 1);
1873 __ mov(r0, scratch);
1874 __ Ret();
1875
1876 __ bind(&return_undefined);
1877 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1878 __ Drop(argc + 1);
1879 __ Ret();
1880
1881 __ bind(&call_builtin);
1882 __ TailCallExternalReference(
1883 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
1884
1885 HandlerFrontendFooter(&miss);
1886
1887 // Return the generated code.
1888 return GetCode(type, name);
1889 }
1890
1891
1892 Handle<Code> CallStubCompiler::CompileFastApiCall(
1893 const CallOptimization& optimization,
1894 Handle<Object> object,
1895 Handle<JSObject> holder,
1896 Handle<Cell> cell,
1897 Handle<JSFunction> function,
1898 Handle<String> name) {
1899 Counters* counters = isolate()->counters();
1900
1901 ASSERT(optimization.is_simple_api_call());
1902 // Bail out if object is a global object as we don't want to
1903 // repatch it to global receiver.
1904 if (object->IsGlobalObject()) return Handle<Code>::null();
1905 if (!cell.is_null()) return Handle<Code>::null();
1906 if (!object->IsJSObject()) return Handle<Code>::null();
1907 int depth = optimization.GetPrototypeDepthOfExpectedType(
1908 Handle<JSObject>::cast(object), holder);
1909 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
1910
1911 Label miss, miss_before_stack_reserved;
1912 GenerateNameCheck(name, &miss_before_stack_reserved);
1913
1914 // Get the receiver from the stack.
1915 const int argc = arguments().immediate();
1916 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1917
1918 // Check that the receiver isn't a smi.
1919 __ JumpIfSmi(r1, &miss_before_stack_reserved);
1920
1921 __ IncrementCounter(counters->call_const(), 1, r0, r3);
1922 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
1923
1924 ReserveSpaceForFastApiCall(masm(), r0);
1925
1926 // Check that the maps haven't changed and find a Holder as a side effect.
1927 CheckPrototypes(
1928 IC::CurrentTypeOf(object, isolate()),
1929 r1, holder, r0, r3, r4, name, depth, &miss);
1930
1931 GenerateFastApiDirectCall(masm(), optimization, argc, false);
1932
1933 __ bind(&miss);
1934 FreeSpaceForFastApiCall(masm());
1935
1936 HandlerFrontendFooter(&miss_before_stack_reserved);
1937
1938 // Return the generated code.
1939 return GetCode(function);
1940 }
1941
1942
1943 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1211 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1944 Label success; 1212 Label success;
1945 // Check that the object is a boolean. 1213 // Check that the object is a boolean.
1946 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1214 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1947 __ cmp(object, ip); 1215 __ cmp(object, ip);
1948 __ b(eq, &success); 1216 __ b(eq, &success);
1949 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1217 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1950 __ cmp(object, ip); 1218 __ cmp(object, ip);
1951 __ b(ne, miss); 1219 __ b(ne, miss);
1952 __ bind(&success); 1220 __ bind(&success);
1953 } 1221 }
1954 1222
1955 1223
1956 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1957 if (object->IsGlobalObject()) {
1958 const int argc = arguments().immediate();
1959 const int receiver_offset = argc * kPointerSize;
1960 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1961 __ str(r3, MemOperand(sp, receiver_offset));
1962 }
1963 }
1964
1965
1966 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1967 Handle<JSObject> holder,
1968 Handle<Name> name,
1969 CheckType check,
1970 Label* miss) {
1971 // ----------- S t a t e -------------
1972 // -- r2 : name
1973 // -- lr : return address
1974 // -----------------------------------
1975 GenerateNameCheck(name, miss);
1976
1977 Register reg = r0;
1978
1979 // Get the receiver from the stack
1980 const int argc = arguments().immediate();
1981 const int receiver_offset = argc * kPointerSize;
1982 __ ldr(r0, MemOperand(sp, receiver_offset));
1983
1984 // Check that the receiver isn't a smi.
1985 if (check != NUMBER_CHECK) {
1986 __ JumpIfSmi(r0, miss);
1987 }
1988
1989 // Make sure that it's okay not to patch the on stack receiver
1990 // unless we're doing a receiver map check.
1991 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1992 switch (check) {
1993 case RECEIVER_MAP_CHECK:
1994 __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
1995
1996 // Check that the maps haven't changed.
1997 reg = CheckPrototypes(
1998 IC::CurrentTypeOf(object, isolate()),
1999 reg, holder, r1, r3, r4, name, miss);
2000 break;
2001
2002 case STRING_CHECK: {
2003 // Check that the object is a string.
2004 __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
2005 __ b(ge, miss);
2006 // Check that the maps starting from the prototype haven't changed.
2007 GenerateDirectLoadGlobalFunctionPrototype(
2008 masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
2009 break;
2010 }
2011 case SYMBOL_CHECK: {
2012 // Check that the object is a symbol.
2013 __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
2014 __ b(ne, miss);
2015 // Check that the maps starting from the prototype haven't changed.
2016 GenerateDirectLoadGlobalFunctionPrototype(
2017 masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
2018 break;
2019 }
2020 case NUMBER_CHECK: {
2021 Label fast;
2022 // Check that the object is a smi or a heap number.
2023 __ JumpIfSmi(reg, &fast);
2024 __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
2025 __ b(ne, miss);
2026 __ bind(&fast);
2027 // Check that the maps starting from the prototype haven't changed.
2028 GenerateDirectLoadGlobalFunctionPrototype(
2029 masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
2030 break;
2031 }
2032 case BOOLEAN_CHECK: {
2033 GenerateBooleanCheck(reg, miss);
2034
2035 // Check that the maps starting from the prototype haven't changed.
2036 GenerateDirectLoadGlobalFunctionPrototype(
2037 masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
2038 break;
2039 }
2040 }
2041
2042 if (check != RECEIVER_MAP_CHECK) {
2043 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
2044 reg = CheckPrototypes(
2045 IC::CurrentTypeOf(prototype, isolate()),
2046 r1, holder, r1, r3, r4, name, miss);
2047 }
2048
2049 return reg;
2050 }
2051
2052
2053 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
2054 Register function,
2055 Label* miss) {
2056 ASSERT(function.is(r1));
2057 // Check that the function really is a function.
2058 GenerateFunctionCheck(function, r3, miss);
2059 PatchImplicitReceiver(object);
2060
2061 // Invoke the function.
2062 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, NullCallWrapper());
2063 }
2064
2065
2066 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2067 Handle<JSObject> holder,
2068 Handle<Name> name) {
2069 Label miss;
2070 GenerateNameCheck(name, &miss);
2071
2072 // Get the number of arguments.
2073 const int argc = arguments().immediate();
2074 LookupResult lookup(isolate());
2075 LookupPostInterceptor(holder, name, &lookup);
2076
2077 // Get the receiver from the stack.
2078 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2079
2080 CallInterceptorCompiler compiler(this, arguments(), r2);
2081 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0,
2082 &miss);
2083
2084 // Move returned value, the function to call, to r1.
2085 __ mov(r1, r0);
2086 // Restore receiver.
2087 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
2088
2089 GenerateJumpFunction(object, r1, &miss);
2090
2091 HandlerFrontendFooter(&miss);
2092
2093 // Return the generated code.
2094 return GetCode(Code::FAST, name);
2095 }
2096
2097
2098 Handle<Code> CallStubCompiler::CompileCallGlobal(
2099 Handle<JSObject> object,
2100 Handle<GlobalObject> holder,
2101 Handle<PropertyCell> cell,
2102 Handle<JSFunction> function,
2103 Handle<Name> name) {
2104 if (HasCustomCallGenerator(function)) {
2105 Handle<Code> code = CompileCustomCall(
2106 object, holder, cell, function, Handle<String>::cast(name),
2107 Code::NORMAL);
2108 // A null handle means bail out to the regular compiler code below.
2109 if (!code.is_null()) return code;
2110 }
2111
2112 Label miss;
2113 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2114 // Potentially loads a closure that matches the shared function info of the
2115 // function, rather than function.
2116 GenerateLoadFunctionFromCell(cell, function, &miss);
2117
2118 Counters* counters = isolate()->counters();
2119 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
2120 GenerateJumpFunction(object, r1, function);
2121 HandlerFrontendFooter(&miss);
2122
2123 // Return the generated code.
2124 return GetCode(Code::NORMAL, name);
2125 }
2126
2127
2128 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1224 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2129 Handle<JSObject> object, 1225 Handle<JSObject> object,
2130 Handle<JSObject> holder, 1226 Handle<JSObject> holder,
2131 Handle<Name> name, 1227 Handle<Name> name,
2132 Handle<ExecutableAccessorInfo> callback) { 1228 Handle<ExecutableAccessorInfo> callback) {
2133 Register holder_reg = HandlerFrontend( 1229 Register holder_reg = HandlerFrontend(
2134 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1230 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
2135 1231
2136 // Stub never generated for non-global objects that require access checks. 1232 // Stub never generated for non-global objects that require access checks.
2137 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1233 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2138 1234
2139 __ push(receiver()); // receiver 1235 __ push(receiver()); // receiver
2140 __ push(holder_reg); 1236 __ push(holder_reg);
2141 __ mov(ip, Operand(callback)); // callback info 1237 __ mov(ip, Operand(callback)); // callback info
2142 __ push(ip); 1238 __ push(ip);
2143 __ mov(ip, Operand(name)); 1239 __ mov(ip, Operand(name));
2144 __ Push(ip, value()); 1240 __ Push(ip, value());
2145 1241
2146 // Do tail-call to the runtime system. 1242 // Do tail-call to the runtime system.
2147 ExternalReference store_callback_property = 1243 ExternalReference store_callback_property =
2148 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 1244 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2149 __ TailCallExternalReference(store_callback_property, 5, 1); 1245 __ TailCallExternalReference(store_callback_property, 5, 1);
2150 1246
2151 // Return the generated code. 1247 // Return the generated code.
2152 return GetCode(kind(), Code::FAST, name); 1248 return GetCode(kind(), Code::FAST, name);
2153 } 1249 }
2154 1250
2155 1251
2156 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2157 Handle<JSObject> object,
2158 Handle<JSObject> holder,
2159 Handle<Name> name,
2160 const CallOptimization& call_optimization) {
2161 HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2162 receiver(), holder, name);
2163
2164 Register values[] = { value() };
2165 GenerateFastApiCall(
2166 masm(), call_optimization, receiver(), scratch3(), 1, values);
2167
2168 // Return the generated code.
2169 return GetCode(kind(), Code::FAST, name);
2170 }
2171
2172
2173 #undef __ 1252 #undef __
2174 #define __ ACCESS_MASM(masm) 1253 #define __ ACCESS_MASM(masm)
2175 1254
2176 1255
2177 void StoreStubCompiler::GenerateStoreViaSetter( 1256 void StoreStubCompiler::GenerateStoreViaSetter(
2178 MacroAssembler* masm, 1257 MacroAssembler* masm,
1258 Handle<HeapType> type,
2179 Handle<JSFunction> setter) { 1259 Handle<JSFunction> setter) {
2180 // ----------- S t a t e ------------- 1260 // ----------- S t a t e -------------
2181 // -- r0 : value 1261 // -- r0 : value
2182 // -- r1 : receiver 1262 // -- r1 : receiver
2183 // -- r2 : name 1263 // -- r2 : name
2184 // -- lr : return address 1264 // -- lr : return address
2185 // ----------------------------------- 1265 // -----------------------------------
2186 { 1266 {
2187 FrameScope scope(masm, StackFrame::INTERNAL); 1267 FrameScope scope(masm, StackFrame::INTERNAL);
1268 Register receiver = r1;
1269 Register value = r0;
2188 1270
2189 // Save value register, so we can restore it later. 1271 // Save value register, so we can restore it later.
2190 __ push(r0); 1272 __ push(value);
2191 1273
2192 if (!setter.is_null()) { 1274 if (!setter.is_null()) {
2193 // Call the JavaScript setter with receiver and value on the stack. 1275 // Call the JavaScript setter with receiver and value on the stack.
2194 __ Push(r1, r0); 1276 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
1277 // Swap in the global receiver.
1278 __ ldr(receiver,
1279 FieldMemOperand(
1280 receiver, JSGlobalObject::kGlobalReceiverOffset));
1281 }
1282 __ Push(receiver, value);
2195 ParameterCount actual(1); 1283 ParameterCount actual(1);
2196 ParameterCount expected(setter); 1284 ParameterCount expected(setter);
2197 __ InvokeFunction(setter, expected, actual, 1285 __ InvokeFunction(setter, expected, actual,
2198 CALL_FUNCTION, NullCallWrapper()); 1286 CALL_FUNCTION, NullCallWrapper());
2199 } else { 1287 } else {
2200 // If we generate a global code snippet for deoptimization only, remember 1288 // If we generate a global code snippet for deoptimization only, remember
2201 // the place to continue after deoptimization. 1289 // the place to continue after deoptimization.
2202 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 1290 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
2203 } 1291 }
2204 1292
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2243 1331
2244 // Handle store cache miss. 1332 // Handle store cache miss.
2245 __ bind(&miss); 1333 __ bind(&miss);
2246 TailCallBuiltin(masm(), MissBuiltin(kind())); 1334 TailCallBuiltin(masm(), MissBuiltin(kind()));
2247 1335
2248 // Return the generated code. 1336 // Return the generated code.
2249 return GetCode(kind(), Code::FAST, name); 1337 return GetCode(kind(), Code::FAST, name);
2250 } 1338 }
2251 1339
2252 1340
2253 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, 1341 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
2254 Handle<JSObject> last, 1342 Handle<JSObject> last,
2255 Handle<Name> name) { 1343 Handle<Name> name) {
2256 NonexistentHandlerFrontend(type, last, name); 1344 NonexistentHandlerFrontend(type, last, name);
2257 1345
2258 // Return undefined if maps of the full prototype chain are still the 1346 // Return undefined if maps of the full prototype chain are still the
2259 // same and no global property with this name contains a value. 1347 // same and no global property with this name contains a value.
2260 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 1348 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2261 __ Ret(); 1349 __ Ret();
2262 1350
2263 // Return the generated code. 1351 // Return the generated code.
(...skipping 27 matching lines...) Expand all
2291 static Register registers[] = { r2, r1, r0, r3, r4, r5 }; 1379 static Register registers[] = { r2, r1, r0, r3, r4, r5 };
2292 return registers; 1380 return registers;
2293 } 1381 }
2294 1382
2295 1383
2296 #undef __ 1384 #undef __
2297 #define __ ACCESS_MASM(masm) 1385 #define __ ACCESS_MASM(masm)
2298 1386
2299 1387
2300 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, 1388 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
1389 Handle<HeapType> type,
2301 Register receiver, 1390 Register receiver,
2302 Handle<JSFunction> getter) { 1391 Handle<JSFunction> getter) {
2303 // ----------- S t a t e ------------- 1392 // ----------- S t a t e -------------
2304 // -- r0 : receiver 1393 // -- r0 : receiver
2305 // -- r2 : name 1394 // -- r2 : name
2306 // -- lr : return address 1395 // -- lr : return address
2307 // ----------------------------------- 1396 // -----------------------------------
2308 { 1397 {
2309 FrameScope scope(masm, StackFrame::INTERNAL); 1398 FrameScope scope(masm, StackFrame::INTERNAL);
2310 1399
2311 if (!getter.is_null()) { 1400 if (!getter.is_null()) {
2312 // Call the JavaScript getter with the receiver on the stack. 1401 // Call the JavaScript getter with the receiver on the stack.
1402 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
1403 // Swap in the global receiver.
1404 __ ldr(receiver,
1405 FieldMemOperand(
1406 receiver, JSGlobalObject::kGlobalReceiverOffset));
1407 }
2313 __ push(receiver); 1408 __ push(receiver);
2314 ParameterCount actual(0); 1409 ParameterCount actual(0);
2315 ParameterCount expected(getter); 1410 ParameterCount expected(getter);
2316 __ InvokeFunction(getter, expected, actual, 1411 __ InvokeFunction(getter, expected, actual,
2317 CALL_FUNCTION, NullCallWrapper()); 1412 CALL_FUNCTION, NullCallWrapper());
2318 } else { 1413 } else {
2319 // If we generate a global code snippet for deoptimization only, remember 1414 // If we generate a global code snippet for deoptimization only, remember
2320 // the place to continue after deoptimization. 1415 // the place to continue after deoptimization.
2321 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 1416 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
2322 } 1417 }
2323 1418
2324 // Restore context register. 1419 // Restore context register.
2325 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1420 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2326 } 1421 }
2327 __ Ret(); 1422 __ Ret();
2328 } 1423 }
2329 1424
2330 1425
2331 #undef __ 1426 #undef __
2332 #define __ ACCESS_MASM(masm()) 1427 #define __ ACCESS_MASM(masm())
2333 1428
2334 1429
2335 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 1430 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
2336 Handle<Type> type, 1431 Handle<HeapType> type,
2337 Handle<GlobalObject> global, 1432 Handle<GlobalObject> global,
2338 Handle<PropertyCell> cell, 1433 Handle<PropertyCell> cell,
2339 Handle<Name> name, 1434 Handle<Name> name,
2340 bool is_dont_delete) { 1435 bool is_dont_delete) {
2341 Label miss; 1436 Label miss;
2342
2343 HandlerFrontendHeader(type, receiver(), global, name, &miss); 1437 HandlerFrontendHeader(type, receiver(), global, name, &miss);
2344 1438
2345 // Get the value from the cell. 1439 // Get the value from the cell.
2346 __ mov(r3, Operand(cell)); 1440 __ mov(r3, Operand(cell));
2347 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); 1441 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
2348 1442
2349 // Check for deleted property if property can actually be deleted. 1443 // Check for deleted property if property can actually be deleted.
2350 if (!is_dont_delete) { 1444 if (!is_dont_delete) {
2351 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1445 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2352 __ cmp(r4, ip); 1446 __ cmp(r4, ip);
2353 __ b(eq, &miss); 1447 __ b(eq, &miss);
2354 } 1448 }
2355 1449
2356 HandlerFrontendFooter(name, &miss);
2357
2358 Counters* counters = isolate()->counters(); 1450 Counters* counters = isolate()->counters();
2359 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 1451 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
2360 __ mov(r0, r4); 1452 __ mov(r0, r4);
2361 __ Ret(); 1453 __ Ret();
2362 1454
1455 HandlerFrontendFooter(name, &miss);
1456
2363 // Return the generated code. 1457 // Return the generated code.
2364 return GetCode(kind(), Code::NORMAL, name); 1458 return GetCode(kind(), Code::NORMAL, name);
2365 } 1459 }
2366 1460
2367 1461
2368 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1462 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2369 TypeHandleList* types, 1463 TypeHandleList* types,
2370 CodeHandleList* handlers, 1464 CodeHandleList* handlers,
2371 Handle<Name> name, 1465 Handle<Name> name,
2372 Code::StubType type, 1466 Code::StubType type,
2373 IcCheckType check) { 1467 IcCheckType check) {
2374 Label miss; 1468 Label miss;
2375 1469
2376 if (check == PROPERTY && 1470 if (check == PROPERTY &&
2377 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { 1471 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
2378 __ cmp(this->name(), Operand(name)); 1472 __ cmp(this->name(), Operand(name));
2379 __ b(ne, &miss); 1473 __ b(ne, &miss);
2380 } 1474 }
2381 1475
2382 Label number_case; 1476 Label number_case;
2383 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 1477 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2384 __ JumpIfSmi(receiver(), smi_target); 1478 __ JumpIfSmi(receiver(), smi_target);
2385 1479
2386 Register map_reg = scratch1(); 1480 Register map_reg = scratch1();
2387 1481
2388 int receiver_count = types->length(); 1482 int receiver_count = types->length();
2389 int number_of_handled_maps = 0; 1483 int number_of_handled_maps = 0;
2390 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); 1484 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
2391 for (int current = 0; current < receiver_count; ++current) { 1485 for (int current = 0; current < receiver_count; ++current) {
2392 Handle<Type> type = types->at(current); 1486 Handle<HeapType> type = types->at(current);
2393 Handle<Map> map = IC::TypeToMap(*type, isolate()); 1487 Handle<Map> map = IC::TypeToMap(*type, isolate());
2394 if (!map->is_deprecated()) { 1488 if (!map->is_deprecated()) {
2395 number_of_handled_maps++; 1489 number_of_handled_maps++;
2396 __ mov(ip, Operand(map)); 1490 __ mov(ip, Operand(map));
2397 __ cmp(map_reg, ip); 1491 __ cmp(map_reg, ip);
2398 if (type->Is(Type::Number())) { 1492 if (type->Is(HeapType::Number())) {
2399 ASSERT(!number_case.is_unused()); 1493 ASSERT(!number_case.is_unused());
2400 __ bind(&number_case); 1494 __ bind(&number_case);
2401 } 1495 }
2402 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); 1496 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq);
2403 } 1497 }
2404 } 1498 }
2405 ASSERT(number_of_handled_maps != 0); 1499 ASSERT(number_of_handled_maps != 0);
2406 1500
2407 __ bind(&miss); 1501 __ bind(&miss);
2408 TailCallBuiltin(masm(), MissBuiltin(kind())); 1502 TailCallBuiltin(masm(), MissBuiltin(kind()));
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 // ----------------------------------- 1583 // -----------------------------------
2490 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1584 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2491 } 1585 }
2492 1586
2493 1587
2494 #undef __ 1588 #undef __
2495 1589
2496 } } // namespace v8::internal 1590 } } // namespace v8::internal
2497 1591
2498 #endif // V8_TARGET_ARCH_ARM 1592 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/array.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698