Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 7fdf6be31fbe5f36f53a22182371963d5e212be1..866fcce0c690ded60456f6c5afb3ad8660924a73 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -959,13 +959,23 @@ bool IC::UpdatePolymorphicIC(State state, |
target()->type() == Code::NORMAL) { |
return false; |
} |
+ |
MapHandleList receiver_maps; |
CodeHandleList handlers; |
- target()->FindAllMaps(&receiver_maps); |
- int number_of_maps = receiver_maps.length(); |
- if (number_of_maps == 0 || number_of_maps >= 4) return false; |
- target()->FindAllCode(&handlers, receiver_maps.length()); |
+ { |
+ AssertNoAllocation no_gc; |
+ target()->FindAllMaps(&receiver_maps); |
+ int number_of_maps = receiver_maps.length(); |
+ if (number_of_maps >= 4) return false; |
+ |
+ // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. |
+ // In that case, allow the IC to go back monomorphic. |
+ if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { |
+ return false; |
+ } |
+ target()->FindAllCode(&handlers, receiver_maps.length()); |
+ } |
if (!AddOneReceiverMapIfMissing(&receiver_maps, |
Handle<Map>(receiver->map()))) { |
@@ -1000,6 +1010,8 @@ void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, |
} |
+// Since GC may have been invoked, by the time PatchCache is called, |state| is |
+// not necessarily equal to target()->state(). |
void IC::PatchCache(State state, |
StrictModeFlag strict_mode, |
Handle<JSObject> receiver, |
@@ -1019,11 +1031,28 @@ void IC::PatchCache(State state, |
break; |
} |
} |
- // We are transitioning from monomorphic to megamorphic case. Place the |
- // stub compiled for the receiver into stub cache. |
- Map* map = target()->FindFirstMap(); |
- if (map != NULL) { |
- UpdateMegamorphicCache(map, *name, target()); |
+ if (target()->type() != Code::NORMAL) { |
+ // We are transitioning from monomorphic to megamorphic case. Place |
+ // the stub compiled for the receiver into stub cache. |
+ Map* map; |
+ Code* handler; |
+ { |
+ AssertNoAllocation no_gc; |
+ map = target()->FindFirstMap(); |
+ if (map != NULL) { |
+ if (target()->is_load_stub()) { |
+ handler = target()->FindFirstCode(); |
+ } else { |
+ handler = target(); |
+ } |
+ } else { |
+ // Avoid compiler warnings. |
+ handler = NULL; |
+ } |
+ } |
+ if (handler != NULL) { |
+ UpdateMegamorphicCache(map, *name, handler); |
+ } |
} |
UpdateMegamorphicCache(receiver->map(), *name, *code); |
set_target((strict_mode == kStrictMode) |
@@ -1042,8 +1071,11 @@ void IC::PatchCache(State state, |
} |
MapHandleList receiver_maps; |
CodeHandleList handlers; |
- target()->FindAllMaps(&receiver_maps); |
- target()->FindAllCode(&handlers, receiver_maps.length()); |
+ { |
+ AssertNoAllocation no_gc; |
+ target()->FindAllMaps(&receiver_maps); |
+ target()->FindAllCode(&handlers, receiver_maps.length()); |
+ } |
for (int i = 0; i < receiver_maps.length(); i++) { |
UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
} |