| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 726 Label* label, | 726 Label* label, |
| 727 Handle<Name> name) { | 727 Handle<Name> name) { |
| 728 if (!label->is_unused()) { | 728 if (!label->is_unused()) { |
| 729 __ bind(label); | 729 __ bind(label); |
| 730 __ li(this->name(), Operand(name)); | 730 __ li(this->name(), Operand(name)); |
| 731 } | 731 } |
| 732 } | 732 } |
| 733 | 733 |
| 734 | 734 |
| 735 static void GenerateCallFunction(MacroAssembler* masm, | |
| 736 Handle<Object> object, | |
| 737 const ParameterCount& arguments, | |
| 738 Label* miss, | |
| 739 Code::ExtraICState extra_ic_state) { | |
| 740 // ----------- S t a t e ------------- | |
| 741 // -- a0: receiver | |
| 742 // -- a1: function to call | |
| 743 // ----------------------------------- | |
| 744 // Check that the function really is a function. | |
| 745 __ JumpIfSmi(a1, miss); | |
| 746 __ GetObjectType(a1, a3, a3); | |
| 747 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | |
| 748 | |
| 749 // Patch the receiver on the stack with the global proxy if | |
| 750 // necessary. | |
| 751 if (object->IsGlobalObject()) { | |
| 752 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | |
| 753 __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); | |
| 754 } | |
| 755 | |
| 756 // Invoke the function. | |
| 757 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | |
| 758 ? CALL_AS_FUNCTION | |
| 759 : CALL_AS_METHOD; | |
| 760 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 761 } | |
| 762 | |
| 763 | |
| 764 static void PushInterceptorArguments(MacroAssembler* masm, | 735 static void PushInterceptorArguments(MacroAssembler* masm, |
| 765 Register receiver, | 736 Register receiver, |
| 766 Register holder, | 737 Register holder, |
| 767 Register name, | 738 Register name, |
| 768 Handle<JSObject> holder_obj) { | 739 Handle<JSObject> holder_obj) { |
| 769 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 740 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 770 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 741 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 771 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 742 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 772 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 743 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 773 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 744 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| 774 __ push(name); | 745 __ push(name); |
| 775 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 746 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 776 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 747 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 777 Register scratch = name; | 748 Register scratch = name; |
| 778 __ li(scratch, Operand(interceptor)); | 749 __ li(scratch, Operand(interceptor)); |
| 779 __ Push(scratch, receiver, holder); | 750 __ Push(scratch, receiver, holder); |
| 780 } | 751 } |
| 781 | 752 |
| 782 | 753 |
| 783 static void CompileCallLoadPropertyWithInterceptor( | 754 static void CompileCallLoadPropertyWithInterceptor( |
| 784 MacroAssembler* masm, | 755 MacroAssembler* masm, |
| 785 Register receiver, | 756 Register receiver, |
| 786 Register holder, | 757 Register holder, |
| 787 Register name, | 758 Register name, |
| 788 Handle<JSObject> holder_obj) { | 759 Handle<JSObject> holder_obj, |
| 760 IC::UtilityId id) { |
| 789 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 761 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 790 | 762 __ CallExternalReference( |
| 791 ExternalReference ref = | 763 ExternalReference(IC_Utility(id), masm->isolate()), |
| 792 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 764 StubCache::kInterceptorArgsLength); |
| 793 masm->isolate()); | |
| 794 __ PrepareCEntryArgs(StubCache::kInterceptorArgsLength); | |
| 795 __ PrepareCEntryFunction(ref); | |
| 796 | |
| 797 CEntryStub stub(1); | |
| 798 __ CallStub(&stub); | |
| 799 } | 765 } |
| 800 | 766 |
| 801 | 767 |
| 802 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 768 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 803 | 769 |
| 804 // Reserves space for the extra arguments to API function in the | 770 // Reserves space for the extra arguments to API function in the |
| 805 // caller's frame. | 771 // caller's frame. |
| 806 // | 772 // |
| 807 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. | 773 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
| 808 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 774 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 ASSERT(!receiver.is(scratch)); | 892 ASSERT(!receiver.is(scratch)); |
| 927 | 893 |
| 928 typedef FunctionCallbackArguments FCA; | 894 typedef FunctionCallbackArguments FCA; |
| 929 const int stack_space = kFastApiCallArguments + argc + 1; | 895 const int stack_space = kFastApiCallArguments + argc + 1; |
| 930 // Assign stack space for the call arguments. | 896 // Assign stack space for the call arguments. |
| 931 __ Subu(sp, sp, Operand(stack_space * kPointerSize)); | 897 __ Subu(sp, sp, Operand(stack_space * kPointerSize)); |
| 932 // Write holder to stack frame. | 898 // Write holder to stack frame. |
| 933 __ sw(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | 899 __ sw(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |
| 934 // Write receiver to stack frame. | 900 // Write receiver to stack frame. |
| 935 int index = stack_space - 1; | 901 int index = stack_space - 1; |
| 936 __ sw(receiver, MemOperand(sp, index * kPointerSize)); | 902 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); |
| 937 // Write the arguments to stack frame. | 903 // Write the arguments to stack frame. |
| 938 for (int i = 0; i < argc; i++) { | 904 for (int i = 0; i < argc; i++) { |
| 939 ASSERT(!receiver.is(values[i])); | 905 ASSERT(!receiver.is(values[i])); |
| 940 ASSERT(!scratch.is(values[i])); | 906 ASSERT(!scratch.is(values[i])); |
| 941 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); | 907 __ sw(values[i], MemOperand(sp, index-- * kPointerSize)); |
| 942 } | 908 } |
| 943 | 909 |
| 944 GenerateFastApiDirectCall(masm, optimization, argc, true); | 910 GenerateFastApiDirectCall(masm, optimization, argc, true); |
| 945 } | 911 } |
| 946 | 912 |
| 947 | 913 |
| 948 class CallInterceptorCompiler BASE_EMBEDDED { | 914 class CallInterceptorCompiler BASE_EMBEDDED { |
| 949 public: | 915 public: |
| 950 CallInterceptorCompiler(StubCompiler* stub_compiler, | 916 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 951 const ParameterCount& arguments, | 917 const ParameterCount& arguments, |
| 952 Register name, | 918 Register name) |
| 953 Code::ExtraICState extra_ic_state) | |
| 954 : stub_compiler_(stub_compiler), | 919 : stub_compiler_(stub_compiler), |
| 955 arguments_(arguments), | 920 arguments_(arguments), |
| 956 name_(name), | 921 name_(name) {} |
| 957 extra_ic_state_(extra_ic_state) {} | |
| 958 | 922 |
| 959 void Compile(MacroAssembler* masm, | 923 void Compile(MacroAssembler* masm, |
| 960 Handle<JSObject> object, | 924 Handle<JSObject> object, |
| 961 Handle<JSObject> holder, | 925 Handle<JSObject> holder, |
| 962 Handle<Name> name, | 926 Handle<Name> name, |
| 963 LookupResult* lookup, | 927 LookupResult* lookup, |
| 964 Register receiver, | 928 Register receiver, |
| 965 Register scratch1, | 929 Register scratch1, |
| 966 Register scratch2, | 930 Register scratch2, |
| 967 Register scratch3, | 931 Register scratch3, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | 982 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |
| 1019 scratch1, scratch2); | 983 scratch1, scratch2); |
| 1020 ReserveSpaceForFastApiCall(masm, scratch1); | 984 ReserveSpaceForFastApiCall(masm, scratch1); |
| 1021 } | 985 } |
| 1022 | 986 |
| 1023 // Check that the maps from receiver to interceptor's holder | 987 // Check that the maps from receiver to interceptor's holder |
| 1024 // haven't changed and thus we can invoke interceptor. | 988 // haven't changed and thus we can invoke interceptor. |
| 1025 Label miss_cleanup; | 989 Label miss_cleanup; |
| 1026 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 990 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 1027 Register holder = | 991 Register holder = |
| 1028 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 992 stub_compiler_->CheckPrototypes( |
| 1029 scratch1, scratch2, scratch3, | 993 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 1030 name, depth1, miss); | 994 interceptor_holder, scratch1, scratch2, scratch3, |
| 995 name, depth1, miss); |
| 1031 | 996 |
| 1032 // Invoke an interceptor and if it provides a value, | 997 // Invoke an interceptor and if it provides a value, |
| 1033 // branch to |regular_invoke|. | 998 // branch to |regular_invoke|. |
| 1034 Label regular_invoke; | 999 Label regular_invoke; |
| 1035 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 1000 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
| 1036 ®ular_invoke); | 1001 ®ular_invoke); |
| 1037 | 1002 |
| 1038 // Interceptor returned nothing for this property. Try to use cached | 1003 // Interceptor returned nothing for this property. Try to use cached |
| 1039 // constant function. | 1004 // constant function. |
| 1040 | 1005 |
| 1041 // Check that the maps from interceptor's holder to constant function's | 1006 // Check that the maps from interceptor's holder to constant function's |
| 1042 // holder haven't changed and thus we can use cached constant function. | 1007 // holder haven't changed and thus we can use cached constant function. |
| 1043 if (*interceptor_holder != lookup->holder()) { | 1008 if (*interceptor_holder != lookup->holder()) { |
| 1044 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 1009 stub_compiler_->CheckPrototypes( |
| 1045 Handle<JSObject>(lookup->holder()), | 1010 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, |
| 1046 scratch1, scratch2, scratch3, | 1011 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 1047 name, depth2, miss); | 1012 name, depth2, miss); |
| 1048 } else { | 1013 } else { |
| 1049 // CheckPrototypes has a side effect of fetching a 'holder' | 1014 // CheckPrototypes has a side effect of fetching a 'holder' |
| 1050 // for API (object which is instanceof for the signature). It's | 1015 // for API (object which is instanceof for the signature). It's |
| 1051 // safe to omit it here, as if present, it should be fetched | 1016 // safe to omit it here, as if present, it should be fetched |
| 1052 // by the previous CheckPrototypes. | 1017 // by the previous CheckPrototypes. |
| 1053 ASSERT(depth2 == kInvalidProtoDepth); | 1018 ASSERT(depth2 == kInvalidProtoDepth); |
| 1054 } | 1019 } |
| 1055 | 1020 |
| 1056 // Invoke function. | 1021 // Invoke function. |
| 1057 if (can_do_fast_api_call) { | 1022 if (can_do_fast_api_call) { |
| 1058 GenerateFastApiDirectCall( | 1023 GenerateFastApiDirectCall( |
| 1059 masm, optimization, arguments_.immediate(), false); | 1024 masm, optimization, arguments_.immediate(), false); |
| 1060 } else { | 1025 } else { |
| 1061 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 1062 ? CALL_AS_FUNCTION | |
| 1063 : CALL_AS_METHOD; | |
| 1064 Handle<JSFunction> function = optimization.constant_function(); | 1026 Handle<JSFunction> function = optimization.constant_function(); |
| 1065 ParameterCount expected(function); | 1027 stub_compiler_->GenerateJumpFunction(object, function); |
| 1066 __ InvokeFunction(function, expected, arguments_, | |
| 1067 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 1068 } | 1028 } |
| 1069 | 1029 |
| 1070 // Deferred code for fast API call case---clean preallocated space. | 1030 // Deferred code for fast API call case---clean preallocated space. |
| 1071 if (can_do_fast_api_call) { | 1031 if (can_do_fast_api_call) { |
| 1072 __ bind(&miss_cleanup); | 1032 __ bind(&miss_cleanup); |
| 1073 FreeSpaceForFastApiCall(masm); | 1033 FreeSpaceForFastApiCall(masm); |
| 1074 __ Branch(miss_label); | 1034 __ Branch(miss_label); |
| 1075 } | 1035 } |
| 1076 | 1036 |
| 1077 // Invoke a regular function. | 1037 // Invoke a regular function. |
| 1078 __ bind(®ular_invoke); | 1038 __ bind(®ular_invoke); |
| 1079 if (can_do_fast_api_call) { | 1039 if (can_do_fast_api_call) { |
| 1080 FreeSpaceForFastApiCall(masm); | 1040 FreeSpaceForFastApiCall(masm); |
| 1081 } | 1041 } |
| 1082 } | 1042 } |
| 1083 | 1043 |
| 1084 void CompileRegular(MacroAssembler* masm, | 1044 void CompileRegular(MacroAssembler* masm, |
| 1085 Handle<JSObject> object, | 1045 Handle<JSObject> object, |
| 1086 Register receiver, | 1046 Register receiver, |
| 1087 Register scratch1, | 1047 Register scratch1, |
| 1088 Register scratch2, | 1048 Register scratch2, |
| 1089 Register scratch3, | 1049 Register scratch3, |
| 1090 Handle<Name> name, | 1050 Handle<Name> name, |
| 1091 Handle<JSObject> interceptor_holder, | 1051 Handle<JSObject> interceptor_holder, |
| 1092 Label* miss_label) { | 1052 Label* miss_label) { |
| 1093 Register holder = | 1053 Register holder = |
| 1094 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 1054 stub_compiler_->CheckPrototypes( |
| 1095 scratch1, scratch2, scratch3, | 1055 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 1096 name, miss_label); | 1056 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 1097 | 1057 |
| 1098 // Call a runtime function to load the interceptor property. | 1058 // Call a runtime function to load the interceptor property. |
| 1099 FrameScope scope(masm, StackFrame::INTERNAL); | 1059 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1100 // Save the name_ register across the call. | 1060 // Save the name_ register across the call. |
| 1101 __ push(name_); | 1061 __ push(name_); |
| 1102 | 1062 |
| 1103 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 1063 CompileCallLoadPropertyWithInterceptor( |
| 1064 masm, receiver, holder, name_, interceptor_holder, |
| 1065 IC::kLoadPropertyWithInterceptorForCall); |
| 1104 | 1066 |
| 1105 __ CallExternalReference( | |
| 1106 ExternalReference( | |
| 1107 IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | |
| 1108 masm->isolate()), | |
| 1109 StubCache::kInterceptorArgsLength); | |
| 1110 // Restore the name_ register. | 1067 // Restore the name_ register. |
| 1111 __ pop(name_); | 1068 __ pop(name_); |
| 1112 // Leave the internal frame. | 1069 // Leave the internal frame. |
| 1113 } | 1070 } |
| 1114 | 1071 |
| 1115 void LoadWithInterceptor(MacroAssembler* masm, | 1072 void LoadWithInterceptor(MacroAssembler* masm, |
| 1116 Register receiver, | 1073 Register receiver, |
| 1117 Register holder, | 1074 Register holder, |
| 1118 Handle<JSObject> holder_obj, | 1075 Handle<JSObject> holder_obj, |
| 1119 Register scratch, | 1076 Register scratch, |
| 1120 Label* interceptor_succeeded) { | 1077 Label* interceptor_succeeded) { |
| 1121 { | 1078 { |
| 1122 FrameScope scope(masm, StackFrame::INTERNAL); | 1079 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1123 | 1080 |
| 1124 __ Push(holder, name_); | 1081 __ Push(receiver, holder, name_); |
| 1125 CompileCallLoadPropertyWithInterceptor(masm, | 1082 CompileCallLoadPropertyWithInterceptor( |
| 1126 receiver, | 1083 masm, receiver, holder, name_, holder_obj, |
| 1127 holder, | 1084 IC::kLoadPropertyWithInterceptorOnly); |
| 1128 name_, | 1085 __ pop(name_); |
| 1129 holder_obj); | 1086 __ pop(holder); |
| 1130 __ pop(name_); // Restore the name. | 1087 __ pop(receiver); |
| 1131 __ pop(receiver); // Restore the holder. | |
| 1132 } | 1088 } |
| 1133 // If interceptor returns no-result sentinel, call the constant function. | 1089 // If interceptor returns no-result sentinel, call the constant function. |
| 1134 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1090 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1135 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); | 1091 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); |
| 1136 } | 1092 } |
| 1137 | 1093 |
| 1138 StubCompiler* stub_compiler_; | 1094 CallStubCompiler* stub_compiler_; |
| 1139 const ParameterCount& arguments_; | 1095 const ParameterCount& arguments_; |
| 1140 Register name_; | 1096 Register name_; |
| 1141 Code::ExtraICState extra_ic_state_; | |
| 1142 }; | 1097 }; |
| 1143 | 1098 |
| 1144 | 1099 |
| 1145 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1146 Handle<JSObject> object, | |
| 1147 Handle<JSObject> holder, | |
| 1148 Handle<Name> name, | |
| 1149 Register scratch, | |
| 1150 Label* miss) { | |
| 1151 Handle<JSObject> current = object; | |
| 1152 while (!current.is_identical_to(holder)) { | |
| 1153 if (current->IsJSGlobalObject()) { | |
| 1154 GenerateCheckPropertyCell(masm, | |
| 1155 Handle<JSGlobalObject>::cast(current), | |
| 1156 name, | |
| 1157 scratch, | |
| 1158 miss); | |
| 1159 } | |
| 1160 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1161 } | |
| 1162 } | |
| 1163 | |
| 1164 | |
| 1165 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1100 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1166 __ Jump(code, RelocInfo::CODE_TARGET); | 1101 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1167 } | 1102 } |
| 1168 | 1103 |
| 1169 | 1104 |
| 1170 #undef __ | 1105 #undef __ |
| 1171 #define __ ACCESS_MASM(masm()) | 1106 #define __ ACCESS_MASM(masm()) |
| 1172 | 1107 |
| 1173 | 1108 |
| 1174 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1109 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1175 Register object_reg, | 1110 Register object_reg, |
| 1176 Handle<JSObject> holder, | 1111 Handle<JSObject> holder, |
| 1177 Register holder_reg, | 1112 Register holder_reg, |
| 1178 Register scratch1, | 1113 Register scratch1, |
| 1179 Register scratch2, | 1114 Register scratch2, |
| 1180 Handle<Name> name, | 1115 Handle<Name> name, |
| 1181 int save_at_depth, | 1116 int save_at_depth, |
| 1182 Label* miss, | 1117 Label* miss, |
| 1183 PrototypeCheckType check) { | 1118 PrototypeCheckType check) { |
| 1119 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1184 // Make sure that the type feedback oracle harvests the receiver map. | 1120 // Make sure that the type feedback oracle harvests the receiver map. |
| 1185 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1121 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1186 __ li(scratch1, Operand(Handle<Map>(object->map()))); | 1122 __ li(scratch1, Operand(receiver_map)); |
| 1187 | 1123 |
| 1188 Handle<JSObject> first = object; | |
| 1189 // Make sure there's no overlap between holder and object registers. | 1124 // Make sure there's no overlap between holder and object registers. |
| 1190 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1125 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1191 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1126 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1192 && !scratch2.is(scratch1)); | 1127 && !scratch2.is(scratch1)); |
| 1193 | 1128 |
| 1194 // Keep track of the current object in register reg. | 1129 // Keep track of the current object in register reg. |
| 1195 Register reg = object_reg; | 1130 Register reg = object_reg; |
| 1196 int depth = 0; | 1131 int depth = 0; |
| 1197 | 1132 |
| 1198 typedef FunctionCallbackArguments FCA; | 1133 typedef FunctionCallbackArguments FCA; |
| 1199 if (save_at_depth == depth) { | 1134 if (save_at_depth == depth) { |
| 1200 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | 1135 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |
| 1201 } | 1136 } |
| 1202 | 1137 |
| 1203 // Check the maps in the prototype chain. | 1138 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1204 // Traverse the prototype chain from the object and do map checks. | 1139 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1205 Handle<JSObject> current = object; | 1140 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1206 while (!current.is_identical_to(holder)) { | 1141 Handle<Map> current_map = receiver_map; |
| 1142 Handle<Map> holder_map(holder->map()); |
| 1143 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1144 // fast and global objects or do negative lookup for normal objects. |
| 1145 while (!current_map.is_identical_to(holder_map)) { |
| 1207 ++depth; | 1146 ++depth; |
| 1208 | 1147 |
| 1209 // Only global objects and objects that do not require access | 1148 // Only global objects and objects that do not require access |
| 1210 // checks are allowed in stubs. | 1149 // checks are allowed in stubs. |
| 1211 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1150 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1151 !current_map->is_access_check_needed()); |
| 1212 | 1152 |
| 1213 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1153 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1214 if (!current->HasFastProperties() && | 1154 if (current_map->is_dictionary_map() && |
| 1215 !current->IsJSGlobalObject() && | 1155 !current_map->IsJSGlobalObjectMap() && |
| 1216 !current->IsJSGlobalProxy()) { | 1156 !current_map->IsJSGlobalProxyMap()) { |
| 1217 if (!name->IsUniqueName()) { | 1157 if (!name->IsUniqueName()) { |
| 1218 ASSERT(name->IsString()); | 1158 ASSERT(name->IsString()); |
| 1219 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1159 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1220 } | 1160 } |
| 1221 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1161 ASSERT(current.is_null() || |
| 1162 current->property_dictionary()->FindEntry(*name) == |
| 1222 NameDictionary::kNotFound); | 1163 NameDictionary::kNotFound); |
| 1223 | 1164 |
| 1224 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1165 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1225 scratch1, scratch2); | 1166 scratch1, scratch2); |
| 1226 | 1167 |
| 1227 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1168 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1228 reg = holder_reg; // From now on the object will be in holder_reg. | 1169 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1229 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1170 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 1230 } else { | 1171 } else { |
| 1231 Register map_reg = scratch1; | 1172 Register map_reg = scratch1; |
| 1232 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1173 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1233 Handle<Map> current_map(current->map()); | |
| 1234 // CheckMap implicitly loads the map of |reg| into |map_reg|. | 1174 // CheckMap implicitly loads the map of |reg| into |map_reg|. |
| 1235 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); | 1175 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1236 } else { | 1176 } else { |
| 1237 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1177 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1238 } | 1178 } |
| 1179 |
| 1239 // Check access rights to the global object. This has to happen after | 1180 // Check access rights to the global object. This has to happen after |
| 1240 // the map check so that we know that the object is actually a global | 1181 // the map check so that we know that the object is actually a global |
| 1241 // object. | 1182 // object. |
| 1242 if (current->IsJSGlobalProxy()) { | 1183 if (current_map->IsJSGlobalProxyMap()) { |
| 1243 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1184 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1185 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1186 GenerateCheckPropertyCell( |
| 1187 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1188 scratch2, miss); |
| 1244 } | 1189 } |
| 1190 |
| 1245 reg = holder_reg; // From now on the object will be in holder_reg. | 1191 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1246 | 1192 |
| 1247 if (heap()->InNewSpace(*prototype)) { | 1193 if (heap()->InNewSpace(*prototype)) { |
| 1248 // The prototype is in new space; we cannot store a reference to it | 1194 // The prototype is in new space; we cannot store a reference to it |
| 1249 // in the code. Load it from the map. | 1195 // in the code. Load it from the map. |
| 1250 __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 1196 __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| 1251 } else { | 1197 } else { |
| 1252 // The prototype is in old space; load it directly. | 1198 // The prototype is in old space; load it directly. |
| 1253 __ li(reg, Operand(prototype)); | 1199 __ li(reg, Operand(prototype)); |
| 1254 } | 1200 } |
| 1255 } | 1201 } |
| 1256 | 1202 |
| 1257 if (save_at_depth == depth) { | 1203 if (save_at_depth == depth) { |
| 1258 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | 1204 __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |
| 1259 } | 1205 } |
| 1260 | 1206 |
| 1261 // Go to the next object in the prototype chain. | 1207 // Go to the next object in the prototype chain. |
| 1262 current = prototype; | 1208 current = prototype; |
| 1209 current_map = handle(current->map()); |
| 1263 } | 1210 } |
| 1264 | 1211 |
| 1265 // Log the check depth. | 1212 // Log the check depth. |
| 1266 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1213 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1267 | 1214 |
| 1268 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1215 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1269 // Check the holder map. | 1216 // Check the holder map. |
| 1270 __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss, | 1217 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |
| 1271 DONT_DO_SMI_CHECK); | |
| 1272 } | 1218 } |
| 1273 | 1219 |
| 1274 // Perform security check for access to the global object. | 1220 // Perform security check for access to the global object. |
| 1275 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1221 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1276 if (holder->IsJSGlobalProxy()) { | 1222 !current_map->is_access_check_needed()); |
| 1223 if (current_map->IsJSGlobalProxyMap()) { |
| 1277 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1224 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1278 } | 1225 } |
| 1279 | 1226 |
| 1280 // If we've skipped any global objects, it's not enough to verify that | |
| 1281 // their maps haven't changed. We also need to check that the property | |
| 1282 // cell for the property is still empty. | |
| 1283 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1284 | |
| 1285 // Return the register containing the holder. | 1227 // Return the register containing the holder. |
| 1286 return reg; | 1228 return reg; |
| 1287 } | 1229 } |
| 1288 | 1230 |
| 1289 | 1231 |
| 1290 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1232 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1291 if (!miss->is_unused()) { | 1233 if (!miss->is_unused()) { |
| 1292 Label success; | 1234 Label success; |
| 1293 __ Branch(&success); | 1235 __ Branch(&success); |
| 1294 __ bind(miss); | 1236 __ bind(miss); |
| 1295 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1237 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1296 __ bind(&success); | 1238 __ bind(&success); |
| 1297 } | 1239 } |
| 1298 } | 1240 } |
| 1299 | 1241 |
| 1300 | 1242 |
| 1301 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1243 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1302 if (!miss->is_unused()) { | 1244 if (!miss->is_unused()) { |
| 1303 Label success; | 1245 Label success; |
| 1304 __ Branch(&success); | 1246 __ Branch(&success); |
| 1305 GenerateRestoreName(masm(), miss, name); | 1247 GenerateRestoreName(masm(), miss, name); |
| 1306 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1248 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1307 __ bind(&success); | 1249 __ bind(&success); |
| 1308 } | 1250 } |
| 1309 } | 1251 } |
| 1310 | 1252 |
| 1311 | 1253 |
| 1312 Register LoadStubCompiler::CallbackHandlerFrontend( | 1254 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1313 Handle<Object> object, | 1255 Handle<Type> type, |
| 1314 Register object_reg, | 1256 Register object_reg, |
| 1315 Handle<JSObject> holder, | 1257 Handle<JSObject> holder, |
| 1316 Handle<Name> name, | 1258 Handle<Name> name, |
| 1317 Handle<Object> callback) { | 1259 Handle<Object> callback) { |
| 1318 Label miss; | 1260 Label miss; |
| 1319 | 1261 |
| 1320 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1262 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1321 | 1263 |
| 1322 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1264 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1323 ASSERT(!reg.is(scratch2())); | 1265 ASSERT(!reg.is(scratch2())); |
| 1324 ASSERT(!reg.is(scratch3())); | 1266 ASSERT(!reg.is(scratch3())); |
| 1325 ASSERT(!reg.is(scratch4())); | 1267 ASSERT(!reg.is(scratch4())); |
| 1326 | 1268 |
| 1327 // Load the properties dictionary. | 1269 // Load the properties dictionary. |
| 1328 Register dictionary = scratch4(); | 1270 Register dictionary = scratch4(); |
| 1329 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 1271 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 1330 | 1272 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 { | 1443 { |
| 1502 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1444 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1503 if (must_preserve_receiver_reg) { | 1445 if (must_preserve_receiver_reg) { |
| 1504 __ Push(receiver(), holder_reg, this->name()); | 1446 __ Push(receiver(), holder_reg, this->name()); |
| 1505 } else { | 1447 } else { |
| 1506 __ Push(holder_reg, this->name()); | 1448 __ Push(holder_reg, this->name()); |
| 1507 } | 1449 } |
| 1508 // Invoke an interceptor. Note: map checks from receiver to | 1450 // Invoke an interceptor. Note: map checks from receiver to |
| 1509 // interceptor's holder has been compiled before (see a caller | 1451 // interceptor's holder has been compiled before (see a caller |
| 1510 // of this method). | 1452 // of this method). |
| 1511 CompileCallLoadPropertyWithInterceptor(masm(), | 1453 CompileCallLoadPropertyWithInterceptor( |
| 1512 receiver(), | 1454 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| 1513 holder_reg, | 1455 IC::kLoadPropertyWithInterceptorOnly); |
| 1514 this->name(), | 1456 |
| 1515 interceptor_holder); | |
| 1516 // Check if interceptor provided a value for property. If it's | 1457 // Check if interceptor provided a value for property. If it's |
| 1517 // the case, return immediately. | 1458 // the case, return immediately. |
| 1518 Label interceptor_failed; | 1459 Label interceptor_failed; |
| 1519 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 1460 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
| 1520 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); | 1461 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); |
| 1521 frame_scope.GenerateLeaveFrame(); | 1462 frame_scope.GenerateLeaveFrame(); |
| 1522 __ Ret(); | 1463 __ Ret(); |
| 1523 | 1464 |
| 1524 __ bind(&interceptor_failed); | 1465 __ bind(&interceptor_failed); |
| 1525 __ pop(this->name()); | 1466 __ pop(this->name()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1543 } | 1484 } |
| 1544 | 1485 |
| 1545 | 1486 |
| 1546 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1487 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1547 if (kind_ == Code::KEYED_CALL_IC) { | 1488 if (kind_ == Code::KEYED_CALL_IC) { |
| 1548 __ Branch(miss, ne, a2, Operand(name)); | 1489 __ Branch(miss, ne, a2, Operand(name)); |
| 1549 } | 1490 } |
| 1550 } | 1491 } |
| 1551 | 1492 |
| 1552 | 1493 |
| 1553 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | 1494 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1554 Handle<JSObject> holder, | 1495 Register scratch, |
| 1555 Handle<Name> name, | 1496 Label* miss) { |
| 1556 Label* miss) { | 1497 __ JumpIfSmi(function, miss); |
| 1557 ASSERT(holder->IsGlobalObject()); | 1498 __ GetObjectType(function, scratch, scratch); |
| 1558 | 1499 __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); |
| 1559 // Get the number of arguments. | |
| 1560 const int argc = arguments().immediate(); | |
| 1561 | |
| 1562 // Get the receiver from the stack. | |
| 1563 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
| 1564 | |
| 1565 // Check that the maps haven't changed. | |
| 1566 __ JumpIfSmi(a0, miss); | |
| 1567 CheckPrototypes(object, a0, holder, a3, a1, t0, name, miss); | |
| 1568 } | 1500 } |
| 1569 | 1501 |
| 1570 | 1502 |
| 1571 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1503 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1572 Handle<Cell> cell, | 1504 Handle<Cell> cell, |
| 1573 Handle<JSFunction> function, | 1505 Handle<JSFunction> function, |
| 1574 Label* miss) { | 1506 Label* miss) { |
| 1575 // Get the value from the cell. | 1507 // Get the value from the cell. |
| 1576 __ li(a3, Operand(cell)); | 1508 __ li(a3, Operand(cell)); |
| 1577 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); | 1509 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); |
| 1578 | 1510 |
| 1579 // Check that the cell contains the same function. | 1511 // Check that the cell contains the same function. |
| 1580 if (heap()->InNewSpace(*function)) { | 1512 if (heap()->InNewSpace(*function)) { |
| 1581 // We can't embed a pointer to a function in new space so we have | 1513 // We can't embed a pointer to a function in new space so we have |
| 1582 // to verify that the shared function info is unchanged. This has | 1514 // to verify that the shared function info is unchanged. This has |
| 1583 // the nice side effect that multiple closures based on the same | 1515 // the nice side effect that multiple closures based on the same |
| 1584 // function can all use this call IC. Before we load through the | 1516 // function can all use this call IC. Before we load through the |
| 1585 // function, we have to verify that it still is a function. | 1517 // function, we have to verify that it still is a function. |
| 1586 __ JumpIfSmi(a1, miss); | 1518 GenerateFunctionCheck(a1, a3, miss); |
| 1587 __ GetObjectType(a1, a3, a3); | |
| 1588 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | |
| 1589 | 1519 |
| 1590 // Check the shared function info. Make sure it hasn't changed. | 1520 // Check the shared function info. Make sure it hasn't changed. |
| 1591 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); | 1521 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); |
| 1592 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1522 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1593 __ Branch(miss, ne, t0, Operand(a3)); | 1523 __ Branch(miss, ne, t0, Operand(a3)); |
| 1594 } else { | 1524 } else { |
| 1595 __ Branch(miss, ne, a1, Operand(function)); | 1525 __ Branch(miss, ne, a1, Operand(function)); |
| 1596 } | 1526 } |
| 1597 } | 1527 } |
| 1598 | 1528 |
| 1599 | 1529 |
| 1600 void CallStubCompiler::GenerateMissBranch() { | 1530 void CallStubCompiler::GenerateMissBranch() { |
| 1601 Handle<Code> code = | 1531 Handle<Code> code = |
| 1602 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1532 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1603 kind_, | 1533 kind_, |
| 1604 extra_state_); | 1534 extra_state()); |
| 1605 __ Jump(code, RelocInfo::CODE_TARGET); | 1535 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1606 } | 1536 } |
| 1607 | 1537 |
| 1608 | 1538 |
| 1609 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1539 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1610 Handle<JSObject> holder, | 1540 Handle<JSObject> holder, |
| 1611 PropertyIndex index, | 1541 PropertyIndex index, |
| 1612 Handle<Name> name) { | 1542 Handle<Name> name) { |
| 1613 // ----------- S t a t e ------------- | |
| 1614 // -- a2 : name | |
| 1615 // -- ra : return address | |
| 1616 // ----------------------------------- | |
| 1617 Label miss; | 1543 Label miss; |
| 1618 | 1544 |
| 1619 GenerateNameCheck(name, &miss); | 1545 Register reg = HandlerFrontendHeader( |
| 1620 | 1546 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1621 const int argc = arguments().immediate(); | |
| 1622 | |
| 1623 // Get the receiver of the function from the stack into a0. | |
| 1624 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
| 1625 // Check that the receiver isn't a smi. | |
| 1626 __ JumpIfSmi(a0, &miss, t0); | |
| 1627 | |
| 1628 // Do the right check and compute the holder register. | |
| 1629 Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); | |
| 1630 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), | 1547 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), |
| 1631 index.translate(holder), Representation::Tagged()); | 1548 index.translate(holder), Representation::Tagged()); |
| 1549 GenerateJumpFunction(object, a1, &miss); |
| 1632 | 1550 |
| 1633 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 1551 HandlerFrontendFooter(&miss); |
| 1634 | |
| 1635 // Handle call cache miss. | |
| 1636 __ bind(&miss); | |
| 1637 GenerateMissBranch(); | |
| 1638 | 1552 |
| 1639 // Return the generated code. | 1553 // Return the generated code. |
| 1640 return GetCode(Code::FAST, name); | 1554 return GetCode(Code::FAST, name); |
| 1641 } | 1555 } |
| 1642 | 1556 |
| 1643 | 1557 |
| 1644 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1558 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1645 Handle<Object> object, | 1559 Handle<Object> object, |
| 1646 Handle<JSObject> holder, | 1560 Handle<JSObject> holder, |
| 1647 Handle<Cell> cell, | 1561 Handle<Cell> cell, |
| 1648 Handle<JSFunction> function, | 1562 Handle<JSFunction> function, |
| 1649 Handle<String> name, | 1563 Handle<String> name, |
| 1650 Code::StubType type) { | 1564 Code::StubType type) { |
| 1651 Label miss; | 1565 Label miss; |
| 1652 | 1566 |
| 1653 // Check that function is still array. | 1567 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1654 const int argc = arguments().immediate(); | 1568 if (!cell.is_null()) { |
| 1655 GenerateNameCheck(name, &miss); | |
| 1656 Register receiver = a1; | |
| 1657 | |
| 1658 if (cell.is_null()) { | |
| 1659 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1660 | |
| 1661 // Check that the receiver isn't a smi. | |
| 1662 __ JumpIfSmi(receiver, &miss); | |
| 1663 | |
| 1664 // Check that the maps haven't changed. | |
| 1665 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, a0, | |
| 1666 t0, name, &miss); | |
| 1667 } else { | |
| 1668 ASSERT(cell->value() == *function); | 1569 ASSERT(cell->value() == *function); |
| 1669 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1670 &miss); | |
| 1671 GenerateLoadFunctionFromCell(cell, function, &miss); | 1570 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1672 } | 1571 } |
| 1673 | 1572 |
| 1674 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1573 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1675 site->SetElementsKind(GetInitialFastElementsKind()); | 1574 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1676 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1575 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1576 const int argc = arguments().immediate(); |
| 1677 __ li(a0, Operand(argc)); | 1577 __ li(a0, Operand(argc)); |
| 1678 __ li(a2, Operand(site_feedback_cell)); | 1578 __ li(a2, Operand(site_feedback_cell)); |
| 1679 __ li(a1, Operand(function)); | 1579 __ li(a1, Operand(function)); |
| 1680 | 1580 |
| 1681 ArrayConstructorStub stub(isolate()); | 1581 ArrayConstructorStub stub(isolate()); |
| 1682 __ TailCallStub(&stub); | 1582 __ TailCallStub(&stub); |
| 1683 | 1583 |
| 1684 __ bind(&miss); | 1584 HandlerFrontendFooter(&miss); |
| 1685 GenerateMissBranch(); | |
| 1686 | 1585 |
| 1687 // Return the generated code. | 1586 // Return the generated code. |
| 1688 return GetCode(type, name); | 1587 return GetCode(type, name); |
| 1689 } | 1588 } |
| 1690 | 1589 |
| 1691 | 1590 |
| 1692 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1591 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1693 Handle<Object> object, | 1592 Handle<Object> object, |
| 1694 Handle<JSObject> holder, | 1593 Handle<JSObject> holder, |
| 1695 Handle<Cell> cell, | 1594 Handle<Cell> cell, |
| 1696 Handle<JSFunction> function, | 1595 Handle<JSFunction> function, |
| 1697 Handle<String> name, | 1596 Handle<String> name, |
| 1698 Code::StubType type) { | 1597 Code::StubType type) { |
| 1699 // ----------- S t a t e ------------- | 1598 // If object is not an array or is observed or sealed, bail out to regular |
| 1700 // -- a2 : name | 1599 // call. |
| 1701 // -- ra : return address | |
| 1702 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 1703 // -- ... | |
| 1704 // -- sp[argc * 4] : receiver | |
| 1705 // ----------------------------------- | |
| 1706 | |
| 1707 // If object is not an array or is observed, bail out to regular call. | |
| 1708 if (!object->IsJSArray() || | 1600 if (!object->IsJSArray() || |
| 1709 !cell.is_null() || | 1601 !cell.is_null() || |
| 1710 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1602 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1603 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1711 return Handle<Code>::null(); | 1604 return Handle<Code>::null(); |
| 1712 } | 1605 } |
| 1713 | 1606 |
| 1714 Label miss; | 1607 Label miss; |
| 1608 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1609 Register receiver = a0; |
| 1610 Register scratch = a1; |
| 1715 | 1611 |
| 1716 GenerateNameCheck(name, &miss); | |
| 1717 | |
| 1718 Register receiver = a1; | |
| 1719 | |
| 1720 // Get the receiver from the stack. | |
| 1721 const int argc = arguments().immediate(); | 1612 const int argc = arguments().immediate(); |
| 1722 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1723 | |
| 1724 // Check that the receiver isn't a smi. | |
| 1725 __ JumpIfSmi(receiver, &miss); | |
| 1726 | |
| 1727 // Check that the maps haven't changed. | |
| 1728 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, v0, t0, | |
| 1729 name, &miss); | |
| 1730 | 1613 |
| 1731 if (argc == 0) { | 1614 if (argc == 0) { |
| 1732 // Nothing to do, just return the length. | 1615 // Nothing to do, just return the length. |
| 1733 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1616 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1734 __ DropAndRet(argc + 1); | 1617 __ DropAndRet(argc + 1); |
| 1735 } else { | 1618 } else { |
| 1736 Label call_builtin; | 1619 Label call_builtin; |
| 1737 if (argc == 1) { // Otherwise fall through to call the builtin. | 1620 if (argc == 1) { // Otherwise fall through to call the builtin. |
| 1738 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1621 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1739 | 1622 |
| 1740 Register elements = t2; | 1623 Register elements = t2; |
| 1741 Register end_elements = t1; | 1624 Register end_elements = t1; |
| 1742 // Get the elements array of the object. | 1625 // Get the elements array of the object. |
| 1743 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1626 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1744 | 1627 |
| 1745 // Check that the elements are in fast mode and writable. | 1628 // Check that the elements are in fast mode and writable. |
| 1746 __ CheckMap(elements, | 1629 __ CheckMap(elements, |
| 1747 v0, | 1630 scratch, |
| 1748 Heap::kFixedArrayMapRootIndex, | 1631 Heap::kFixedArrayMapRootIndex, |
| 1749 &check_double, | 1632 &check_double, |
| 1750 DONT_DO_SMI_CHECK); | 1633 DONT_DO_SMI_CHECK); |
| 1751 | 1634 |
| 1752 // Get the array's length into v0 and calculate new length. | 1635 // Get the array's length into scratch and calculate new length. |
| 1753 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1636 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1754 STATIC_ASSERT(kSmiTagSize == 1); | 1637 STATIC_ASSERT(kSmiTagSize == 1); |
| 1755 STATIC_ASSERT(kSmiTag == 0); | 1638 STATIC_ASSERT(kSmiTag == 0); |
| 1756 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1639 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
| 1757 | 1640 |
| 1758 // Get the elements' length. | 1641 // Get the elements' length. |
| 1759 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1642 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1760 | 1643 |
| 1761 // Check if we could survive without allocation. | 1644 // Check if we could survive without allocation. |
| 1762 __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); | 1645 __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0)); |
| 1763 | 1646 |
| 1764 // Check if value is a smi. | 1647 // Check if value is a smi. |
| 1765 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1648 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1766 __ JumpIfNotSmi(t0, &with_write_barrier); | 1649 __ JumpIfNotSmi(t0, &with_write_barrier); |
| 1767 | 1650 |
| 1768 // Save new length. | 1651 // Save new length. |
| 1769 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1652 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1770 | 1653 |
| 1771 // Store the value. | 1654 // Store the value. |
| 1772 // We may need a register containing the address end_elements below, | 1655 // We may need a register containing the address end_elements below, |
| 1773 // so write back the value in end_elements. | 1656 // so write back the value in end_elements. |
| 1774 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1657 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1775 __ Addu(end_elements, elements, end_elements); | 1658 __ Addu(end_elements, elements, end_elements); |
| 1776 const int kEndElementsOffset = | 1659 const int kEndElementsOffset = |
| 1777 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1660 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
| 1778 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1661 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1779 __ sw(t0, MemOperand(end_elements)); | 1662 __ sw(t0, MemOperand(end_elements)); |
| 1780 | 1663 |
| 1781 // Check for a smi. | 1664 // Check for a smi. |
| 1665 __ mov(v0, scratch); |
| 1782 __ DropAndRet(argc + 1); | 1666 __ DropAndRet(argc + 1); |
| 1783 | 1667 |
| 1784 __ bind(&check_double); | 1668 __ bind(&check_double); |
| 1785 | 1669 |
| 1786 // Check that the elements are in fast mode and writable. | 1670 // Check that the elements are in fast mode and writable. |
| 1787 __ CheckMap(elements, | 1671 __ CheckMap(elements, |
| 1788 a0, | 1672 scratch, |
| 1789 Heap::kFixedDoubleArrayMapRootIndex, | 1673 Heap::kFixedDoubleArrayMapRootIndex, |
| 1790 &call_builtin, | 1674 &call_builtin, |
| 1791 DONT_DO_SMI_CHECK); | 1675 DONT_DO_SMI_CHECK); |
| 1792 | 1676 |
| 1793 // Get the array's length into v0 and calculate new length. | 1677 // Get the array's length into scratch and calculate new length. |
| 1794 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1678 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1795 STATIC_ASSERT(kSmiTagSize == 1); | 1679 STATIC_ASSERT(kSmiTagSize == 1); |
| 1796 STATIC_ASSERT(kSmiTag == 0); | 1680 STATIC_ASSERT(kSmiTag == 0); |
| 1797 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1681 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
| 1798 | 1682 |
| 1799 // Get the elements' length. | 1683 // Get the elements' length. |
| 1800 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1684 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1801 | 1685 |
| 1802 // Check if we could survive without allocation. | 1686 // Check if we could survive without allocation. |
| 1803 __ Branch(&call_builtin, gt, v0, Operand(t0)); | 1687 __ Branch(&call_builtin, gt, scratch, Operand(t0)); |
| 1804 | 1688 |
| 1805 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1689 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1806 __ StoreNumberToDoubleElements( | 1690 __ StoreNumberToDoubleElements( |
| 1807 t0, v0, elements, a3, t1, a2, | 1691 t0, scratch, elements, a3, t1, a2, |
| 1808 &call_builtin, argc * kDoubleSize); | 1692 &call_builtin, argc * kDoubleSize); |
| 1809 | 1693 |
| 1810 // Save new length. | 1694 // Save new length. |
| 1811 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1695 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1812 | 1696 |
| 1813 // Check for a smi. | 1697 __ mov(v0, scratch); |
| 1814 __ DropAndRet(argc + 1); | 1698 __ DropAndRet(argc + 1); |
| 1815 | 1699 |
| 1816 __ bind(&with_write_barrier); | 1700 __ bind(&with_write_barrier); |
| 1817 | 1701 |
| 1818 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1702 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1819 | 1703 |
| 1820 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | 1704 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
| 1821 Label fast_object, not_fast_object; | 1705 Label fast_object, not_fast_object; |
| 1822 __ CheckFastObjectElements(a3, t3, ¬_fast_object); | 1706 __ CheckFastObjectElements(a3, t3, ¬_fast_object); |
| 1823 __ jmp(&fast_object); | 1707 __ jmp(&fast_object); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1853 ElementsTransitionGenerator:: | 1737 ElementsTransitionGenerator:: |
| 1854 GenerateMapChangeElementsTransition(masm(), | 1738 GenerateMapChangeElementsTransition(masm(), |
| 1855 DONT_TRACK_ALLOCATION_SITE, | 1739 DONT_TRACK_ALLOCATION_SITE, |
| 1856 NULL); | 1740 NULL); |
| 1857 __ bind(&fast_object); | 1741 __ bind(&fast_object); |
| 1858 } else { | 1742 } else { |
| 1859 __ CheckFastObjectElements(a3, a3, &call_builtin); | 1743 __ CheckFastObjectElements(a3, a3, &call_builtin); |
| 1860 } | 1744 } |
| 1861 | 1745 |
| 1862 // Save new length. | 1746 // Save new length. |
| 1863 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1747 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1864 | 1748 |
| 1865 // Store the value. | 1749 // Store the value. |
| 1866 // We may need a register containing the address end_elements below, | 1750 // We may need a register containing the address end_elements below, |
| 1867 // so write back the value in end_elements. | 1751 // so write back the value in end_elements. |
| 1868 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1752 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1869 __ Addu(end_elements, elements, end_elements); | 1753 __ Addu(end_elements, elements, end_elements); |
| 1870 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1754 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1871 __ sw(t0, MemOperand(end_elements)); | 1755 __ sw(t0, MemOperand(end_elements)); |
| 1872 | 1756 |
| 1873 __ RecordWrite(elements, | 1757 __ RecordWrite(elements, |
| 1874 end_elements, | 1758 end_elements, |
| 1875 t0, | 1759 t0, |
| 1876 kRAHasNotBeenSaved, | 1760 kRAHasNotBeenSaved, |
| 1877 kDontSaveFPRegs, | 1761 kDontSaveFPRegs, |
| 1878 EMIT_REMEMBERED_SET, | 1762 EMIT_REMEMBERED_SET, |
| 1879 OMIT_SMI_CHECK); | 1763 OMIT_SMI_CHECK); |
| 1764 __ mov(v0, scratch); |
| 1880 __ DropAndRet(argc + 1); | 1765 __ DropAndRet(argc + 1); |
| 1881 | 1766 |
| 1882 __ bind(&attempt_to_grow_elements); | 1767 __ bind(&attempt_to_grow_elements); |
| 1883 // v0: array's length + 1. | 1768 // scratch: array's length + 1. |
| 1884 // t0: elements' length. | 1769 // t0: elements' length. |
| 1885 | 1770 |
| 1886 if (!FLAG_inline_new) { | 1771 if (!FLAG_inline_new) { |
| 1887 __ Branch(&call_builtin); | 1772 __ Branch(&call_builtin); |
| 1888 } | 1773 } |
| 1889 | 1774 |
| 1890 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); | 1775 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1891 // Growing elements that are SMI-only requires special handling in case | 1776 // Growing elements that are SMI-only requires special handling in case |
| 1892 // the new element is non-Smi. For now, delegate to the builtin. | 1777 // the new element is non-Smi. For now, delegate to the builtin. |
| 1893 Label no_fast_elements_check; | 1778 Label no_fast_elements_check; |
| 1894 __ JumpIfSmi(a2, &no_fast_elements_check); | 1779 __ JumpIfSmi(a2, &no_fast_elements_check); |
| 1895 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1780 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1896 __ CheckFastObjectElements(t3, t3, &call_builtin); | 1781 __ CheckFastObjectElements(t3, t3, &call_builtin); |
| 1897 __ bind(&no_fast_elements_check); | 1782 __ bind(&no_fast_elements_check); |
| 1898 | 1783 |
| 1899 ExternalReference new_space_allocation_top = | 1784 ExternalReference new_space_allocation_top = |
| 1900 ExternalReference::new_space_allocation_top_address(isolate()); | 1785 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1901 ExternalReference new_space_allocation_limit = | 1786 ExternalReference new_space_allocation_limit = |
| 1902 ExternalReference::new_space_allocation_limit_address(isolate()); | 1787 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1903 | 1788 |
| 1904 const int kAllocationDelta = 4; | 1789 const int kAllocationDelta = 4; |
| 1905 // Load top and check if it is the end of elements. | 1790 // Load top and check if it is the end of elements. |
| 1906 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1791 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1907 __ Addu(end_elements, elements, end_elements); | 1792 __ Addu(end_elements, elements, end_elements); |
| 1908 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); | 1793 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); |
| 1909 __ li(t3, Operand(new_space_allocation_top)); | 1794 __ li(t3, Operand(new_space_allocation_top)); |
| 1910 __ lw(a3, MemOperand(t3)); | 1795 __ lw(a3, MemOperand(t3)); |
| 1911 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); | 1796 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); |
| 1912 | 1797 |
| 1913 __ li(t5, Operand(new_space_allocation_limit)); | 1798 __ li(t5, Operand(new_space_allocation_limit)); |
| 1914 __ lw(t5, MemOperand(t5)); | 1799 __ lw(t5, MemOperand(t5)); |
| 1915 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); | 1800 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); |
| 1916 __ Branch(&call_builtin, hi, a3, Operand(t5)); | 1801 __ Branch(&call_builtin, hi, a3, Operand(t5)); |
| 1917 | 1802 |
| 1918 // We fit and could grow elements. | 1803 // We fit and could grow elements. |
| 1919 // Update new_space_allocation_top. | 1804 // Update new_space_allocation_top. |
| 1920 __ sw(a3, MemOperand(t3)); | 1805 __ sw(a3, MemOperand(t3)); |
| 1921 // Push the argument. | 1806 // Push the argument. |
| 1922 __ sw(a2, MemOperand(end_elements)); | 1807 __ sw(a2, MemOperand(end_elements)); |
| 1923 // Fill the rest with holes. | 1808 // Fill the rest with holes. |
| 1924 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); | 1809 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); |
| 1925 for (int i = 1; i < kAllocationDelta; i++) { | 1810 for (int i = 1; i < kAllocationDelta; i++) { |
| 1926 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); | 1811 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); |
| 1927 } | 1812 } |
| 1928 | 1813 |
| 1929 // Update elements' and array's sizes. | 1814 // Update elements' and array's sizes. |
| 1930 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1815 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1931 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); | 1816 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); |
| 1932 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1817 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1933 | 1818 |
| 1934 // Elements are in new space, so write barrier is not required. | 1819 // Elements are in new space, so write barrier is not required. |
| 1820 __ mov(v0, scratch); |
| 1935 __ DropAndRet(argc + 1); | 1821 __ DropAndRet(argc + 1); |
| 1936 } | 1822 } |
| 1937 __ bind(&call_builtin); | 1823 __ bind(&call_builtin); |
| 1938 __ TailCallExternalReference( | 1824 __ TailCallExternalReference( |
| 1939 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | 1825 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); |
| 1940 } | 1826 } |
| 1941 | 1827 |
| 1942 // Handle call cache miss. | 1828 HandlerFrontendFooter(&miss); |
| 1943 __ bind(&miss); | |
| 1944 GenerateMissBranch(); | |
| 1945 | 1829 |
| 1946 // Return the generated code. | 1830 // Return the generated code. |
| 1947 return GetCode(type, name); | 1831 return GetCode(type, name); |
| 1948 } | 1832 } |
| 1949 | 1833 |
| 1950 | 1834 |
| 1951 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1835 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1952 Handle<Object> object, | 1836 Handle<Object> object, |
| 1953 Handle<JSObject> holder, | 1837 Handle<JSObject> holder, |
| 1954 Handle<Cell> cell, | 1838 Handle<Cell> cell, |
| 1955 Handle<JSFunction> function, | 1839 Handle<JSFunction> function, |
| 1956 Handle<String> name, | 1840 Handle<String> name, |
| 1957 Code::StubType type) { | 1841 Code::StubType type) { |
| 1958 // ----------- S t a t e ------------- | 1842 // If object is not an array or is observed or sealed, bail out to regular |
| 1959 // -- a2 : name | 1843 // call. |
| 1960 // -- ra : return address | |
| 1961 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 1962 // -- ... | |
| 1963 // -- sp[argc * 4] : receiver | |
| 1964 // ----------------------------------- | |
| 1965 | |
| 1966 // If object is not an array or is observed, bail out to regular call. | |
| 1967 if (!object->IsJSArray() || | 1844 if (!object->IsJSArray() || |
| 1968 !cell.is_null() || | 1845 !cell.is_null() || |
| 1969 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1846 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1847 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1970 return Handle<Code>::null(); | 1848 return Handle<Code>::null(); |
| 1971 } | 1849 } |
| 1972 | 1850 |
| 1973 Label miss, return_undefined, call_builtin; | 1851 Label miss, return_undefined, call_builtin; |
| 1974 Register receiver = a1; | 1852 Register receiver = a0; |
| 1853 Register scratch = a1; |
| 1975 Register elements = a3; | 1854 Register elements = a3; |
| 1976 GenerateNameCheck(name, &miss); | 1855 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1977 | |
| 1978 // Get the receiver from the stack. | |
| 1979 const int argc = arguments().immediate(); | |
| 1980 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1981 // Check that the receiver isn't a smi. | |
| 1982 __ JumpIfSmi(receiver, &miss); | |
| 1983 | |
| 1984 // Check that the maps haven't changed. | |
| 1985 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, | |
| 1986 t0, v0, name, &miss); | |
| 1987 | 1856 |
| 1988 // Get the elements array of the object. | 1857 // Get the elements array of the object. |
| 1989 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1858 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1990 | 1859 |
| 1991 // Check that the elements are in fast mode and writable. | 1860 // Check that the elements are in fast mode and writable. |
| 1992 __ CheckMap(elements, | 1861 __ CheckMap(elements, |
| 1993 v0, | 1862 scratch, |
| 1994 Heap::kFixedArrayMapRootIndex, | 1863 Heap::kFixedArrayMapRootIndex, |
| 1995 &call_builtin, | 1864 &call_builtin, |
| 1996 DONT_DO_SMI_CHECK); | 1865 DONT_DO_SMI_CHECK); |
| 1997 | 1866 |
| 1998 // Get the array's length into t0 and calculate new length. | 1867 // Get the array's length into t0 and calculate new length. |
| 1999 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1868 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 2000 __ Subu(t0, t0, Operand(Smi::FromInt(1))); | 1869 __ Subu(t0, t0, Operand(Smi::FromInt(1))); |
| 2001 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); | 1870 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); |
| 2002 | 1871 |
| 2003 // Get the last element. | 1872 // Get the last element. |
| 2004 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | 1873 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); |
| 2005 STATIC_ASSERT(kSmiTagSize == 1); | 1874 STATIC_ASSERT(kSmiTagSize == 1); |
| 2006 STATIC_ASSERT(kSmiTag == 0); | 1875 STATIC_ASSERT(kSmiTag == 0); |
| 2007 // We can't address the last element in one operation. Compute the more | 1876 // We can't address the last element in one operation. Compute the more |
| 2008 // expensive shift first, and use an offset later on. | 1877 // expensive shift first, and use an offset later on. |
| 2009 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); | 1878 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); |
| 2010 __ Addu(elements, elements, t1); | 1879 __ Addu(elements, elements, t1); |
| 2011 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1880 __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 2012 __ Branch(&call_builtin, eq, v0, Operand(t2)); | 1881 __ Branch(&call_builtin, eq, scratch, Operand(t2)); |
| 2013 | 1882 |
| 2014 // Set the array's length. | 1883 // Set the array's length. |
| 2015 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1884 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 2016 | 1885 |
| 2017 // Fill with the hole. | 1886 // Fill with the hole. |
| 2018 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1887 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 1888 const int argc = arguments().immediate(); |
| 1889 __ mov(v0, scratch); |
| 2019 __ DropAndRet(argc + 1); | 1890 __ DropAndRet(argc + 1); |
| 2020 | 1891 |
| 2021 __ bind(&return_undefined); | 1892 __ bind(&return_undefined); |
| 2022 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1893 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 2023 __ DropAndRet(argc + 1); | 1894 __ DropAndRet(argc + 1); |
| 2024 | 1895 |
| 2025 __ bind(&call_builtin); | 1896 __ bind(&call_builtin); |
| 2026 __ TailCallExternalReference( | 1897 __ TailCallExternalReference( |
| 2027 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | 1898 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); |
| 2028 | 1899 |
| 2029 // Handle call cache miss. | 1900 HandlerFrontendFooter(&miss); |
| 2030 __ bind(&miss); | |
| 2031 GenerateMissBranch(); | |
| 2032 | 1901 |
| 2033 // Return the generated code. | 1902 // Return the generated code. |
| 2034 return GetCode(type, name); | 1903 return GetCode(type, name); |
| 2035 } | 1904 } |
| 2036 | 1905 |
| 2037 | 1906 |
| 2038 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1907 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2039 Handle<Object> object, | 1908 Handle<Object> object, |
| 2040 Handle<JSObject> holder, | 1909 Handle<JSObject> holder, |
| 2041 Handle<Cell> cell, | 1910 Handle<Cell> cell, |
| 2042 Handle<JSFunction> function, | 1911 Handle<JSFunction> function, |
| 2043 Handle<String> name, | 1912 Handle<String> name, |
| 2044 Code::StubType type) { | 1913 Code::StubType type) { |
| 2045 // ----------- S t a t e ------------- | |
| 2046 // -- a2 : function name | |
| 2047 // -- ra : return address | |
| 2048 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2049 // -- ... | |
| 2050 // -- sp[argc * 4] : receiver | |
| 2051 // ----------------------------------- | |
| 2052 | |
| 2053 // If object is not a string, bail out to regular call. | 1914 // If object is not a string, bail out to regular call. |
| 2054 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1915 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2055 | 1916 |
| 2056 const int argc = arguments().immediate(); | |
| 2057 Label miss; | 1917 Label miss; |
| 2058 Label name_miss; | 1918 Label name_miss; |
| 2059 Label index_out_of_range; | 1919 Label index_out_of_range; |
| 2060 | 1920 |
| 2061 Label* index_out_of_range_label = &index_out_of_range; | 1921 Label* index_out_of_range_label = &index_out_of_range; |
| 2062 | 1922 |
| 2063 if (kind_ == Code::CALL_IC && | 1923 if (kind_ == Code::CALL_IC && |
| 2064 (CallICBase::StringStubState::decode(extra_state_) == | 1924 (CallICBase::StringStubState::decode(extra_state()) == |
| 2065 DEFAULT_STRING_STUB)) { | 1925 DEFAULT_STRING_STUB)) { |
| 2066 index_out_of_range_label = &miss; | 1926 index_out_of_range_label = &miss; |
| 2067 } | 1927 } |
| 2068 | 1928 |
| 2069 GenerateNameCheck(name, &name_miss); | 1929 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2070 | 1930 |
| 2071 // Check that the maps starting from the prototype haven't changed. | 1931 Register receiver = a0; |
| 2072 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2073 Context::STRING_FUNCTION_INDEX, | |
| 2074 v0, | |
| 2075 &miss); | |
| 2076 ASSERT(!object.is_identical_to(holder)); | |
| 2077 CheckPrototypes( | |
| 2078 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2079 v0, holder, a1, a3, t0, name, &miss); | |
| 2080 | |
| 2081 Register receiver = a1; | |
| 2082 Register index = t1; | 1932 Register index = t1; |
| 2083 Register result = v0; | 1933 Register result = a1; |
| 1934 const int argc = arguments().immediate(); |
| 2084 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1935 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2085 if (argc > 0) { | 1936 if (argc > 0) { |
| 2086 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1937 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2087 } else { | 1938 } else { |
| 2088 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1939 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2089 } | 1940 } |
| 2090 | 1941 |
| 2091 StringCharCodeAtGenerator generator(receiver, | 1942 StringCharCodeAtGenerator generator(receiver, |
| 2092 index, | 1943 index, |
| 2093 result, | 1944 result, |
| 2094 &miss, // When not a string. | 1945 &miss, // When not a string. |
| 2095 &miss, // When not a number. | 1946 &miss, // When not a number. |
| 2096 index_out_of_range_label, | 1947 index_out_of_range_label, |
| 2097 STRING_INDEX_IS_NUMBER); | 1948 STRING_INDEX_IS_NUMBER); |
| 2098 generator.GenerateFast(masm()); | 1949 generator.GenerateFast(masm()); |
| 1950 __ mov(v0, result); |
| 2099 __ DropAndRet(argc + 1); | 1951 __ DropAndRet(argc + 1); |
| 2100 | 1952 |
| 2101 StubRuntimeCallHelper call_helper; | 1953 StubRuntimeCallHelper call_helper; |
| 2102 generator.GenerateSlow(masm(), call_helper); | 1954 generator.GenerateSlow(masm(), call_helper); |
| 2103 | 1955 |
| 2104 if (index_out_of_range.is_linked()) { | 1956 if (index_out_of_range.is_linked()) { |
| 2105 __ bind(&index_out_of_range); | 1957 __ bind(&index_out_of_range); |
| 2106 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 1958 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
| 2107 __ DropAndRet(argc + 1); | 1959 __ DropAndRet(argc + 1); |
| 2108 } | 1960 } |
| 2109 | 1961 |
| 2110 __ bind(&miss); | 1962 __ bind(&miss); |
| 2111 // Restore function name in a2. | 1963 // Restore function name in a2. |
| 2112 __ li(a2, name); | 1964 __ li(a2, name); |
| 2113 __ bind(&name_miss); | 1965 HandlerFrontendFooter(&name_miss); |
| 2114 GenerateMissBranch(); | |
| 2115 | 1966 |
| 2116 // Return the generated code. | 1967 // Return the generated code. |
| 2117 return GetCode(type, name); | 1968 return GetCode(type, name); |
| 2118 } | 1969 } |
| 2119 | 1970 |
| 2120 | 1971 |
| 2121 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1972 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2122 Handle<Object> object, | 1973 Handle<Object> object, |
| 2123 Handle<JSObject> holder, | 1974 Handle<JSObject> holder, |
| 2124 Handle<Cell> cell, | 1975 Handle<Cell> cell, |
| 2125 Handle<JSFunction> function, | 1976 Handle<JSFunction> function, |
| 2126 Handle<String> name, | 1977 Handle<String> name, |
| 2127 Code::StubType type) { | 1978 Code::StubType type) { |
| 2128 // ----------- S t a t e ------------- | |
| 2129 // -- a2 : function name | |
| 2130 // -- ra : return address | |
| 2131 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2132 // -- ... | |
| 2133 // -- sp[argc * 4] : receiver | |
| 2134 // ----------------------------------- | |
| 2135 | |
| 2136 // If object is not a string, bail out to regular call. | 1979 // If object is not a string, bail out to regular call. |
| 2137 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1980 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2138 | 1981 |
| 2139 const int argc = arguments().immediate(); | 1982 const int argc = arguments().immediate(); |
| 2140 Label miss; | 1983 Label miss; |
| 2141 Label name_miss; | 1984 Label name_miss; |
| 2142 Label index_out_of_range; | 1985 Label index_out_of_range; |
| 2143 Label* index_out_of_range_label = &index_out_of_range; | 1986 Label* index_out_of_range_label = &index_out_of_range; |
| 2144 if (kind_ == Code::CALL_IC && | 1987 if (kind_ == Code::CALL_IC && |
| 2145 (CallICBase::StringStubState::decode(extra_state_) == | 1988 (CallICBase::StringStubState::decode(extra_state()) == |
| 2146 DEFAULT_STRING_STUB)) { | 1989 DEFAULT_STRING_STUB)) { |
| 2147 index_out_of_range_label = &miss; | 1990 index_out_of_range_label = &miss; |
| 2148 } | 1991 } |
| 2149 GenerateNameCheck(name, &name_miss); | |
| 2150 | 1992 |
| 2151 // Check that the maps starting from the prototype haven't changed. | 1993 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2152 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2153 Context::STRING_FUNCTION_INDEX, | |
| 2154 v0, | |
| 2155 &miss); | |
| 2156 ASSERT(!object.is_identical_to(holder)); | |
| 2157 CheckPrototypes( | |
| 2158 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2159 v0, holder, a1, a3, t0, name, &miss); | |
| 2160 | 1994 |
| 2161 Register receiver = v0; | 1995 Register receiver = a0; |
| 2162 Register index = t1; | 1996 Register index = t1; |
| 2163 Register scratch = a3; | 1997 Register scratch = a3; |
| 2164 Register result = v0; | 1998 Register result = a1; |
| 2165 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 2166 if (argc > 0) { | 1999 if (argc > 0) { |
| 2167 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 2000 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2168 } else { | 2001 } else { |
| 2169 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2002 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2170 } | 2003 } |
| 2171 | 2004 |
| 2172 StringCharAtGenerator generator(receiver, | 2005 StringCharAtGenerator generator(receiver, |
| 2173 index, | 2006 index, |
| 2174 scratch, | 2007 scratch, |
| 2175 result, | 2008 result, |
| 2176 &miss, // When not a string. | 2009 &miss, // When not a string. |
| 2177 &miss, // When not a number. | 2010 &miss, // When not a number. |
| 2178 index_out_of_range_label, | 2011 index_out_of_range_label, |
| 2179 STRING_INDEX_IS_NUMBER); | 2012 STRING_INDEX_IS_NUMBER); |
| 2180 generator.GenerateFast(masm()); | 2013 generator.GenerateFast(masm()); |
| 2014 __ mov(v0, result); |
| 2181 __ DropAndRet(argc + 1); | 2015 __ DropAndRet(argc + 1); |
| 2182 | 2016 |
| 2183 StubRuntimeCallHelper call_helper; | 2017 StubRuntimeCallHelper call_helper; |
| 2184 generator.GenerateSlow(masm(), call_helper); | 2018 generator.GenerateSlow(masm(), call_helper); |
| 2185 | 2019 |
| 2186 if (index_out_of_range.is_linked()) { | 2020 if (index_out_of_range.is_linked()) { |
| 2187 __ bind(&index_out_of_range); | 2021 __ bind(&index_out_of_range); |
| 2188 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 2022 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
| 2189 __ DropAndRet(argc + 1); | 2023 __ DropAndRet(argc + 1); |
| 2190 } | 2024 } |
| 2191 | 2025 |
| 2192 __ bind(&miss); | 2026 __ bind(&miss); |
| 2193 // Restore function name in a2. | 2027 // Restore function name in a2. |
| 2194 __ li(a2, name); | 2028 __ li(a2, name); |
| 2195 __ bind(&name_miss); | 2029 HandlerFrontendFooter(&name_miss); |
| 2196 GenerateMissBranch(); | |
| 2197 | 2030 |
| 2198 // Return the generated code. | 2031 // Return the generated code. |
| 2199 return GetCode(type, name); | 2032 return GetCode(type, name); |
| 2200 } | 2033 } |
| 2201 | 2034 |
| 2202 | 2035 |
| 2203 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2036 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2204 Handle<Object> object, | 2037 Handle<Object> object, |
| 2205 Handle<JSObject> holder, | 2038 Handle<JSObject> holder, |
| 2206 Handle<Cell> cell, | 2039 Handle<Cell> cell, |
| 2207 Handle<JSFunction> function, | 2040 Handle<JSFunction> function, |
| 2208 Handle<String> name, | 2041 Handle<String> name, |
| 2209 Code::StubType type) { | 2042 Code::StubType type) { |
| 2210 // ----------- S t a t e ------------- | |
| 2211 // -- a2 : function name | |
| 2212 // -- ra : return address | |
| 2213 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2214 // -- ... | |
| 2215 // -- sp[argc * 4] : receiver | |
| 2216 // ----------------------------------- | |
| 2217 | |
| 2218 const int argc = arguments().immediate(); | 2043 const int argc = arguments().immediate(); |
| 2219 | 2044 |
| 2220 // If the object is not a JSObject or we got an unexpected number of | 2045 // If the object is not a JSObject or we got an unexpected number of |
| 2221 // arguments, bail out to the regular call. | 2046 // arguments, bail out to the regular call. |
| 2222 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2047 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2223 | 2048 |
| 2224 Label miss; | 2049 Label miss; |
| 2225 GenerateNameCheck(name, &miss); | 2050 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2226 | 2051 if (!cell.is_null()) { |
| 2227 if (cell.is_null()) { | |
| 2228 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2229 | |
| 2230 STATIC_ASSERT(kSmiTag == 0); | |
| 2231 __ JumpIfSmi(a1, &miss); | |
| 2232 | |
| 2233 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, | |
| 2234 name, &miss); | |
| 2235 } else { | |
| 2236 ASSERT(cell->value() == *function); | 2052 ASSERT(cell->value() == *function); |
| 2237 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2238 &miss); | |
| 2239 GenerateLoadFunctionFromCell(cell, function, &miss); | 2053 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2240 } | 2054 } |
| 2241 | 2055 |
| 2242 // Load the char code argument. | 2056 // Load the char code argument. |
| 2243 Register code = a1; | 2057 Register code = a1; |
| 2244 __ lw(code, MemOperand(sp, 0 * kPointerSize)); | 2058 __ lw(code, MemOperand(sp, 0 * kPointerSize)); |
| 2245 | 2059 |
| 2246 // Check the code is a smi. | 2060 // Check the code is a smi. |
| 2247 Label slow; | 2061 Label slow; |
| 2248 STATIC_ASSERT(kSmiTag == 0); | 2062 STATIC_ASSERT(kSmiTag == 0); |
| 2249 __ JumpIfNotSmi(code, &slow); | 2063 __ JumpIfNotSmi(code, &slow); |
| 2250 | 2064 |
| 2251 // Convert the smi code to uint16. | 2065 // Convert the smi code to uint16. |
| 2252 __ And(code, code, Operand(Smi::FromInt(0xffff))); | 2066 __ And(code, code, Operand(Smi::FromInt(0xffff))); |
| 2253 | 2067 |
| 2254 StringCharFromCodeGenerator generator(code, v0); | 2068 StringCharFromCodeGenerator generator(code, v0); |
| 2255 generator.GenerateFast(masm()); | 2069 generator.GenerateFast(masm()); |
| 2256 __ DropAndRet(argc + 1); | 2070 __ DropAndRet(argc + 1); |
| 2257 | 2071 |
| 2258 StubRuntimeCallHelper call_helper; | 2072 StubRuntimeCallHelper call_helper; |
| 2259 generator.GenerateSlow(masm(), call_helper); | 2073 generator.GenerateSlow(masm(), call_helper); |
| 2260 | 2074 |
| 2261 // Tail call the full function. We do not have to patch the receiver | |
| 2262 // because the function makes no use of it. | |
| 2263 __ bind(&slow); | 2075 __ bind(&slow); |
| 2264 ParameterCount expected(function); | 2076 // We do not have to patch the receiver because the function makes no use of |
| 2265 __ InvokeFunction(function, expected, arguments(), | 2077 // it. |
| 2266 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2078 GenerateJumpFunctionIgnoreReceiver(function); |
| 2267 | 2079 |
| 2268 __ bind(&miss); | 2080 HandlerFrontendFooter(&miss); |
| 2269 // a2: function name. | |
| 2270 GenerateMissBranch(); | |
| 2271 | 2081 |
| 2272 // Return the generated code. | 2082 // Return the generated code. |
| 2273 return GetCode(type, name); | 2083 return GetCode(type, name); |
| 2274 } | 2084 } |
| 2275 | 2085 |
| 2276 | 2086 |
| 2277 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2087 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2278 Handle<Object> object, | 2088 Handle<Object> object, |
| 2279 Handle<JSObject> holder, | 2089 Handle<JSObject> holder, |
| 2280 Handle<Cell> cell, | 2090 Handle<Cell> cell, |
| 2281 Handle<JSFunction> function, | 2091 Handle<JSFunction> function, |
| 2282 Handle<String> name, | 2092 Handle<String> name, |
| 2283 Code::StubType type) { | 2093 Code::StubType type) { |
| 2284 // ----------- S t a t e ------------- | |
| 2285 // -- a2 : function name | |
| 2286 // -- ra : return address | |
| 2287 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2288 // -- ... | |
| 2289 // -- sp[argc * 4] : receiver | |
| 2290 // ----------------------------------- | |
| 2291 | |
| 2292 | |
| 2293 const int argc = arguments().immediate(); | 2094 const int argc = arguments().immediate(); |
| 2294 // If the object is not a JSObject or we got an unexpected number of | 2095 // If the object is not a JSObject or we got an unexpected number of |
| 2295 // arguments, bail out to the regular call. | 2096 // arguments, bail out to the regular call. |
| 2296 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2097 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2297 | 2098 |
| 2298 Label miss, slow; | 2099 Label miss, slow; |
| 2299 GenerateNameCheck(name, &miss); | 2100 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2300 | 2101 if (!cell.is_null()) { |
| 2301 if (cell.is_null()) { | |
| 2302 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2303 STATIC_ASSERT(kSmiTag == 0); | |
| 2304 __ JumpIfSmi(a1, &miss); | |
| 2305 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, | |
| 2306 name, &miss); | |
| 2307 } else { | |
| 2308 ASSERT(cell->value() == *function); | 2102 ASSERT(cell->value() == *function); |
| 2309 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2310 &miss); | |
| 2311 GenerateLoadFunctionFromCell(cell, function, &miss); | 2103 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2312 } | 2104 } |
| 2313 | 2105 |
| 2314 // Load the (only) argument into v0. | 2106 // Load the (only) argument into v0. |
| 2315 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2107 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2316 | 2108 |
| 2317 // If the argument is a smi, just return. | 2109 // If the argument is a smi, just return. |
| 2318 STATIC_ASSERT(kSmiTag == 0); | 2110 STATIC_ASSERT(kSmiTag == 0); |
| 2319 __ SmiTst(v0, t0); | 2111 __ SmiTst(v0, t0); |
| 2320 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); | 2112 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 // Restore FCSR and return. | 2174 // Restore FCSR and return. |
| 2383 __ ctc1(a3, FCSR); | 2175 __ ctc1(a3, FCSR); |
| 2384 | 2176 |
| 2385 __ DropAndRet(argc + 1); | 2177 __ DropAndRet(argc + 1); |
| 2386 | 2178 |
| 2387 __ bind(&wont_fit_smi); | 2179 __ bind(&wont_fit_smi); |
| 2388 // Restore FCSR and fall to slow case. | 2180 // Restore FCSR and fall to slow case. |
| 2389 __ ctc1(a3, FCSR); | 2181 __ ctc1(a3, FCSR); |
| 2390 | 2182 |
| 2391 __ bind(&slow); | 2183 __ bind(&slow); |
| 2392 // Tail call the full function. We do not have to patch the receiver | 2184 // We do not have to patch the receiver because the function makes no use of |
| 2393 // because the function makes no use of it. | 2185 // it. |
| 2394 ParameterCount expected(function); | 2186 GenerateJumpFunctionIgnoreReceiver(function); |
| 2395 __ InvokeFunction(function, expected, arguments(), | |
| 2396 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
| 2397 | 2187 |
| 2398 __ bind(&miss); | 2188 HandlerFrontendFooter(&miss); |
| 2399 // a2: function name. | |
| 2400 GenerateMissBranch(); | |
| 2401 | 2189 |
| 2402 // Return the generated code. | 2190 // Return the generated code. |
| 2403 return GetCode(type, name); | 2191 return GetCode(type, name); |
| 2404 } | 2192 } |
| 2405 | 2193 |
| 2406 | 2194 |
| 2407 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2195 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2408 Handle<Object> object, | 2196 Handle<Object> object, |
| 2409 Handle<JSObject> holder, | 2197 Handle<JSObject> holder, |
| 2410 Handle<Cell> cell, | 2198 Handle<Cell> cell, |
| 2411 Handle<JSFunction> function, | 2199 Handle<JSFunction> function, |
| 2412 Handle<String> name, | 2200 Handle<String> name, |
| 2413 Code::StubType type) { | 2201 Code::StubType type) { |
| 2414 // ----------- S t a t e ------------- | |
| 2415 // -- a2 : function name | |
| 2416 // -- ra : return address | |
| 2417 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2418 // -- ... | |
| 2419 // -- sp[argc * 4] : receiver | |
| 2420 // ----------------------------------- | |
| 2421 | |
| 2422 const int argc = arguments().immediate(); | 2202 const int argc = arguments().immediate(); |
| 2423 // If the object is not a JSObject or we got an unexpected number of | 2203 // If the object is not a JSObject or we got an unexpected number of |
| 2424 // arguments, bail out to the regular call. | 2204 // arguments, bail out to the regular call. |
| 2425 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2205 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2426 | 2206 |
| 2427 Label miss; | 2207 Label miss; |
| 2428 | 2208 |
| 2429 GenerateNameCheck(name, &miss); | 2209 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2430 if (cell.is_null()) { | 2210 if (!cell.is_null()) { |
| 2431 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2432 STATIC_ASSERT(kSmiTag == 0); | |
| 2433 __ JumpIfSmi(a1, &miss); | |
| 2434 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, | |
| 2435 name, &miss); | |
| 2436 } else { | |
| 2437 ASSERT(cell->value() == *function); | 2211 ASSERT(cell->value() == *function); |
| 2438 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2439 &miss); | |
| 2440 GenerateLoadFunctionFromCell(cell, function, &miss); | 2212 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2441 } | 2213 } |
| 2442 | 2214 |
| 2443 // Load the (only) argument into v0. | 2215 // Load the (only) argument into v0. |
| 2444 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2216 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2445 | 2217 |
| 2446 // Check if the argument is a smi. | 2218 // Check if the argument is a smi. |
| 2447 Label not_smi; | 2219 Label not_smi; |
| 2448 STATIC_ASSERT(kSmiTag == 0); | 2220 STATIC_ASSERT(kSmiTag == 0); |
| 2449 __ JumpIfNotSmi(v0, ¬_smi); | 2221 __ JumpIfNotSmi(v0, ¬_smi); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2481 // number. | 2253 // number. |
| 2482 __ bind(&negative_sign); | 2254 __ bind(&negative_sign); |
| 2483 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); | 2255 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); |
| 2484 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2256 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 2485 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); | 2257 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); |
| 2486 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); | 2258 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); |
| 2487 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 2259 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 2488 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2260 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 2489 __ DropAndRet(argc + 1); | 2261 __ DropAndRet(argc + 1); |
| 2490 | 2262 |
| 2491 // Tail call the full function. We do not have to patch the receiver | |
| 2492 // because the function makes no use of it. | |
| 2493 __ bind(&slow); | 2263 __ bind(&slow); |
| 2494 ParameterCount expected(function); | 2264 // We do not have to patch the receiver because the function makes no use of |
| 2495 __ InvokeFunction(function, expected, arguments(), | 2265 // it. |
| 2496 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2266 GenerateJumpFunctionIgnoreReceiver(function); |
| 2497 | 2267 |
| 2498 __ bind(&miss); | 2268 HandlerFrontendFooter(&miss); |
| 2499 // a2: function name. | |
| 2500 GenerateMissBranch(); | |
| 2501 | 2269 |
| 2502 // Return the generated code. | 2270 // Return the generated code. |
| 2503 return GetCode(type, name); | 2271 return GetCode(type, name); |
| 2504 } | 2272 } |
| 2505 | 2273 |
| 2506 | 2274 |
| 2507 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2275 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2508 const CallOptimization& optimization, | 2276 const CallOptimization& optimization, |
| 2509 Handle<Object> object, | 2277 Handle<Object> object, |
| 2510 Handle<JSObject> holder, | 2278 Handle<JSObject> holder, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2534 | 2302 |
| 2535 // Check that the receiver isn't a smi. | 2303 // Check that the receiver isn't a smi. |
| 2536 __ JumpIfSmi(a1, &miss_before_stack_reserved); | 2304 __ JumpIfSmi(a1, &miss_before_stack_reserved); |
| 2537 | 2305 |
| 2538 __ IncrementCounter(counters->call_const(), 1, a0, a3); | 2306 __ IncrementCounter(counters->call_const(), 1, a0, a3); |
| 2539 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); | 2307 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); |
| 2540 | 2308 |
| 2541 ReserveSpaceForFastApiCall(masm(), a0); | 2309 ReserveSpaceForFastApiCall(masm(), a0); |
| 2542 | 2310 |
| 2543 // Check that the maps haven't changed and find a Holder as a side effect. | 2311 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2544 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name, | 2312 CheckPrototypes( |
| 2545 depth, &miss); | 2313 IC::CurrentTypeOf(object, isolate()), |
| 2314 a1, holder, a0, a3, t0, name, depth, &miss); |
| 2546 | 2315 |
| 2547 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2316 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
| 2548 | 2317 |
| 2549 __ bind(&miss); | 2318 __ bind(&miss); |
| 2550 FreeSpaceForFastApiCall(masm()); | 2319 FreeSpaceForFastApiCall(masm()); |
| 2551 | 2320 |
| 2552 __ bind(&miss_before_stack_reserved); | 2321 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2553 GenerateMissBranch(); | |
| 2554 | 2322 |
| 2555 // Return the generated code. | 2323 // Return the generated code. |
| 2556 return GetCode(function); | 2324 return GetCode(function); |
| 2557 } | 2325 } |
| 2558 | 2326 |
| 2559 | 2327 |
| 2560 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2328 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2561 Label success; | 2329 Label success; |
| 2562 // Check that the object is a boolean. | 2330 // Check that the object is a boolean. |
| 2563 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2331 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 2564 __ Branch(&success, eq, object, Operand(at)); | 2332 __ Branch(&success, eq, object, Operand(at)); |
| 2565 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 2333 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
| 2566 __ Branch(miss, ne, object, Operand(at)); | 2334 __ Branch(miss, ne, object, Operand(at)); |
| 2567 __ bind(&success); | 2335 __ bind(&success); |
| 2568 } | 2336 } |
| 2569 | 2337 |
| 2570 | 2338 |
| 2571 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2339 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2572 Handle<JSObject> holder, | 2340 if (object->IsGlobalObject()) { |
| 2573 Handle<Name> name, | 2341 const int argc = arguments().immediate(); |
| 2574 CheckType check) { | 2342 const int receiver_offset = argc * kPointerSize; |
| 2343 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 2344 __ sw(a3, MemOperand(sp, receiver_offset)); |
| 2345 } |
| 2346 } |
| 2347 |
| 2348 |
| 2349 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2350 Handle<JSObject> holder, |
| 2351 Handle<Name> name, |
| 2352 CheckType check, |
| 2353 Label* miss) { |
| 2575 // ----------- S t a t e ------------- | 2354 // ----------- S t a t e ------------- |
| 2576 // -- a2 : name | 2355 // -- a2 : name |
| 2577 // -- ra : return address | 2356 // -- ra : return address |
| 2578 // ----------------------------------- | 2357 // ----------------------------------- |
| 2579 Label miss; | 2358 GenerateNameCheck(name, miss); |
| 2580 GenerateNameCheck(name, &miss); | 2359 |
| 2360 Register reg = a0; |
| 2581 | 2361 |
| 2582 // Get the receiver from the stack. | 2362 // Get the receiver from the stack. |
| 2583 const int argc = arguments().immediate(); | 2363 const int argc = arguments().immediate(); |
| 2584 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2364 const int receiver_offset = argc * kPointerSize; |
| 2365 __ lw(a0, MemOperand(sp, receiver_offset)); |
| 2585 | 2366 |
| 2586 // Check that the receiver isn't a smi. | 2367 // Check that the receiver isn't a smi. |
| 2587 if (check != NUMBER_CHECK) { | 2368 if (check != NUMBER_CHECK) { |
| 2588 __ JumpIfSmi(a1, &miss); | 2369 __ JumpIfSmi(a0, miss); |
| 2589 } | 2370 } |
| 2590 | 2371 |
| 2591 // Make sure that it's okay not to patch the on stack receiver | 2372 // Make sure that it's okay not to patch the on stack receiver |
| 2592 // unless we're doing a receiver map check. | 2373 // unless we're doing a receiver map check. |
| 2593 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2374 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2594 switch (check) { | 2375 switch (check) { |
| 2595 case RECEIVER_MAP_CHECK: | 2376 case RECEIVER_MAP_CHECK: |
| 2596 __ IncrementCounter(isolate()->counters()->call_const(), 1, a0, a3); | 2377 __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3); |
| 2597 | 2378 |
| 2598 // Check that the maps haven't changed. | 2379 // Check that the maps haven't changed. |
| 2599 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, | 2380 reg = CheckPrototypes( |
| 2600 name, &miss); | 2381 IC::CurrentTypeOf(object, isolate()), |
| 2601 | 2382 reg, holder, a1, a3, t0, name, miss); |
| 2602 // Patch the receiver on the stack with the global proxy if | |
| 2603 // necessary. | |
| 2604 if (object->IsGlobalObject()) { | |
| 2605 __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | |
| 2606 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
| 2607 } | |
| 2608 break; | 2383 break; |
| 2609 | 2384 |
| 2610 case STRING_CHECK: | 2385 case STRING_CHECK: { |
| 2611 // Check that the object is a string. | 2386 // Check that the object is a string. |
| 2612 __ GetObjectType(a1, a3, a3); | 2387 __ GetObjectType(reg, a3, a3); |
| 2613 __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); | 2388 __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); |
| 2614 // Check that the maps starting from the prototype haven't changed. | 2389 // Check that the maps starting from the prototype haven't changed. |
| 2615 GenerateDirectLoadGlobalFunctionPrototype( | 2390 GenerateDirectLoadGlobalFunctionPrototype( |
| 2616 masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); | 2391 masm(), Context::STRING_FUNCTION_INDEX, a1, miss); |
| 2617 CheckPrototypes( | |
| 2618 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2619 a0, holder, a3, a1, t0, name, &miss); | |
| 2620 break; | 2392 break; |
| 2621 | 2393 } |
| 2622 case SYMBOL_CHECK: | 2394 case SYMBOL_CHECK: { |
| 2623 // Check that the object is a symbol. | 2395 // Check that the object is a symbol. |
| 2624 __ GetObjectType(a1, a1, a3); | 2396 __ GetObjectType(reg, a1, a3); |
| 2625 __ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE)); | 2397 __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE)); |
| 2626 // Check that the maps starting from the prototype haven't changed. | 2398 // Check that the maps starting from the prototype haven't changed. |
| 2627 GenerateDirectLoadGlobalFunctionPrototype( | 2399 GenerateDirectLoadGlobalFunctionPrototype( |
| 2628 masm(), Context::SYMBOL_FUNCTION_INDEX, a0, &miss); | 2400 masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss); |
| 2629 CheckPrototypes( | |
| 2630 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2631 a0, holder, a3, a1, t0, name, &miss); | |
| 2632 break; | 2401 break; |
| 2633 | 2402 } |
| 2634 case NUMBER_CHECK: { | 2403 case NUMBER_CHECK: { |
| 2635 Label fast; | 2404 Label fast; |
| 2636 // Check that the object is a smi or a heap number. | 2405 // Check that the object is a smi or a heap number. |
| 2637 __ JumpIfSmi(a1, &fast); | 2406 __ JumpIfSmi(reg, &fast); |
| 2638 __ GetObjectType(a1, a0, a0); | 2407 __ GetObjectType(reg, a3, a3); |
| 2639 __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); | 2408 __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE)); |
| 2640 __ bind(&fast); | 2409 __ bind(&fast); |
| 2641 // Check that the maps starting from the prototype haven't changed. | 2410 // Check that the maps starting from the prototype haven't changed. |
| 2642 GenerateDirectLoadGlobalFunctionPrototype( | 2411 GenerateDirectLoadGlobalFunctionPrototype( |
| 2643 masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); | 2412 masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss); |
| 2644 CheckPrototypes( | |
| 2645 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2646 a0, holder, a3, a1, t0, name, &miss); | |
| 2647 break; | 2413 break; |
| 2648 } | 2414 } |
| 2649 case BOOLEAN_CHECK: { | 2415 case BOOLEAN_CHECK: { |
| 2650 GenerateBooleanCheck(a1, &miss); | 2416 GenerateBooleanCheck(reg, miss); |
| 2651 | 2417 |
| 2652 // Check that the maps starting from the prototype haven't changed. | 2418 // Check that the maps starting from the prototype haven't changed. |
| 2653 GenerateDirectLoadGlobalFunctionPrototype( | 2419 GenerateDirectLoadGlobalFunctionPrototype( |
| 2654 masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); | 2420 masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss); |
| 2655 CheckPrototypes( | |
| 2656 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2657 a0, holder, a3, a1, t0, name, &miss); | |
| 2658 break; | 2421 break; |
| 2659 } | 2422 } |
| 2660 } | 2423 } |
| 2661 | 2424 |
| 2662 Label success; | 2425 if (check != RECEIVER_MAP_CHECK) { |
| 2663 __ Branch(&success); | 2426 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2427 reg = CheckPrototypes( |
| 2428 IC::CurrentTypeOf(prototype, isolate()), |
| 2429 a1, holder, a1, a3, t0, name, miss); |
| 2430 } |
| 2664 | 2431 |
| 2665 // Handle call cache miss. | 2432 return reg; |
| 2666 __ bind(&miss); | |
| 2667 | |
| 2668 GenerateMissBranch(); | |
| 2669 | |
| 2670 __ bind(&success); | |
| 2671 } | 2433 } |
| 2672 | 2434 |
| 2673 | 2435 |
| 2674 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2436 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2675 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2437 Register function, |
| 2676 ? CALL_AS_FUNCTION | 2438 Label* miss) { |
| 2677 : CALL_AS_METHOD; | 2439 ASSERT(function.is(a1)); |
| 2678 ParameterCount expected(function); | 2440 // Check that the function really is a function. |
| 2679 __ InvokeFunction(function, expected, arguments(), | 2441 GenerateFunctionCheck(function, a3, miss); |
| 2680 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2442 PatchGlobalProxy(object); |
| 2681 } | 2443 // Invoke the function. |
| 2682 | 2444 __ InvokeFunction(a1, arguments(), JUMP_FUNCTION, |
| 2683 | 2445 NullCallWrapper(), call_kind()); |
| 2684 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2685 Handle<Object> object, | |
| 2686 Handle<JSObject> holder, | |
| 2687 Handle<Name> name, | |
| 2688 CheckType check, | |
| 2689 Handle<JSFunction> function) { | |
| 2690 if (HasCustomCallGenerator(function)) { | |
| 2691 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2692 Handle<Cell>::null(), | |
| 2693 function, Handle<String>::cast(name), | |
| 2694 Code::FAST); | |
| 2695 // A null handle means bail out to the regular compiler code below. | |
| 2696 if (!code.is_null()) return code; | |
| 2697 } | |
| 2698 | |
| 2699 CompileHandlerFrontend(object, holder, name, check); | |
| 2700 CompileHandlerBackend(function); | |
| 2701 | |
| 2702 // Return the generated code. | |
| 2703 return GetCode(function); | |
| 2704 } | 2446 } |
| 2705 | 2447 |
| 2706 | 2448 |
| 2707 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2449 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2708 Handle<JSObject> holder, | 2450 Handle<JSObject> holder, |
| 2709 Handle<Name> name) { | 2451 Handle<Name> name) { |
| 2710 // ----------- S t a t e ------------- | |
| 2711 // -- a2 : name | |
| 2712 // -- ra : return address | |
| 2713 // ----------------------------------- | |
| 2714 | |
| 2715 Label miss; | 2452 Label miss; |
| 2716 | 2453 |
| 2717 GenerateNameCheck(name, &miss); | 2454 GenerateNameCheck(name, &miss); |
| 2718 | 2455 |
| 2719 // Get the number of arguments. | 2456 // Get the number of arguments. |
| 2720 const int argc = arguments().immediate(); | 2457 const int argc = arguments().immediate(); |
| 2721 LookupResult lookup(isolate()); | 2458 LookupResult lookup(isolate()); |
| 2722 LookupPostInterceptor(holder, name, &lookup); | 2459 LookupPostInterceptor(holder, name, &lookup); |
| 2723 | 2460 |
| 2724 // Get the receiver from the stack. | 2461 // Get the receiver from the stack. |
| 2725 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2462 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2726 | 2463 |
| 2727 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); | 2464 CallInterceptorCompiler compiler(this, arguments(), a2); |
| 2728 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, | 2465 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, |
| 2729 &miss); | 2466 &miss); |
| 2730 | 2467 |
| 2731 // Move returned value, the function to call, to a1. | 2468 // Move returned value, the function to call, to a1. |
| 2732 __ mov(a1, v0); | 2469 __ mov(a1, v0); |
| 2733 // Restore receiver. | 2470 // Restore receiver. |
| 2734 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2471 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 2735 | 2472 |
| 2736 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 2473 GenerateJumpFunction(object, a1, &miss); |
| 2737 | 2474 |
| 2738 // Handle call cache miss. | 2475 HandlerFrontendFooter(&miss); |
| 2739 __ bind(&miss); | |
| 2740 GenerateMissBranch(); | |
| 2741 | 2476 |
| 2742 // Return the generated code. | 2477 // Return the generated code. |
| 2743 return GetCode(Code::FAST, name); | 2478 return GetCode(Code::FAST, name); |
| 2744 } | 2479 } |
| 2745 | 2480 |
| 2746 | 2481 |
| 2747 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2482 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2748 Handle<JSObject> object, | 2483 Handle<JSObject> object, |
| 2749 Handle<GlobalObject> holder, | 2484 Handle<GlobalObject> holder, |
| 2750 Handle<PropertyCell> cell, | 2485 Handle<PropertyCell> cell, |
| 2751 Handle<JSFunction> function, | 2486 Handle<JSFunction> function, |
| 2752 Handle<Name> name) { | 2487 Handle<Name> name) { |
| 2753 // ----------- S t a t e ------------- | |
| 2754 // -- a2 : name | |
| 2755 // -- ra : return address | |
| 2756 // ----------------------------------- | |
| 2757 | |
| 2758 if (HasCustomCallGenerator(function)) { | 2488 if (HasCustomCallGenerator(function)) { |
| 2759 Handle<Code> code = CompileCustomCall( | 2489 Handle<Code> code = CompileCustomCall( |
| 2760 object, holder, cell, function, Handle<String>::cast(name), | 2490 object, holder, cell, function, Handle<String>::cast(name), |
| 2761 Code::NORMAL); | 2491 Code::NORMAL); |
| 2762 // A null handle means bail out to the regular compiler code below. | 2492 // A null handle means bail out to the regular compiler code below. |
| 2763 if (!code.is_null()) return code; | 2493 if (!code.is_null()) return code; |
| 2764 } | 2494 } |
| 2765 | 2495 |
| 2766 Label miss; | 2496 Label miss; |
| 2767 GenerateNameCheck(name, &miss); | 2497 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2768 | 2498 // Potentially loads a closure that matches the shared function info of the |
| 2769 // Get the number of arguments. | 2499 // function, rather than function. |
| 2770 const int argc = arguments().immediate(); | |
| 2771 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2772 GenerateLoadFunctionFromCell(cell, function, &miss); | 2500 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2773 | |
| 2774 // Patch the receiver on the stack with the global proxy if | |
| 2775 // necessary. | |
| 2776 if (object->IsGlobalObject()) { | |
| 2777 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | |
| 2778 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
| 2779 } | |
| 2780 | |
| 2781 // Set up the context (function already in r1). | |
| 2782 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | |
| 2783 | |
| 2784 // Jump to the cached code (tail call). | |
| 2785 Counters* counters = isolate()->counters(); | 2501 Counters* counters = isolate()->counters(); |
| 2786 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2502 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
| 2787 ParameterCount expected(function->shared()->formal_parameter_count()); | 2503 GenerateJumpFunction(object, a1, function); |
| 2788 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2504 HandlerFrontendFooter(&miss); |
| 2789 ? CALL_AS_FUNCTION | |
| 2790 : CALL_AS_METHOD; | |
| 2791 // We call indirectly through the code field in the function to | |
| 2792 // allow recompilation to take effect without changing any of the | |
| 2793 // call sites. | |
| 2794 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | |
| 2795 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, | |
| 2796 NullCallWrapper(), call_kind); | |
| 2797 | |
| 2798 // Handle call cache miss. | |
| 2799 __ bind(&miss); | |
| 2800 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | |
| 2801 GenerateMissBranch(); | |
| 2802 | 2505 |
| 2803 // Return the generated code. | 2506 // Return the generated code. |
| 2804 return GetCode(Code::NORMAL, name); | 2507 return GetCode(Code::NORMAL, name); |
| 2805 } | 2508 } |
| 2806 | 2509 |
| 2807 | 2510 |
| 2808 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2511 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2809 Handle<JSObject> object, | 2512 Handle<JSObject> object, |
| 2810 Handle<JSObject> holder, | 2513 Handle<JSObject> holder, |
| 2811 Handle<Name> name, | 2514 Handle<Name> name, |
| 2812 Handle<ExecutableAccessorInfo> callback) { | 2515 Handle<ExecutableAccessorInfo> callback) { |
| 2813 HandlerFrontend(object, receiver(), holder, name); | 2516 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2517 receiver(), holder, name); |
| 2814 | 2518 |
| 2815 // Stub never generated for non-global objects that require access | 2519 // Stub never generated for non-global objects that require access |
| 2816 // checks. | 2520 // checks. |
| 2817 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 2521 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 2818 | 2522 |
| 2819 __ push(receiver()); // Receiver. | 2523 __ push(receiver()); // Receiver. |
| 2820 __ li(at, Operand(callback)); // Callback info. | 2524 __ li(at, Operand(callback)); // Callback info. |
| 2821 __ push(at); | 2525 __ push(at); |
| 2822 __ li(at, Operand(name)); | 2526 __ li(at, Operand(name)); |
| 2823 __ Push(at, value()); | 2527 __ Push(at, value()); |
| 2824 | 2528 |
| 2825 // Do tail-call to the runtime system. | 2529 // Do tail-call to the runtime system. |
| 2826 ExternalReference store_callback_property = | 2530 ExternalReference store_callback_property = |
| 2827 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2531 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2828 __ TailCallExternalReference(store_callback_property, 4, 1); | 2532 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2829 | 2533 |
| 2830 // Return the generated code. | 2534 // Return the generated code. |
| 2831 return GetCode(kind(), Code::FAST, name); | 2535 return GetCode(kind(), Code::FAST, name); |
| 2832 } | 2536 } |
| 2833 | 2537 |
| 2834 | 2538 |
| 2835 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2539 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2836 Handle<JSObject> object, | 2540 Handle<JSObject> object, |
| 2837 Handle<JSObject> holder, | 2541 Handle<JSObject> holder, |
| 2838 Handle<Name> name, | 2542 Handle<Name> name, |
| 2839 const CallOptimization& call_optimization) { | 2543 const CallOptimization& call_optimization) { |
| 2840 HandlerFrontend(object, receiver(), holder, name); | 2544 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2545 receiver(), holder, name); |
| 2841 | 2546 |
| 2842 Register values[] = { value() }; | 2547 Register values[] = { value() }; |
| 2843 GenerateFastApiCall( | 2548 GenerateFastApiCall( |
| 2844 masm(), call_optimization, receiver(), scratch3(), 1, values); | 2549 masm(), call_optimization, receiver(), scratch3(), 1, values); |
| 2845 | 2550 |
| 2846 // Return the generated code. | 2551 // Return the generated code. |
| 2847 return GetCode(kind(), Code::FAST, name); | 2552 return GetCode(kind(), Code::FAST, name); |
| 2848 } | 2553 } |
| 2849 | 2554 |
| 2850 | 2555 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2908 if (object->IsJSGlobalProxy()) { | 2613 if (object->IsJSGlobalProxy()) { |
| 2909 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | 2614 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); |
| 2910 } | 2615 } |
| 2911 | 2616 |
| 2912 // Stub is never generated for non-global objects that require access | 2617 // Stub is never generated for non-global objects that require access |
| 2913 // checks. | 2618 // checks. |
| 2914 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2619 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2915 | 2620 |
| 2916 __ Push(receiver(), this->name(), value()); | 2621 __ Push(receiver(), this->name(), value()); |
| 2917 | 2622 |
| 2918 __ li(scratch1(), Operand(Smi::FromInt(strict_mode()))); | |
| 2919 __ push(scratch1()); // strict mode | |
| 2920 | |
| 2921 // Do tail-call to the runtime system. | 2623 // Do tail-call to the runtime system. |
| 2922 ExternalReference store_ic_property = | 2624 ExternalReference store_ic_property = |
| 2923 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2625 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2924 __ TailCallExternalReference(store_ic_property, 4, 1); | 2626 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 2925 | 2627 |
| 2926 // Handle store cache miss. | 2628 // Handle store cache miss. |
| 2927 __ bind(&miss); | 2629 __ bind(&miss); |
| 2928 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2630 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2929 | 2631 |
| 2930 // Return the generated code. | 2632 // Return the generated code. |
| 2931 return GetCode(kind(), Code::FAST, name); | 2633 return GetCode(kind(), Code::FAST, name); |
| 2932 } | 2634 } |
| 2933 | 2635 |
| 2934 | 2636 |
| 2935 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2637 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, |
| 2936 Handle<Object> object, | 2638 Handle<JSObject> last, |
| 2937 Handle<JSObject> last, | 2639 Handle<Name> name) { |
| 2938 Handle<Name> name, | 2640 NonexistentHandlerFrontend(type, last, name); |
| 2939 Handle<JSGlobalObject> global) { | |
| 2940 NonexistentHandlerFrontend(object, last, name, global); | |
| 2941 | 2641 |
| 2942 // Return undefined if maps of the full prototype chain is still the same. | 2642 // Return undefined if maps of the full prototype chain is still the same. |
| 2943 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 2643 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 2944 __ Ret(); | 2644 __ Ret(); |
| 2945 | 2645 |
| 2946 // Return the generated code. | 2646 // Return the generated code. |
| 2947 return GetCode(kind(), Code::FAST, name); | 2647 return GetCode(kind(), Code::FAST, name); |
| 2948 } | 2648 } |
| 2949 | 2649 |
| 2950 | 2650 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3023 } | 2723 } |
| 3024 __ Ret(); | 2724 __ Ret(); |
| 3025 } | 2725 } |
| 3026 | 2726 |
| 3027 | 2727 |
| 3028 #undef __ | 2728 #undef __ |
| 3029 #define __ ACCESS_MASM(masm()) | 2729 #define __ ACCESS_MASM(masm()) |
| 3030 | 2730 |
| 3031 | 2731 |
| 3032 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2732 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3033 Handle<Object> object, | 2733 Handle<Type> type, |
| 3034 Handle<GlobalObject> global, | 2734 Handle<GlobalObject> global, |
| 3035 Handle<PropertyCell> cell, | 2735 Handle<PropertyCell> cell, |
| 3036 Handle<Name> name, | 2736 Handle<Name> name, |
| 3037 bool is_dont_delete) { | 2737 bool is_dont_delete) { |
| 3038 Label miss; | 2738 Label miss; |
| 3039 | 2739 |
| 3040 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 2740 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 3041 | 2741 |
| 3042 // Get the value from the cell. | 2742 // Get the value from the cell. |
| 3043 __ li(a3, Operand(cell)); | 2743 __ li(a3, Operand(cell)); |
| 3044 __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset)); | 2744 __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset)); |
| 3045 | 2745 |
| 3046 // Check for deleted property if property can actually be deleted. | 2746 // Check for deleted property if property can actually be deleted. |
| 3047 if (!is_dont_delete) { | 2747 if (!is_dont_delete) { |
| 3048 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2748 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 3049 __ Branch(&miss, eq, t0, Operand(at)); | 2749 __ Branch(&miss, eq, t0, Operand(at)); |
| 3050 } | 2750 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3183 // ----------------------------------- | 2883 // ----------------------------------- |
| 3184 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2884 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3185 } | 2885 } |
| 3186 | 2886 |
| 3187 | 2887 |
| 3188 #undef __ | 2888 #undef __ |
| 3189 | 2889 |
| 3190 } } // namespace v8::internal | 2890 } } // namespace v8::internal |
| 3191 | 2891 |
| 3192 #endif // V8_TARGET_ARCH_MIPS | 2892 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |