Index: src/ic.cc |
=================================================================== |
--- src/ic.cc (revision 5101) |
+++ src/ic.cc (working copy) |
@@ -277,6 +277,13 @@ |
} |
+void KeyedLoadIC::ClearInlinedVersion(Address address) { |
+ // Insert null as the map to check for to make sure the map check fails |
+ // sending control flow to the IC instead of the inlined version. |
+ PatchInlinedLoad(address, Heap::null_value()); |
+} |
+ |
+ |
void KeyedLoadIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
// Make sure to also clear the map used in inline fast cases. If we |
@@ -287,6 +294,14 @@ |
} |
+void LoadIC::ClearInlinedVersion(Address address) { |
+ // Reset the map check of the inlined inobject property load (if |
+ // present) to guarantee failure by holding an invalid map (the null |
+ // value). The offset can be patched to anything. |
+ PatchInlinedLoad(address, Heap::null_value(), 0); |
+} |
+ |
+ |
void LoadIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
ClearInlinedVersion(address); |
@@ -294,12 +309,36 @@ |
} |
+void StoreIC::ClearInlinedVersion(Address address) { |
+ // Reset the map check of the inlined inobject property store (if |
+ // present) to guarantee failure by holding an invalid map (the null |
+ // value). The offset can be patched to anything. |
+ PatchInlinedStore(address, Heap::null_value(), 0); |
+} |
+ |
+ |
void StoreIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
+ ClearInlinedVersion(address); |
SetTargetAtAddress(address, initialize_stub()); |
} |
+void KeyedStoreIC::ClearInlinedVersion(Address address) { |
+ // Insert null as the elements map to check for. This will make |
+ // sure that the elements fast-case map check fails so that control |
+ // flows to the IC instead of the inlined version. |
+ PatchInlinedStore(address, Heap::null_value()); |
+} |
+ |
+ |
+void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
+ // Restore the fast-case elements map check so that the inlined |
+ // version can be used again. |
+ PatchInlinedStore(address, Heap::fixed_array_map()); |
+} |
+ |
+ |
void KeyedStoreIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
SetTargetAtAddress(address, initialize_stub()); |
@@ -777,11 +816,13 @@ |
int offset = map->instance_size() + (index * kPointerSize); |
if (PatchInlinedLoad(address(), map, offset)) { |
set_target(megamorphic_stub()); |
- return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
#ifdef DEBUG |
if (FLAG_trace_ic) { |
PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); |
} |
+#endif |
+ return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
+#ifdef DEBUG |
} else { |
if (FLAG_trace_ic) { |
PrintF("[LoadIC : no inline patch %s (patching failed)]\n", |
@@ -1205,7 +1246,57 @@ |
// Lookup the property locally in the receiver. |
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
LookupResult lookup; |
+ |
if (LookupForWrite(*receiver, *name, &lookup)) { |
+ bool can_be_inlined = |
+ state == UNINITIALIZED && |
+ lookup.IsProperty() && |
+ lookup.holder() == *receiver && |
+ lookup.type() == FIELD && |
+ !receiver->IsAccessCheckNeeded(); |
+ |
+ if (can_be_inlined) { |
+ Map* map = lookup.holder()->map(); |
+ // Property's index in the properties array. If negative we have |
+ // an inobject property. |
+ int index = lookup.GetFieldIndex() - map->inobject_properties(); |
+ if (index < 0) { |
+ // Index is an offset from the end of the object. |
+ int offset = map->instance_size() + (index * kPointerSize); |
+ if (PatchInlinedStore(address(), map, offset)) { |
+ set_target(megamorphic_stub()); |
+#ifdef DEBUG |
+ if (FLAG_trace_ic) { |
+ PrintF("[StoreIC : inline patch %s]\n", *name->ToCString()); |
+ } |
+#endif |
+ return receiver->SetProperty(*name, *value, NONE); |
+#ifdef DEBUG |
+ |
+ } else { |
+ if (FLAG_trace_ic) { |
+ PrintF("[StoreIC : no inline patch %s (patching failed)]\n", |
+ *name->ToCString()); |
+ } |
+ } |
+ } else { |
+ if (FLAG_trace_ic) { |
+ PrintF("[StoreIC : no inline patch %s (not inobject)]\n", |
+ *name->ToCString()); |
+ } |
+ } |
+ } else { |
+ if (state == PREMONOMORPHIC) { |
+ if (FLAG_trace_ic) { |
+ PrintF("[StoreIC : no inline patch %s (not inlinable)]\n", |
+ *name->ToCString()); |
+#endif |
+ } |
+ } |
+ } |
+ |
+ // If no inlined store ic was patched, generate a stub for this |
+ // store. |
UpdateCaches(&lookup, state, receiver, name, value); |
} |
} |