Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 3b232e6e93ee2d307e5ea9504266825fb9f11b36..be50b7ad5079259628a79b3d7f08db2e28bfcf9d 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -5577,6 +5577,21 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
checked_object->ClearGVNFlag(kDependsOnElementsKind); |
} |
+ if (is_store && map->prototype()->IsJSObject()) { |
+ // monomorphic stores need a prototype chain check because shape |
+ // changes could allow callbacks on elements in the chain that |
+ // aren't compatible with monomorphic keyed stores. |
+ Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
+ Object* holder = map->prototype(); |
+ while (holder->GetPrototype(isolate())->IsJSObject()) { |
+ holder = holder->GetPrototype(isolate()); |
+ } |
+ ASSERT(holder->GetPrototype(isolate())->IsNull()); |
+ |
+ BuildCheckPrototypeMaps(prototype, |
+ Handle<JSObject>(JSObject::cast(holder))); |
+ } |
+ |
LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
return BuildUncheckedMonomorphicElementAccess( |
checked_object, key, val, |
@@ -5790,6 +5805,20 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
SmallMapList* types; |
bool monomorphic = ComputeReceiverTypes(expr, obj, &types); |
+ bool force_generic = false; |
+ if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { |
+ // Stores can't be mono/polymorphic if there are indexed callbacks |
+ // in their prototype chains. Nip this problem in the bud now. |
+ for (int i = 0; i < types->length(); i++) { |
+ Handle<Map> current_map = types->at(i); |
+ if (IsDictionaryElementsKind(current_map->elements_kind())) { |
+ force_generic = true; |
+ monomorphic = false; |
+ break; |
+ } |
+ } |
+ } |
+ |
if (monomorphic) { |
Handle<Map> map = types->first(); |
if (map->has_slow_elements_kind()) { |
@@ -5801,7 +5830,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
instr = BuildMonomorphicElementAccess( |
obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
} |
- } else if (types != NULL && !types->is_empty()) { |
+ } else if (!force_generic && (types != NULL && !types->is_empty())) { |
return HandlePolymorphicElementAccess( |
obj, key, val, types, is_store, |
expr->GetStoreMode(), has_side_effects); |