OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 State state = target->ic_state(); | 270 State state = target->ic_state(); |
271 if (state == UNINITIALIZED) return; | 271 if (state == UNINITIALIZED) return; |
272 Code* code = | 272 Code* code = |
273 StubCache::FindCallInitialize(target->arguments_count(), | 273 StubCache::FindCallInitialize(target->arguments_count(), |
274 target->ic_in_loop(), | 274 target->ic_in_loop(), |
275 target->kind()); | 275 target->kind()); |
276 SetTargetAtAddress(address, code); | 276 SetTargetAtAddress(address, code); |
277 } | 277 } |
278 | 278 |
279 | 279 |
| 280 void KeyedLoadIC::ClearInlinedVersion(Address address) { |
| 281 // Insert null as the map to check for to make sure the map check fails |
| 282 // sending control flow to the IC instead of the inlined version. |
| 283 PatchInlinedLoad(address, Heap::null_value()); |
| 284 } |
| 285 |
| 286 |
280 void KeyedLoadIC::Clear(Address address, Code* target) { | 287 void KeyedLoadIC::Clear(Address address, Code* target) { |
281 if (target->ic_state() == UNINITIALIZED) return; | 288 if (target->ic_state() == UNINITIALIZED) return; |
282 // Make sure to also clear the map used in inline fast cases. If we | 289 // Make sure to also clear the map used in inline fast cases. If we |
283 // do not clear these maps, cached code can keep objects alive | 290 // do not clear these maps, cached code can keep objects alive |
284 // through the embedded maps. | 291 // through the embedded maps. |
285 ClearInlinedVersion(address); | 292 ClearInlinedVersion(address); |
286 SetTargetAtAddress(address, initialize_stub()); | 293 SetTargetAtAddress(address, initialize_stub()); |
287 } | 294 } |
288 | 295 |
289 | 296 |
| 297 void LoadIC::ClearInlinedVersion(Address address) { |
| 298 // Reset the map check of the inlined inobject property load (if |
| 299 // present) to guarantee failure by holding an invalid map (the null |
| 300 // value). The offset can be patched to anything. |
| 301 PatchInlinedLoad(address, Heap::null_value(), 0); |
| 302 } |
| 303 |
| 304 |
290 void LoadIC::Clear(Address address, Code* target) { | 305 void LoadIC::Clear(Address address, Code* target) { |
291 if (target->ic_state() == UNINITIALIZED) return; | 306 if (target->ic_state() == UNINITIALIZED) return; |
292 ClearInlinedVersion(address); | 307 ClearInlinedVersion(address); |
293 SetTargetAtAddress(address, initialize_stub()); | 308 SetTargetAtAddress(address, initialize_stub()); |
294 } | 309 } |
295 | 310 |
296 | 311 |
| 312 void StoreIC::ClearInlinedVersion(Address address) { |
| 313 // Reset the map check of the inlined inobject property store (if |
| 314 // present) to guarantee failure by holding an invalid map (the null |
| 315 // value). The offset can be patched to anything. |
| 316 PatchInlinedStore(address, Heap::null_value(), 0); |
| 317 } |
| 318 |
| 319 |
297 void StoreIC::Clear(Address address, Code* target) { | 320 void StoreIC::Clear(Address address, Code* target) { |
298 if (target->ic_state() == UNINITIALIZED) return; | 321 if (target->ic_state() == UNINITIALIZED) return; |
| 322 ClearInlinedVersion(address); |
299 SetTargetAtAddress(address, initialize_stub()); | 323 SetTargetAtAddress(address, initialize_stub()); |
300 } | 324 } |
301 | 325 |
302 | 326 |
| 327 void KeyedStoreIC::ClearInlinedVersion(Address address) { |
| 328 // Insert null as the elements map to check for. This will make |
| 329 // sure that the elements fast-case map check fails so that control |
| 330 // flows to the IC instead of the inlined version. |
| 331 PatchInlinedStore(address, Heap::null_value()); |
| 332 } |
| 333 |
| 334 |
| 335 void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
| 336 // Restore the fast-case elements map check so that the inlined |
| 337 // version can be used again. |
| 338 PatchInlinedStore(address, Heap::fixed_array_map()); |
| 339 } |
| 340 |
| 341 |
303 void KeyedStoreIC::Clear(Address address, Code* target) { | 342 void KeyedStoreIC::Clear(Address address, Code* target) { |
304 if (target->ic_state() == UNINITIALIZED) return; | 343 if (target->ic_state() == UNINITIALIZED) return; |
305 SetTargetAtAddress(address, initialize_stub()); | 344 SetTargetAtAddress(address, initialize_stub()); |
306 } | 345 } |
307 | 346 |
308 | 347 |
309 Code* KeyedLoadIC::external_array_stub(JSObject::ElementsKind elements_kind) { | 348 Code* KeyedLoadIC::external_array_stub(JSObject::ElementsKind elements_kind) { |
310 switch (elements_kind) { | 349 switch (elements_kind) { |
311 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 350 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
312 return Builtins::builtin(Builtins::KeyedLoadIC_ExternalByteArray); | 351 return Builtins::builtin(Builtins::KeyedLoadIC_ExternalByteArray); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 if (can_be_inlined) { | 809 if (can_be_inlined) { |
771 Map* map = lookup.holder()->map(); | 810 Map* map = lookup.holder()->map(); |
772 // Property's index in the properties array. If negative we have | 811 // Property's index in the properties array. If negative we have |
773 // an inobject property. | 812 // an inobject property. |
774 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 813 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
775 if (index < 0) { | 814 if (index < 0) { |
776 // Index is an offset from the end of the object. | 815 // Index is an offset from the end of the object. |
777 int offset = map->instance_size() + (index * kPointerSize); | 816 int offset = map->instance_size() + (index * kPointerSize); |
778 if (PatchInlinedLoad(address(), map, offset)) { | 817 if (PatchInlinedLoad(address(), map, offset)) { |
779 set_target(megamorphic_stub()); | 818 set_target(megamorphic_stub()); |
780 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | |
781 #ifdef DEBUG | 819 #ifdef DEBUG |
782 if (FLAG_trace_ic) { | 820 if (FLAG_trace_ic) { |
783 PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); | 821 PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); |
784 } | 822 } |
| 823 #endif |
| 824 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
| 825 #ifdef DEBUG |
785 } else { | 826 } else { |
786 if (FLAG_trace_ic) { | 827 if (FLAG_trace_ic) { |
787 PrintF("[LoadIC : no inline patch %s (patching failed)]\n", | 828 PrintF("[LoadIC : no inline patch %s (patching failed)]\n", |
788 *name->ToCString()); | 829 *name->ToCString()); |
789 } | 830 } |
790 } | 831 } |
791 } else { | 832 } else { |
792 if (FLAG_trace_ic) { | 833 if (FLAG_trace_ic) { |
793 PrintF("[LoadIC : no inline patch %s (not inobject)]\n", | 834 PrintF("[LoadIC : no inline patch %s (not inobject)]\n", |
794 *name->ToCString()); | 835 *name->ToCString()); |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1239 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
1199 #endif | 1240 #endif |
1200 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); | 1241 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); |
1201 set_target(target); | 1242 set_target(target); |
1202 return receiver->SetProperty(*name, *value, NONE); | 1243 return receiver->SetProperty(*name, *value, NONE); |
1203 } | 1244 } |
1204 | 1245 |
1205 // Lookup the property locally in the receiver. | 1246 // Lookup the property locally in the receiver. |
1206 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1247 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
1207 LookupResult lookup; | 1248 LookupResult lookup; |
| 1249 |
1208 if (LookupForWrite(*receiver, *name, &lookup)) { | 1250 if (LookupForWrite(*receiver, *name, &lookup)) { |
| 1251 bool can_be_inlined = |
| 1252 state == UNINITIALIZED && |
| 1253 lookup.IsProperty() && |
| 1254 lookup.holder() == *receiver && |
| 1255 lookup.type() == FIELD && |
| 1256 !receiver->IsAccessCheckNeeded(); |
| 1257 |
| 1258 if (can_be_inlined) { |
| 1259 Map* map = lookup.holder()->map(); |
| 1260 // Property's index in the properties array. If negative we have |
| 1261 // an inobject property. |
| 1262 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 1263 if (index < 0) { |
| 1264 // Index is an offset from the end of the object. |
| 1265 int offset = map->instance_size() + (index * kPointerSize); |
| 1266 if (PatchInlinedStore(address(), map, offset)) { |
| 1267 set_target(megamorphic_stub()); |
| 1268 #ifdef DEBUG |
| 1269 if (FLAG_trace_ic) { |
| 1270 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString()); |
| 1271 } |
| 1272 #endif |
| 1273 return receiver->SetProperty(*name, *value, NONE); |
| 1274 #ifdef DEBUG |
| 1275 |
| 1276 } else { |
| 1277 if (FLAG_trace_ic) { |
| 1278 PrintF("[StoreIC : no inline patch %s (patching failed)]\n", |
| 1279 *name->ToCString()); |
| 1280 } |
| 1281 } |
| 1282 } else { |
| 1283 if (FLAG_trace_ic) { |
| 1284 PrintF("[StoreIC : no inline patch %s (not inobject)]\n", |
| 1285 *name->ToCString()); |
| 1286 } |
| 1287 } |
| 1288 } else { |
| 1289 if (state == PREMONOMORPHIC) { |
| 1290 if (FLAG_trace_ic) { |
| 1291 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n", |
| 1292 *name->ToCString()); |
| 1293 #endif |
| 1294 } |
| 1295 } |
| 1296 } |
| 1297 |
| 1298 // If no inlined store ic was patched, generate a stub for this |
| 1299 // store. |
1209 UpdateCaches(&lookup, state, receiver, name, value); | 1300 UpdateCaches(&lookup, state, receiver, name, value); |
1210 } | 1301 } |
1211 } | 1302 } |
1212 | 1303 |
1213 // Set the property. | 1304 // Set the property. |
1214 return receiver->SetProperty(*name, *value, NONE); | 1305 return receiver->SetProperty(*name, *value, NONE); |
1215 } | 1306 } |
1216 | 1307 |
1217 | 1308 |
1218 void StoreIC::UpdateCaches(LookupResult* lookup, | 1309 void StoreIC::UpdateCaches(LookupResult* lookup, |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 #undef ADDR | 1818 #undef ADDR |
1728 }; | 1819 }; |
1729 | 1820 |
1730 | 1821 |
1731 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1822 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1732 return IC_utilities[id]; | 1823 return IC_utilities[id]; |
1733 } | 1824 } |
1734 | 1825 |
1735 | 1826 |
1736 } } // namespace v8::internal | 1827 } } // namespace v8::internal |
OLD | NEW |