| 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 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 __ push(receiver); | 791 __ push(receiver); |
| 792 __ push(holder); | 792 __ push(holder); |
| 793 } | 793 } |
| 794 | 794 |
| 795 | 795 |
| 796 static void CompileCallLoadPropertyWithInterceptor( | 796 static void CompileCallLoadPropertyWithInterceptor( |
| 797 MacroAssembler* masm, | 797 MacroAssembler* masm, |
| 798 Register receiver, | 798 Register receiver, |
| 799 Register holder, | 799 Register holder, |
| 800 Register name, | 800 Register name, |
| 801 Handle<JSObject> holder_obj) { | 801 Handle<JSObject> holder_obj, |
| 802 IC::UtilityId id) { |
| 802 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 803 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 803 | 804 __ CallExternalReference( |
| 804 ExternalReference ref = | 805 ExternalReference(IC_Utility(id), masm->isolate()), |
| 805 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 806 StubCache::kInterceptorArgsLength); |
| 806 masm->isolate()); | |
| 807 __ mov(r0, Operand(StubCache::kInterceptorArgsLength)); | |
| 808 __ mov(r1, Operand(ref)); | |
| 809 | |
| 810 CEntryStub stub(1); | |
| 811 __ CallStub(&stub); | |
| 812 } | 807 } |
| 813 | 808 |
| 814 | 809 |
| 815 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 810 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 816 | 811 |
| 817 // Reserves space for the extra arguments to API function in the | 812 // Reserves space for the extra arguments to API function in the |
| 818 // caller's frame. | 813 // caller's frame. |
| 819 // | 814 // |
| 820 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. | 815 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
| 821 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 816 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | 1026 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |
| 1032 scratch1, scratch2); | 1027 scratch1, scratch2); |
| 1033 ReserveSpaceForFastApiCall(masm, scratch1); | 1028 ReserveSpaceForFastApiCall(masm, scratch1); |
| 1034 } | 1029 } |
| 1035 | 1030 |
| 1036 // Check that the maps from receiver to interceptor's holder | 1031 // Check that the maps from receiver to interceptor's holder |
| 1037 // haven't changed and thus we can invoke interceptor. | 1032 // haven't changed and thus we can invoke interceptor. |
| 1038 Label miss_cleanup; | 1033 Label miss_cleanup; |
| 1039 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 1034 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 1040 Register holder = | 1035 Register holder = |
| 1041 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 1036 stub_compiler_->CheckPrototypes( |
| 1042 scratch1, scratch2, scratch3, | 1037 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 1043 name, depth1, miss); | 1038 interceptor_holder, scratch1, scratch2, scratch3, |
| 1039 name, depth1, miss); |
| 1044 | 1040 |
| 1045 // Invoke an interceptor and if it provides a value, | 1041 // Invoke an interceptor and if it provides a value, |
| 1046 // branch to |regular_invoke|. | 1042 // branch to |regular_invoke|. |
| 1047 Label regular_invoke; | 1043 Label regular_invoke; |
| 1048 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 1044 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
| 1049 ®ular_invoke); | 1045 ®ular_invoke); |
| 1050 | 1046 |
| 1051 // Interceptor returned nothing for this property. Try to use cached | 1047 // Interceptor returned nothing for this property. Try to use cached |
| 1052 // constant function. | 1048 // constant function. |
| 1053 | 1049 |
| 1054 // Check that the maps from interceptor's holder to constant function's | 1050 // Check that the maps from interceptor's holder to constant function's |
| 1055 // holder haven't changed and thus we can use cached constant function. | 1051 // holder haven't changed and thus we can use cached constant function. |
| 1056 if (*interceptor_holder != lookup->holder()) { | 1052 if (*interceptor_holder != lookup->holder()) { |
| 1057 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 1053 stub_compiler_->CheckPrototypes( |
| 1058 Handle<JSObject>(lookup->holder()), | 1054 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver, |
| 1059 scratch1, scratch2, scratch3, | 1055 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 1060 name, depth2, miss); | 1056 name, depth2, miss); |
| 1061 } else { | 1057 } else { |
| 1062 // CheckPrototypes has a side effect of fetching a 'holder' | 1058 // CheckPrototypes has a side effect of fetching a 'holder' |
| 1063 // for API (object which is instanceof for the signature). It's | 1059 // for API (object which is instanceof for the signature). It's |
| 1064 // safe to omit it here, as if present, it should be fetched | 1060 // safe to omit it here, as if present, it should be fetched |
| 1065 // by the previous CheckPrototypes. | 1061 // by the previous CheckPrototypes. |
| 1066 ASSERT(depth2 == kInvalidProtoDepth); | 1062 ASSERT(depth2 == kInvalidProtoDepth); |
| 1067 } | 1063 } |
| 1068 | 1064 |
| 1069 // Invoke function. | 1065 // Invoke function. |
| 1070 if (can_do_fast_api_call) { | 1066 if (can_do_fast_api_call) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1097 void CompileRegular(MacroAssembler* masm, | 1093 void CompileRegular(MacroAssembler* masm, |
| 1098 Handle<JSObject> object, | 1094 Handle<JSObject> object, |
| 1099 Register receiver, | 1095 Register receiver, |
| 1100 Register scratch1, | 1096 Register scratch1, |
| 1101 Register scratch2, | 1097 Register scratch2, |
| 1102 Register scratch3, | 1098 Register scratch3, |
| 1103 Handle<Name> name, | 1099 Handle<Name> name, |
| 1104 Handle<JSObject> interceptor_holder, | 1100 Handle<JSObject> interceptor_holder, |
| 1105 Label* miss_label) { | 1101 Label* miss_label) { |
| 1106 Register holder = | 1102 Register holder = |
| 1107 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 1103 stub_compiler_->CheckPrototypes( |
| 1108 scratch1, scratch2, scratch3, | 1104 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 1109 name, miss_label); | 1105 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 1110 | 1106 |
| 1111 // Call a runtime function to load the interceptor property. | 1107 // Call a runtime function to load the interceptor property. |
| 1112 FrameScope scope(masm, StackFrame::INTERNAL); | 1108 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1113 // Save the name_ register across the call. | 1109 // Save the name_ register across the call. |
| 1114 __ push(name_); | 1110 __ push(name_); |
| 1115 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 1111 |
| 1116 __ CallExternalReference( | 1112 CompileCallLoadPropertyWithInterceptor( |
| 1117 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 1113 masm, receiver, holder, name_, interceptor_holder, |
| 1118 masm->isolate()), | 1114 IC::kLoadPropertyWithInterceptorForCall); |
| 1119 StubCache::kInterceptorArgsLength); | 1115 |
| 1120 // Restore the name_ register. | 1116 // Restore the name_ register. |
| 1121 __ pop(name_); | 1117 __ pop(name_); |
| 1122 // Leave the internal frame. | 1118 // Leave the internal frame. |
| 1123 } | 1119 } |
| 1124 | 1120 |
| 1125 void LoadWithInterceptor(MacroAssembler* masm, | 1121 void LoadWithInterceptor(MacroAssembler* masm, |
| 1126 Register receiver, | 1122 Register receiver, |
| 1127 Register holder, | 1123 Register holder, |
| 1128 Handle<JSObject> holder_obj, | 1124 Handle<JSObject> holder_obj, |
| 1129 Register scratch, | 1125 Register scratch, |
| 1130 Label* interceptor_succeeded) { | 1126 Label* interceptor_succeeded) { |
| 1131 { | 1127 { |
| 1132 FrameScope scope(masm, StackFrame::INTERNAL); | 1128 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1133 __ Push(holder, name_); | 1129 __ Push(holder, name_); |
| 1134 CompileCallLoadPropertyWithInterceptor(masm, | 1130 CompileCallLoadPropertyWithInterceptor( |
| 1135 receiver, | 1131 masm, receiver, holder, name_, holder_obj, |
| 1136 holder, | 1132 IC::kLoadPropertyWithInterceptorOnly); |
| 1137 name_, | |
| 1138 holder_obj); | |
| 1139 __ pop(name_); // Restore the name. | 1133 __ pop(name_); // Restore the name. |
| 1140 __ pop(receiver); // Restore the holder. | 1134 __ pop(receiver); // Restore the holder. |
| 1141 } | 1135 } |
| 1142 // If interceptor returns no-result sentinel, call the constant function. | 1136 // If interceptor returns no-result sentinel, call the constant function. |
| 1143 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1137 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1144 __ cmp(r0, scratch); | 1138 __ cmp(r0, scratch); |
| 1145 __ b(ne, interceptor_succeeded); | 1139 __ b(ne, interceptor_succeeded); |
| 1146 } | 1140 } |
| 1147 | 1141 |
| 1148 StubCompiler* stub_compiler_; | 1142 StubCompiler* stub_compiler_; |
| 1149 const ParameterCount& arguments_; | 1143 const ParameterCount& arguments_; |
| 1150 Register name_; | 1144 Register name_; |
| 1151 Code::ExtraICState extra_ic_state_; | 1145 Code::ExtraICState extra_ic_state_; |
| 1152 }; | 1146 }; |
| 1153 | 1147 |
| 1154 | 1148 |
| 1155 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1156 Handle<JSObject> object, | |
| 1157 Handle<JSObject> holder, | |
| 1158 Handle<Name> name, | |
| 1159 Register scratch, | |
| 1160 Label* miss) { | |
| 1161 Handle<JSObject> current = object; | |
| 1162 while (!current.is_identical_to(holder)) { | |
| 1163 if (current->IsJSGlobalObject()) { | |
| 1164 GenerateCheckPropertyCell(masm, | |
| 1165 Handle<JSGlobalObject>::cast(current), | |
| 1166 name, | |
| 1167 scratch, | |
| 1168 miss); | |
| 1169 } | |
| 1170 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1171 } | |
| 1172 } | |
| 1173 | |
| 1174 | |
| 1175 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1149 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1176 __ Jump(code, RelocInfo::CODE_TARGET); | 1150 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1177 } | 1151 } |
| 1178 | 1152 |
| 1179 | 1153 |
| 1180 #undef __ | 1154 #undef __ |
| 1181 #define __ ACCESS_MASM(masm()) | 1155 #define __ ACCESS_MASM(masm()) |
| 1182 | 1156 |
| 1183 | 1157 |
| 1184 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1158 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1185 Register object_reg, | 1159 Register object_reg, |
| 1186 Handle<JSObject> holder, | 1160 Handle<JSObject> holder, |
| 1187 Register holder_reg, | 1161 Register holder_reg, |
| 1188 Register scratch1, | 1162 Register scratch1, |
| 1189 Register scratch2, | 1163 Register scratch2, |
| 1190 Handle<Name> name, | 1164 Handle<Name> name, |
| 1191 int save_at_depth, | 1165 int save_at_depth, |
| 1192 Label* miss, | 1166 Label* miss, |
| 1193 PrototypeCheckType check) { | 1167 PrototypeCheckType check) { |
| 1168 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1194 // Make sure that the type feedback oracle harvests the receiver map. | 1169 // Make sure that the type feedback oracle harvests the receiver map. |
| 1195 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1170 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1196 __ mov(scratch1, Operand(Handle<Map>(object->map()))); | 1171 __ mov(scratch1, Operand(receiver_map)); |
| 1197 | 1172 |
| 1198 Handle<JSObject> first = object; | |
| 1199 // Make sure there's no overlap between holder and object registers. | 1173 // Make sure there's no overlap between holder and object registers. |
| 1200 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1174 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1201 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1175 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1202 && !scratch2.is(scratch1)); | 1176 && !scratch2.is(scratch1)); |
| 1203 | 1177 |
| 1204 // Keep track of the current object in register reg. | 1178 // Keep track of the current object in register reg. |
| 1205 Register reg = object_reg; | 1179 Register reg = object_reg; |
| 1206 int depth = 0; | 1180 int depth = 0; |
| 1207 | 1181 |
| 1208 typedef FunctionCallbackArguments FCA; | 1182 typedef FunctionCallbackArguments FCA; |
| 1209 if (save_at_depth == depth) { | 1183 if (save_at_depth == depth) { |
| 1210 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | 1184 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |
| 1211 } | 1185 } |
| 1212 | 1186 |
| 1213 // Check the maps in the prototype chain. | 1187 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1214 // Traverse the prototype chain from the object and do map checks. | 1188 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1215 Handle<JSObject> current = object; | 1189 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1216 while (!current.is_identical_to(holder)) { | 1190 Handle<Map> current_map = receiver_map; |
| 1191 Handle<Map> holder_map(holder->map()); |
| 1192 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1193 // fast and global objects or do negative lookup for normal objects. |
| 1194 while (!current_map.is_identical_to(holder_map)) { |
| 1217 ++depth; | 1195 ++depth; |
| 1218 | 1196 |
| 1219 // Only global objects and objects that do not require access | 1197 // Only global objects and objects that do not require access |
| 1220 // checks are allowed in stubs. | 1198 // checks are allowed in stubs. |
| 1221 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1199 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1200 !current_map->is_access_check_needed()); |
| 1222 | 1201 |
| 1223 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1202 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1224 if (!current->HasFastProperties() && | 1203 if (current_map->is_dictionary_map() && |
| 1225 !current->IsJSGlobalObject() && | 1204 !current_map->IsJSGlobalObjectMap() && |
| 1226 !current->IsJSGlobalProxy()) { | 1205 !current_map->IsJSGlobalProxyMap()) { |
| 1227 if (!name->IsUniqueName()) { | 1206 if (!name->IsUniqueName()) { |
| 1228 ASSERT(name->IsString()); | 1207 ASSERT(name->IsString()); |
| 1229 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1208 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1230 } | 1209 } |
| 1231 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1210 ASSERT(current.is_null() || |
| 1211 current->property_dictionary()->FindEntry(*name) == |
| 1232 NameDictionary::kNotFound); | 1212 NameDictionary::kNotFound); |
| 1233 | 1213 |
| 1234 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1214 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1235 scratch1, scratch2); | 1215 scratch1, scratch2); |
| 1236 | 1216 |
| 1237 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1217 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1238 reg = holder_reg; // From now on the object will be in holder_reg. | 1218 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1239 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1219 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 1240 } else { | 1220 } else { |
| 1241 Register map_reg = scratch1; | 1221 Register map_reg = scratch1; |
| 1242 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1222 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1243 Handle<Map> current_map(current->map()); | |
| 1244 // CheckMap implicitly loads the map of |reg| into |map_reg|. | 1223 // CheckMap implicitly loads the map of |reg| into |map_reg|. |
| 1245 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); | 1224 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1246 } else { | 1225 } else { |
| 1247 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1226 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1248 } | 1227 } |
| 1249 | 1228 |
| 1250 // Check access rights to the global object. This has to happen after | 1229 // Check access rights to the global object. This has to happen after |
| 1251 // the map check so that we know that the object is actually a global | 1230 // the map check so that we know that the object is actually a global |
| 1252 // object. | 1231 // object. |
| 1253 if (current->IsJSGlobalProxy()) { | 1232 if (current_map->IsJSGlobalProxyMap()) { |
| 1254 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1233 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1234 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1235 GenerateCheckPropertyCell( |
| 1236 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1237 scratch2, miss); |
| 1255 } | 1238 } |
| 1239 |
| 1256 reg = holder_reg; // From now on the object will be in holder_reg. | 1240 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1257 | 1241 |
| 1258 if (heap()->InNewSpace(*prototype)) { | 1242 if (heap()->InNewSpace(*prototype)) { |
| 1259 // The prototype is in new space; we cannot store a reference to it | 1243 // The prototype is in new space; we cannot store a reference to it |
| 1260 // in the code. Load it from the map. | 1244 // in the code. Load it from the map. |
| 1261 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 1245 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| 1262 } else { | 1246 } else { |
| 1263 // The prototype is in old space; load it directly. | 1247 // The prototype is in old space; load it directly. |
| 1264 __ mov(reg, Operand(prototype)); | 1248 __ mov(reg, Operand(prototype)); |
| 1265 } | 1249 } |
| 1266 } | 1250 } |
| 1267 | 1251 |
| 1268 if (save_at_depth == depth) { | 1252 if (save_at_depth == depth) { |
| 1269 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); | 1253 __ str(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |
| 1270 } | 1254 } |
| 1271 | 1255 |
| 1272 // Go to the next object in the prototype chain. | 1256 // Go to the next object in the prototype chain. |
| 1273 current = prototype; | 1257 current = prototype; |
| 1258 current_map = handle(current->map()); |
| 1274 } | 1259 } |
| 1275 | 1260 |
| 1276 // Log the check depth. | 1261 // Log the check depth. |
| 1277 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1262 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1278 | 1263 |
| 1279 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1264 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1280 // Check the holder map. | 1265 // Check the holder map. |
| 1281 __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss, | 1266 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |
| 1282 DONT_DO_SMI_CHECK); | |
| 1283 } | 1267 } |
| 1284 | 1268 |
| 1285 // Perform security check for access to the global object. | 1269 // Perform security check for access to the global object. |
| 1286 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1270 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1287 if (holder->IsJSGlobalProxy()) { | 1271 !current_map->is_access_check_needed()); |
| 1272 if (current_map->IsJSGlobalProxyMap()) { |
| 1288 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1273 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1289 } | 1274 } |
| 1290 | 1275 |
| 1291 // If we've skipped any global objects, it's not enough to verify that | |
| 1292 // their maps haven't changed. We also need to check that the property | |
| 1293 // cell for the property is still empty. | |
| 1294 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1295 | |
| 1296 // Return the register containing the holder. | 1276 // Return the register containing the holder. |
| 1297 return reg; | 1277 return reg; |
| 1298 } | 1278 } |
| 1299 | 1279 |
| 1300 | 1280 |
| 1301 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1281 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1302 if (!miss->is_unused()) { | 1282 if (!miss->is_unused()) { |
| 1303 Label success; | 1283 Label success; |
| 1304 __ b(&success); | 1284 __ b(&success); |
| 1305 __ bind(miss); | 1285 __ bind(miss); |
| 1306 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1286 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1307 __ bind(&success); | 1287 __ bind(&success); |
| 1308 } | 1288 } |
| 1309 } | 1289 } |
| 1310 | 1290 |
| 1311 | 1291 |
| 1312 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1292 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1313 if (!miss->is_unused()) { | 1293 if (!miss->is_unused()) { |
| 1314 Label success; | 1294 Label success; |
| 1315 __ b(&success); | 1295 __ b(&success); |
| 1316 GenerateRestoreName(masm(), miss, name); | 1296 GenerateRestoreName(masm(), miss, name); |
| 1317 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1297 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1318 __ bind(&success); | 1298 __ bind(&success); |
| 1319 } | 1299 } |
| 1320 } | 1300 } |
| 1321 | 1301 |
| 1322 | 1302 |
| 1323 Register LoadStubCompiler::CallbackHandlerFrontend( | 1303 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1324 Handle<Object> object, | 1304 Handle<Type> type, |
| 1325 Register object_reg, | 1305 Register object_reg, |
| 1326 Handle<JSObject> holder, | 1306 Handle<JSObject> holder, |
| 1327 Handle<Name> name, | 1307 Handle<Name> name, |
| 1328 Handle<Object> callback) { | 1308 Handle<Object> callback) { |
| 1329 Label miss; | 1309 Label miss; |
| 1330 | 1310 |
| 1331 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1311 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1332 | 1312 |
| 1333 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1313 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1334 ASSERT(!reg.is(scratch2())); | 1314 ASSERT(!reg.is(scratch2())); |
| 1335 ASSERT(!reg.is(scratch3())); | 1315 ASSERT(!reg.is(scratch3())); |
| 1336 ASSERT(!reg.is(scratch4())); | 1316 ASSERT(!reg.is(scratch4())); |
| 1337 | 1317 |
| 1338 // Load the properties dictionary. | 1318 // Load the properties dictionary. |
| 1339 Register dictionary = scratch4(); | 1319 Register dictionary = scratch4(); |
| 1340 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 1320 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 1341 | 1321 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 { | 1489 { |
| 1510 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1490 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1511 if (must_preserve_receiver_reg) { | 1491 if (must_preserve_receiver_reg) { |
| 1512 __ Push(receiver(), holder_reg, this->name()); | 1492 __ Push(receiver(), holder_reg, this->name()); |
| 1513 } else { | 1493 } else { |
| 1514 __ Push(holder_reg, this->name()); | 1494 __ Push(holder_reg, this->name()); |
| 1515 } | 1495 } |
| 1516 // Invoke an interceptor. Note: map checks from receiver to | 1496 // Invoke an interceptor. Note: map checks from receiver to |
| 1517 // interceptor's holder has been compiled before (see a caller | 1497 // interceptor's holder has been compiled before (see a caller |
| 1518 // of this method.) | 1498 // of this method.) |
| 1519 CompileCallLoadPropertyWithInterceptor(masm(), | 1499 CompileCallLoadPropertyWithInterceptor( |
| 1520 receiver(), | 1500 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| 1521 holder_reg, | 1501 IC::kLoadPropertyWithInterceptorOnly); |
| 1522 this->name(), | 1502 |
| 1523 interceptor_holder); | |
| 1524 // Check if interceptor provided a value for property. If it's | 1503 // Check if interceptor provided a value for property. If it's |
| 1525 // the case, return immediately. | 1504 // the case, return immediately. |
| 1526 Label interceptor_failed; | 1505 Label interceptor_failed; |
| 1527 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 1506 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
| 1528 __ cmp(r0, scratch1()); | 1507 __ cmp(r0, scratch1()); |
| 1529 __ b(eq, &interceptor_failed); | 1508 __ b(eq, &interceptor_failed); |
| 1530 frame_scope.GenerateLeaveFrame(); | 1509 frame_scope.GenerateLeaveFrame(); |
| 1531 __ Ret(); | 1510 __ Ret(); |
| 1532 | 1511 |
| 1533 __ bind(&interceptor_failed); | 1512 __ bind(&interceptor_failed); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 ASSERT(holder->IsGlobalObject()); | 1548 ASSERT(holder->IsGlobalObject()); |
| 1570 | 1549 |
| 1571 // Get the number of arguments. | 1550 // Get the number of arguments. |
| 1572 const int argc = arguments().immediate(); | 1551 const int argc = arguments().immediate(); |
| 1573 | 1552 |
| 1574 // Get the receiver from the stack. | 1553 // Get the receiver from the stack. |
| 1575 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1554 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1576 | 1555 |
| 1577 // Check that the maps haven't changed. | 1556 // Check that the maps haven't changed. |
| 1578 __ JumpIfSmi(r0, miss); | 1557 __ JumpIfSmi(r0, miss); |
| 1579 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); | 1558 CheckPrototypes( |
| 1559 IC::CurrentTypeOf(object, isolate()), r0, holder, r3, r1, r4, name, miss); |
| 1580 } | 1560 } |
| 1581 | 1561 |
| 1582 | 1562 |
| 1583 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1563 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1584 Handle<Cell> cell, | 1564 Handle<Cell> cell, |
| 1585 Handle<JSFunction> function, | 1565 Handle<JSFunction> function, |
| 1586 Label* miss) { | 1566 Label* miss) { |
| 1587 // Get the value from the cell. | 1567 // Get the value from the cell. |
| 1588 __ mov(r3, Operand(cell)); | 1568 __ mov(r3, Operand(cell)); |
| 1589 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | 1569 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 GenerateNameCheck(name, &miss); | 1612 GenerateNameCheck(name, &miss); |
| 1633 | 1613 |
| 1634 const int argc = arguments().immediate(); | 1614 const int argc = arguments().immediate(); |
| 1635 | 1615 |
| 1636 // Get the receiver of the function from the stack into r0. | 1616 // Get the receiver of the function from the stack into r0. |
| 1637 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1617 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1638 // Check that the receiver isn't a smi. | 1618 // Check that the receiver isn't a smi. |
| 1639 __ JumpIfSmi(r0, &miss); | 1619 __ JumpIfSmi(r0, &miss); |
| 1640 | 1620 |
| 1641 // Do the right check and compute the holder register. | 1621 // Do the right check and compute the holder register. |
| 1642 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); | 1622 Register reg = CheckPrototypes( |
| 1623 IC::CurrentTypeOf(object, isolate()), |
| 1624 r0, holder, r1, r3, r4, name, &miss); |
| 1643 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | 1625 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
| 1644 index.translate(holder), Representation::Tagged()); | 1626 index.translate(holder), Representation::Tagged()); |
| 1645 | 1627 |
| 1646 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 1628 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| 1647 | 1629 |
| 1648 // Handle call cache miss. | 1630 // Handle call cache miss. |
| 1649 __ bind(&miss); | 1631 __ bind(&miss); |
| 1650 GenerateMissBranch(); | 1632 GenerateMissBranch(); |
| 1651 | 1633 |
| 1652 // Return the generated code. | 1634 // Return the generated code. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1668 GenerateNameCheck(name, &miss); | 1650 GenerateNameCheck(name, &miss); |
| 1669 Register receiver = r1; | 1651 Register receiver = r1; |
| 1670 | 1652 |
| 1671 if (cell.is_null()) { | 1653 if (cell.is_null()) { |
| 1672 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1654 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1673 | 1655 |
| 1674 // Check that the receiver isn't a smi. | 1656 // Check that the receiver isn't a smi. |
| 1675 __ JumpIfSmi(receiver, &miss); | 1657 __ JumpIfSmi(receiver, &miss); |
| 1676 | 1658 |
| 1677 // Check that the maps haven't changed. | 1659 // Check that the maps haven't changed. |
| 1678 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, | 1660 CheckPrototypes( |
| 1679 r4, name, &miss); | 1661 IC::CurrentTypeOf(object, isolate()), receiver, holder, |
| 1662 r3, r0, r4, name, &miss); |
| 1680 } else { | 1663 } else { |
| 1681 ASSERT(cell->value() == *function); | 1664 ASSERT(cell->value() == *function); |
| 1682 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1665 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1683 &miss); | 1666 &miss); |
| 1684 GenerateLoadFunctionFromCell(cell, function, &miss); | 1667 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1685 } | 1668 } |
| 1686 | 1669 |
| 1687 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1670 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1688 site->SetElementsKind(GetInitialFastElementsKind()); | 1671 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1689 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1672 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 | 1712 |
| 1730 Register receiver = r1; | 1713 Register receiver = r1; |
| 1731 // Get the receiver from the stack | 1714 // Get the receiver from the stack |
| 1732 const int argc = arguments().immediate(); | 1715 const int argc = arguments().immediate(); |
| 1733 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1716 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1734 | 1717 |
| 1735 // Check that the receiver isn't a smi. | 1718 // Check that the receiver isn't a smi. |
| 1736 __ JumpIfSmi(receiver, &miss); | 1719 __ JumpIfSmi(receiver, &miss); |
| 1737 | 1720 |
| 1738 // Check that the maps haven't changed. | 1721 // Check that the maps haven't changed. |
| 1739 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4, | 1722 CheckPrototypes( |
| 1740 name, &miss); | 1723 IC::CurrentTypeOf(object, isolate()), receiver, holder, |
| 1724 r3, r0, r4, name, &miss); |
| 1741 | 1725 |
| 1742 if (argc == 0) { | 1726 if (argc == 0) { |
| 1743 // Nothing to do, just return the length. | 1727 // Nothing to do, just return the length. |
| 1744 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1728 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1745 __ Drop(argc + 1); | 1729 __ Drop(argc + 1); |
| 1746 __ Ret(); | 1730 __ Ret(); |
| 1747 } else { | 1731 } else { |
| 1748 Label call_builtin; | 1732 Label call_builtin; |
| 1749 | 1733 |
| 1750 if (argc == 1) { // Otherwise fall through to call the builtin. | 1734 if (argc == 1) { // Otherwise fall through to call the builtin. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1987 Register elements = r3; | 1971 Register elements = r3; |
| 1988 GenerateNameCheck(name, &miss); | 1972 GenerateNameCheck(name, &miss); |
| 1989 | 1973 |
| 1990 // Get the receiver from the stack | 1974 // Get the receiver from the stack |
| 1991 const int argc = arguments().immediate(); | 1975 const int argc = arguments().immediate(); |
| 1992 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1976 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1993 // Check that the receiver isn't a smi. | 1977 // Check that the receiver isn't a smi. |
| 1994 __ JumpIfSmi(receiver, &miss); | 1978 __ JumpIfSmi(receiver, &miss); |
| 1995 | 1979 |
| 1996 // Check that the maps haven't changed. | 1980 // Check that the maps haven't changed. |
| 1997 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, | 1981 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), receiver, holder, |
| 1998 r4, r0, name, &miss); | 1982 elements, r4, r0, name, &miss); |
| 1999 | 1983 |
| 2000 // Get the elements array of the object. | 1984 // Get the elements array of the object. |
| 2001 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1985 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 2002 | 1986 |
| 2003 // Check that the elements are in fast mode and writable. | 1987 // Check that the elements are in fast mode and writable. |
| 2004 __ CheckMap(elements, | 1988 __ CheckMap(elements, |
| 2005 r0, | 1989 r0, |
| 2006 Heap::kFixedArrayMapRootIndex, | 1990 Heap::kFixedArrayMapRootIndex, |
| 2007 &call_builtin, | 1991 &call_builtin, |
| 2008 DONT_DO_SMI_CHECK); | 1992 DONT_DO_SMI_CHECK); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2077 index_out_of_range_label = &miss; | 2061 index_out_of_range_label = &miss; |
| 2078 } | 2062 } |
| 2079 GenerateNameCheck(name, &name_miss); | 2063 GenerateNameCheck(name, &name_miss); |
| 2080 | 2064 |
| 2081 // Check that the maps starting from the prototype haven't changed. | 2065 // Check that the maps starting from the prototype haven't changed. |
| 2082 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2066 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2083 Context::STRING_FUNCTION_INDEX, | 2067 Context::STRING_FUNCTION_INDEX, |
| 2084 r0, | 2068 r0, |
| 2085 &miss); | 2069 &miss); |
| 2086 ASSERT(!object.is_identical_to(holder)); | 2070 ASSERT(!object.is_identical_to(holder)); |
| 2071 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); |
| 2087 CheckPrototypes( | 2072 CheckPrototypes( |
| 2088 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2073 IC::CurrentTypeOf(prototype, isolate()), |
| 2089 r0, holder, r1, r3, r4, name, &miss); | 2074 r0, holder, r1, r3, r4, name, &miss); |
| 2090 | 2075 |
| 2091 Register receiver = r1; | 2076 Register receiver = r1; |
| 2092 Register index = r4; | 2077 Register index = r4; |
| 2093 Register result = r0; | 2078 Register result = r0; |
| 2094 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 2079 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2095 if (argc > 0) { | 2080 if (argc > 0) { |
| 2096 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 2081 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2097 } else { | 2082 } else { |
| 2098 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2083 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 index_out_of_range_label = &miss; | 2144 index_out_of_range_label = &miss; |
| 2160 } | 2145 } |
| 2161 GenerateNameCheck(name, &name_miss); | 2146 GenerateNameCheck(name, &name_miss); |
| 2162 | 2147 |
| 2163 // Check that the maps starting from the prototype haven't changed. | 2148 // Check that the maps starting from the prototype haven't changed. |
| 2164 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2149 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2165 Context::STRING_FUNCTION_INDEX, | 2150 Context::STRING_FUNCTION_INDEX, |
| 2166 r0, | 2151 r0, |
| 2167 &miss); | 2152 &miss); |
| 2168 ASSERT(!object.is_identical_to(holder)); | 2153 ASSERT(!object.is_identical_to(holder)); |
| 2154 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); |
| 2169 CheckPrototypes( | 2155 CheckPrototypes( |
| 2170 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2156 IC::CurrentTypeOf(prototype, isolate()), |
| 2171 r0, holder, r1, r3, r4, name, &miss); | 2157 r0, holder, r1, r3, r4, name, &miss); |
| 2172 | 2158 |
| 2173 Register receiver = r0; | 2159 Register receiver = r0; |
| 2174 Register index = r4; | 2160 Register index = r4; |
| 2175 Register scratch = r3; | 2161 Register scratch = r3; |
| 2176 Register result = r0; | 2162 Register result = r0; |
| 2177 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 2163 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2178 if (argc > 0) { | 2164 if (argc > 0) { |
| 2179 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 2165 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2180 } else { | 2166 } else { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2222 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2237 | 2223 |
| 2238 Label miss; | 2224 Label miss; |
| 2239 GenerateNameCheck(name, &miss); | 2225 GenerateNameCheck(name, &miss); |
| 2240 | 2226 |
| 2241 if (cell.is_null()) { | 2227 if (cell.is_null()) { |
| 2242 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2228 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2243 | 2229 |
| 2244 __ JumpIfSmi(r1, &miss); | 2230 __ JumpIfSmi(r1, &miss); |
| 2245 | 2231 |
| 2246 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, | 2232 CheckPrototypes( |
| 2247 name, &miss); | 2233 IC::CurrentTypeOf(object, isolate()), |
| 2234 r1, holder, r0, r3, r4, name, &miss); |
| 2248 } else { | 2235 } else { |
| 2249 ASSERT(cell->value() == *function); | 2236 ASSERT(cell->value() == *function); |
| 2250 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2237 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2251 &miss); | 2238 &miss); |
| 2252 GenerateLoadFunctionFromCell(cell, function, &miss); | 2239 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2253 } | 2240 } |
| 2254 | 2241 |
| 2255 // Load the char code argument. | 2242 // Load the char code argument. |
| 2256 Register code = r1; | 2243 Register code = r1; |
| 2257 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 2244 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 // If the object is not a JSObject or we got an unexpected number of | 2293 // If the object is not a JSObject or we got an unexpected number of |
| 2307 // arguments, bail out to the regular call. | 2294 // arguments, bail out to the regular call. |
| 2308 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2295 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2309 | 2296 |
| 2310 Label miss, slow; | 2297 Label miss, slow; |
| 2311 GenerateNameCheck(name, &miss); | 2298 GenerateNameCheck(name, &miss); |
| 2312 | 2299 |
| 2313 if (cell.is_null()) { | 2300 if (cell.is_null()) { |
| 2314 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2301 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2315 __ JumpIfSmi(r1, &miss); | 2302 __ JumpIfSmi(r1, &miss); |
| 2316 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, | 2303 CheckPrototypes( |
| 2317 name, &miss); | 2304 IC::CurrentTypeOf(object, isolate()), |
| 2305 r1, holder, r0, r3, r4, name, &miss); |
| 2318 } else { | 2306 } else { |
| 2319 ASSERT(cell->value() == *function); | 2307 ASSERT(cell->value() == *function); |
| 2320 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2308 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2321 &miss); | 2309 &miss); |
| 2322 GenerateLoadFunctionFromCell(cell, function, &miss); | 2310 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2323 } | 2311 } |
| 2324 | 2312 |
| 2325 // Load the (only) argument into r0. | 2313 // Load the (only) argument into r0. |
| 2326 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2314 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
| 2327 | 2315 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2414 const int argc = arguments().immediate(); | 2402 const int argc = arguments().immediate(); |
| 2415 // If the object is not a JSObject or we got an unexpected number of | 2403 // If the object is not a JSObject or we got an unexpected number of |
| 2416 // arguments, bail out to the regular call. | 2404 // arguments, bail out to the regular call. |
| 2417 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2405 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2418 | 2406 |
| 2419 Label miss; | 2407 Label miss; |
| 2420 GenerateNameCheck(name, &miss); | 2408 GenerateNameCheck(name, &miss); |
| 2421 if (cell.is_null()) { | 2409 if (cell.is_null()) { |
| 2422 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2410 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2423 __ JumpIfSmi(r1, &miss); | 2411 __ JumpIfSmi(r1, &miss); |
| 2424 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, | 2412 CheckPrototypes( |
| 2425 name, &miss); | 2413 IC::CurrentTypeOf(object, isolate()), |
| 2414 r1, holder, r0, r3, r4, name, &miss); |
| 2426 } else { | 2415 } else { |
| 2427 ASSERT(cell->value() == *function); | 2416 ASSERT(cell->value() == *function); |
| 2428 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2417 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2429 &miss); | 2418 &miss); |
| 2430 GenerateLoadFunctionFromCell(cell, function, &miss); | 2419 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2431 } | 2420 } |
| 2432 | 2421 |
| 2433 // Load the (only) argument into r0. | 2422 // Load the (only) argument into r0. |
| 2434 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2423 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
| 2435 | 2424 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 | 2512 |
| 2524 // Check that the receiver isn't a smi. | 2513 // Check that the receiver isn't a smi. |
| 2525 __ JumpIfSmi(r1, &miss_before_stack_reserved); | 2514 __ JumpIfSmi(r1, &miss_before_stack_reserved); |
| 2526 | 2515 |
| 2527 __ IncrementCounter(counters->call_const(), 1, r0, r3); | 2516 __ IncrementCounter(counters->call_const(), 1, r0, r3); |
| 2528 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); | 2517 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); |
| 2529 | 2518 |
| 2530 ReserveSpaceForFastApiCall(masm(), r0); | 2519 ReserveSpaceForFastApiCall(masm(), r0); |
| 2531 | 2520 |
| 2532 // Check that the maps haven't changed and find a Holder as a side effect. | 2521 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2533 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name, | 2522 CheckPrototypes( |
| 2534 depth, &miss); | 2523 IC::CurrentTypeOf(object, isolate()), |
| 2524 r1, holder, r0, r3, r4, name, depth, &miss); |
| 2535 | 2525 |
| 2536 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2526 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
| 2537 | 2527 |
| 2538 __ bind(&miss); | 2528 __ bind(&miss); |
| 2539 FreeSpaceForFastApiCall(masm()); | 2529 FreeSpaceForFastApiCall(masm()); |
| 2540 | 2530 |
| 2541 __ bind(&miss_before_stack_reserved); | 2531 __ bind(&miss_before_stack_reserved); |
| 2542 GenerateMissBranch(); | 2532 GenerateMissBranch(); |
| 2543 | 2533 |
| 2544 // Return the generated code. | 2534 // Return the generated code. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2580 } | 2570 } |
| 2581 | 2571 |
| 2582 // Make sure that it's okay not to patch the on stack receiver | 2572 // Make sure that it's okay not to patch the on stack receiver |
| 2583 // unless we're doing a receiver map check. | 2573 // unless we're doing a receiver map check. |
| 2584 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2574 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2585 switch (check) { | 2575 switch (check) { |
| 2586 case RECEIVER_MAP_CHECK: | 2576 case RECEIVER_MAP_CHECK: |
| 2587 __ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3); | 2577 __ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3); |
| 2588 | 2578 |
| 2589 // Check that the maps haven't changed. | 2579 // Check that the maps haven't changed. |
| 2590 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, | 2580 CheckPrototypes( |
| 2591 name, &miss); | 2581 IC::CurrentTypeOf(object, isolate()), |
| 2582 r1, holder, r0, r3, r4, name, &miss); |
| 2592 | 2583 |
| 2593 // Patch the receiver on the stack with the global proxy if | 2584 // Patch the receiver on the stack with the global proxy if |
| 2594 // necessary. | 2585 // necessary. |
| 2595 if (object->IsGlobalObject()) { | 2586 if (object->IsGlobalObject()) { |
| 2596 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2587 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2597 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2588 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
| 2598 } | 2589 } |
| 2599 break; | 2590 break; |
| 2600 | 2591 |
| 2601 case STRING_CHECK: | 2592 case STRING_CHECK: { |
| 2602 // Check that the object is a string. | 2593 // Check that the object is a string. |
| 2603 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2594 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
| 2604 __ b(ge, &miss); | 2595 __ b(ge, &miss); |
| 2605 // Check that the maps starting from the prototype haven't changed. | 2596 // Check that the maps starting from the prototype haven't changed. |
| 2606 GenerateDirectLoadGlobalFunctionPrototype( | 2597 GenerateDirectLoadGlobalFunctionPrototype( |
| 2607 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2598 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); |
| 2599 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2608 CheckPrototypes( | 2600 CheckPrototypes( |
| 2609 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2601 IC::CurrentTypeOf(prototype, isolate()), |
| 2610 r0, holder, r3, r1, r4, name, &miss); | 2602 r0, holder, r3, r1, r4, name, &miss); |
| 2611 break; | 2603 break; |
| 2612 | 2604 } |
| 2613 case SYMBOL_CHECK: | 2605 case SYMBOL_CHECK: { |
| 2614 // Check that the object is a symbol. | 2606 // Check that the object is a symbol. |
| 2615 __ CompareObjectType(r1, r1, r3, SYMBOL_TYPE); | 2607 __ CompareObjectType(r1, r1, r3, SYMBOL_TYPE); |
| 2616 __ b(ne, &miss); | 2608 __ b(ne, &miss); |
| 2617 // Check that the maps starting from the prototype haven't changed. | 2609 // Check that the maps starting from the prototype haven't changed. |
| 2618 GenerateDirectLoadGlobalFunctionPrototype( | 2610 GenerateDirectLoadGlobalFunctionPrototype( |
| 2619 masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss); | 2611 masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss); |
| 2612 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2620 CheckPrototypes( | 2613 CheckPrototypes( |
| 2621 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2614 IC::CurrentTypeOf(prototype, isolate()), |
| 2622 r0, holder, r3, r1, r4, name, &miss); | 2615 r0, holder, r3, r1, r4, name, &miss); |
| 2623 break; | 2616 break; |
| 2624 | 2617 } |
| 2625 case NUMBER_CHECK: { | 2618 case NUMBER_CHECK: { |
| 2626 Label fast; | 2619 Label fast; |
| 2627 // Check that the object is a smi or a heap number. | 2620 // Check that the object is a smi or a heap number. |
| 2628 __ JumpIfSmi(r1, &fast); | 2621 __ JumpIfSmi(r1, &fast); |
| 2629 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2622 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
| 2630 __ b(ne, &miss); | 2623 __ b(ne, &miss); |
| 2631 __ bind(&fast); | 2624 __ bind(&fast); |
| 2632 // Check that the maps starting from the prototype haven't changed. | 2625 // Check that the maps starting from the prototype haven't changed. |
| 2633 GenerateDirectLoadGlobalFunctionPrototype( | 2626 GenerateDirectLoadGlobalFunctionPrototype( |
| 2634 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2627 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
| 2628 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2635 CheckPrototypes( | 2629 CheckPrototypes( |
| 2636 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2630 IC::CurrentTypeOf(prototype, isolate()), |
| 2637 r0, holder, r3, r1, r4, name, &miss); | 2631 r0, holder, r3, r1, r4, name, &miss); |
| 2638 break; | 2632 break; |
| 2639 } | 2633 } |
| 2640 case BOOLEAN_CHECK: { | 2634 case BOOLEAN_CHECK: { |
| 2641 GenerateBooleanCheck(r1, &miss); | 2635 GenerateBooleanCheck(r1, &miss); |
| 2642 | 2636 |
| 2643 // Check that the maps starting from the prototype haven't changed. | 2637 // Check that the maps starting from the prototype haven't changed. |
| 2644 GenerateDirectLoadGlobalFunctionPrototype( | 2638 GenerateDirectLoadGlobalFunctionPrototype( |
| 2645 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); | 2639 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); |
| 2640 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2646 CheckPrototypes( | 2641 CheckPrototypes( |
| 2647 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2642 IC::CurrentTypeOf(prototype, isolate()), |
| 2648 r0, holder, r3, r1, r4, name, &miss); | 2643 r0, holder, r3, r1, r4, name, &miss); |
| 2649 break; | 2644 break; |
| 2650 } | 2645 } |
| 2651 } | 2646 } |
| 2652 | 2647 |
| 2653 Label success; | 2648 Label success; |
| 2654 __ b(&success); | 2649 __ b(&success); |
| 2655 | 2650 |
| 2656 // Handle call cache miss. | 2651 // Handle call cache miss. |
| 2657 __ bind(&miss); | 2652 __ bind(&miss); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2790 // Return the generated code. | 2785 // Return the generated code. |
| 2791 return GetCode(Code::NORMAL, name); | 2786 return GetCode(Code::NORMAL, name); |
| 2792 } | 2787 } |
| 2793 | 2788 |
| 2794 | 2789 |
| 2795 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2790 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2796 Handle<JSObject> object, | 2791 Handle<JSObject> object, |
| 2797 Handle<JSObject> holder, | 2792 Handle<JSObject> holder, |
| 2798 Handle<Name> name, | 2793 Handle<Name> name, |
| 2799 Handle<ExecutableAccessorInfo> callback) { | 2794 Handle<ExecutableAccessorInfo> callback) { |
| 2800 HandlerFrontend(object, receiver(), holder, name); | 2795 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2796 receiver(), holder, name); |
| 2801 | 2797 |
| 2802 // Stub never generated for non-global objects that require access checks. | 2798 // Stub never generated for non-global objects that require access checks. |
| 2803 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 2799 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 2804 | 2800 |
| 2805 __ push(receiver()); // receiver | 2801 __ push(receiver()); // receiver |
| 2806 __ mov(ip, Operand(callback)); // callback info | 2802 __ mov(ip, Operand(callback)); // callback info |
| 2807 __ push(ip); | 2803 __ push(ip); |
| 2808 __ mov(ip, Operand(name)); | 2804 __ mov(ip, Operand(name)); |
| 2809 __ Push(ip, value()); | 2805 __ Push(ip, value()); |
| 2810 | 2806 |
| 2811 // Do tail-call to the runtime system. | 2807 // Do tail-call to the runtime system. |
| 2812 ExternalReference store_callback_property = | 2808 ExternalReference store_callback_property = |
| 2813 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2809 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2814 __ TailCallExternalReference(store_callback_property, 4, 1); | 2810 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2815 | 2811 |
| 2816 // Return the generated code. | 2812 // Return the generated code. |
| 2817 return GetCode(kind(), Code::FAST, name); | 2813 return GetCode(kind(), Code::FAST, name); |
| 2818 } | 2814 } |
| 2819 | 2815 |
| 2820 | 2816 |
| 2821 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2817 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2822 Handle<JSObject> object, | 2818 Handle<JSObject> object, |
| 2823 Handle<JSObject> holder, | 2819 Handle<JSObject> holder, |
| 2824 Handle<Name> name, | 2820 Handle<Name> name, |
| 2825 const CallOptimization& call_optimization) { | 2821 const CallOptimization& call_optimization) { |
| 2826 HandlerFrontend(object, receiver(), holder, name); | 2822 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2823 receiver(), holder, name); |
| 2827 | 2824 |
| 2828 Register values[] = { value() }; | 2825 Register values[] = { value() }; |
| 2829 GenerateFastApiCall( | 2826 GenerateFastApiCall( |
| 2830 masm(), call_optimization, receiver(), scratch3(), 1, values); | 2827 masm(), call_optimization, receiver(), scratch3(), 1, values); |
| 2831 | 2828 |
| 2832 // Return the generated code. | 2829 // Return the generated code. |
| 2833 return GetCode(kind(), Code::FAST, name); | 2830 return GetCode(kind(), Code::FAST, name); |
| 2834 } | 2831 } |
| 2835 | 2832 |
| 2836 | 2833 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2910 | 2907 |
| 2911 // Handle store cache miss. | 2908 // Handle store cache miss. |
| 2912 __ bind(&miss); | 2909 __ bind(&miss); |
| 2913 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2910 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2914 | 2911 |
| 2915 // Return the generated code. | 2912 // Return the generated code. |
| 2916 return GetCode(kind(), Code::FAST, name); | 2913 return GetCode(kind(), Code::FAST, name); |
| 2917 } | 2914 } |
| 2918 | 2915 |
| 2919 | 2916 |
| 2920 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2917 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, |
| 2921 Handle<Object> object, | 2918 Handle<JSObject> last, |
| 2922 Handle<JSObject> last, | 2919 Handle<Name> name) { |
| 2923 Handle<Name> name, | 2920 NonexistentHandlerFrontend(type, last, name); |
| 2924 Handle<JSGlobalObject> global) { | |
| 2925 NonexistentHandlerFrontend(object, last, name, global); | |
| 2926 | 2921 |
| 2927 // Return undefined if maps of the full prototype chain are still the | 2922 // Return undefined if maps of the full prototype chain are still the |
| 2928 // same and no global property with this name contains a value. | 2923 // same and no global property with this name contains a value. |
| 2929 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2924 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 2930 __ Ret(); | 2925 __ Ret(); |
| 2931 | 2926 |
| 2932 // Return the generated code. | 2927 // Return the generated code. |
| 2933 return GetCode(kind(), Code::FAST, name); | 2928 return GetCode(kind(), Code::FAST, name); |
| 2934 } | 2929 } |
| 2935 | 2930 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3011 } | 3006 } |
| 3012 __ Ret(); | 3007 __ Ret(); |
| 3013 } | 3008 } |
| 3014 | 3009 |
| 3015 | 3010 |
| 3016 #undef __ | 3011 #undef __ |
| 3017 #define __ ACCESS_MASM(masm()) | 3012 #define __ ACCESS_MASM(masm()) |
| 3018 | 3013 |
| 3019 | 3014 |
| 3020 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3015 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3021 Handle<Object> object, | 3016 Handle<Type> type, |
| 3022 Handle<GlobalObject> global, | 3017 Handle<GlobalObject> global, |
| 3023 Handle<PropertyCell> cell, | 3018 Handle<PropertyCell> cell, |
| 3024 Handle<Name> name, | 3019 Handle<Name> name, |
| 3025 bool is_dont_delete) { | 3020 bool is_dont_delete) { |
| 3026 Label miss; | 3021 Label miss; |
| 3027 | 3022 |
| 3028 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3023 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 3029 | 3024 |
| 3030 // Get the value from the cell. | 3025 // Get the value from the cell. |
| 3031 __ mov(r3, Operand(cell)); | 3026 __ mov(r3, Operand(cell)); |
| 3032 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); | 3027 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); |
| 3033 | 3028 |
| 3034 // Check for deleted property if property can actually be deleted. | 3029 // Check for deleted property if property can actually be deleted. |
| 3035 if (!is_dont_delete) { | 3030 if (!is_dont_delete) { |
| 3036 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3031 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3037 __ cmp(r4, ip); | 3032 __ cmp(r4, ip); |
| 3038 __ b(eq, &miss); | 3033 __ b(eq, &miss); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3172 // ----------------------------------- | 3167 // ----------------------------------- |
| 3173 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3168 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3174 } | 3169 } |
| 3175 | 3170 |
| 3176 | 3171 |
| 3177 #undef __ | 3172 #undef __ |
| 3178 | 3173 |
| 3179 } } // namespace v8::internal | 3174 } } // namespace v8::internal |
| 3180 | 3175 |
| 3181 #endif // V8_TARGET_ARCH_ARM | 3176 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |