Index: src/compiler/js-native-context-specialization.cc |
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc |
index 26793cc85185ea395bf134c0a6395df17f475b7e..0f6724ba2811af3da1e43c22cb565a2a486e93f6 100644 |
--- a/src/compiler/js-native-context-specialization.cc |
+++ b/src/compiler/js-native-context-specialization.cc |
@@ -472,6 +472,43 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( |
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); |
} |
+ // For holey stores or growing stores, we need to check that the prototype |
+ // chain contains no setters for elements, and we need to guard those checks |
+ // via code dependencies on the relevant prototype maps. |
+ if (access_mode == AccessMode::kStore) { |
+ // TODO(turbofan): We could have a fast path here, that checks for the |
+ // common case of Array or Object prototype only and therefore avoids |
+ // the zone allocation of this vector. |
+ ZoneVector<Handle<Map>> prototype_maps(zone()); |
+ for (ElementAccessInfo const& access_info : access_infos) { |
+ for (Handle<Map> receiver_map : access_info.receiver_maps()) { |
+ // If the {receiver_map} has a prototype and it's elements backing |
+ // store is either holey, or we have a potentially growing store, |
+ // then we need to check that all prototypes have stable maps with |
+ // fast elements (and we need to guard against changes to that below). |
+ if (IsHoleyElementsKind(receiver_map->elements_kind()) || |
+ IsGrowStoreMode(store_mode)) { |
+ // Make sure all prototypes are stable and have fast elements. |
+ for (Handle<Map> map = receiver_map;;) { |
+ Handle<Object> map_prototype(map->prototype(), isolate()); |
+ if (map_prototype->IsNull(isolate())) break; |
+ if (!map_prototype->IsJSObject()) return NoChange(); |
+ map = handle(Handle<JSObject>::cast(map_prototype)->map(), |
+ isolate()); |
+ if (!map->is_stable()) return NoChange(); |
+ if (!IsFastElementsKind(map->elements_kind())) return NoChange(); |
+ prototype_maps.push_back(map); |
+ } |
+ } |
+ } |
+ } |
+ |
+ // Install dependencies on the relevant prototype maps. |
+ for (Handle<Map> prototype_map : prototype_maps) { |
+ dependencies()->AssumeMapStable(prototype_map); |
+ } |
+ } |
+ |
// Ensure that {receiver} is a heap object. |
effect = BuildCheckTaggedPointer(receiver, effect, control); |