| 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);
|
|
|