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 44521793a035676f137d366a43428e652b1e9c54..cc3bb1c8856925ba31bdb231762ab5904b2feb87 100644 |
--- a/src/compiler/js-native-context-specialization.cc |
+++ b/src/compiler/js-native-context-specialization.cc |
@@ -581,14 +581,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( |
} |
} |
- // Certain stores need a prototype chain check because shape changes |
- // could allow callbacks on elements in the prototype chain that are |
- // not compatible with (monomorphic) keyed stores. |
- Handle<JSObject> holder; |
- if (access_info.holder().ToHandle(&holder)) { |
- AssumePrototypesStable(receiver_maps, native_context, holder); |
- } |
- |
// Access the actual element. |
ValueEffectControl continuation = BuildElementAccess( |
this_receiver, this_index, this_value, this_effect, this_control, |
@@ -956,12 +948,6 @@ JSNativeContextSpecialization::BuildElementAccess( |
Node* receiver, Node* index, Node* value, Node* effect, Node* control, |
Handle<Context> native_context, ElementAccessInfo const& access_info, |
AccessMode access_mode, KeyedAccessStoreMode store_mode) { |
- // Determine actual holder and perform prototype chain checks. |
- Handle<JSObject> holder; |
- if (access_info.holder().ToHandle(&holder)) { |
- AssumePrototypesStable(access_info.receiver_maps(), native_context, holder); |
- } |
- |
// TODO(bmeurer): We currently specialize based on elements kind. We should |
// also be able to properly support strings and other JSObjects here. |
ElementsKind elements_kind = access_info.elements_kind(); |
@@ -1133,16 +1119,7 @@ JSNativeContextSpecialization::BuildElementAccess( |
// Perform the hole check on the result. |
CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole; |
// Check if we are allowed to turn the hole into undefined. |
- // TODO(bmeurer): We might check the JSArray map from a different |
- // context here; may need reinvestigation. |
- if (receiver_maps.size() == 1 && |
- receiver_maps[0].is_identical_to( |
- handle(isolate()->get_initial_js_array_map(elements_kind))) && |
- isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
- // Add a code dependency on the array protector cell. |
- dependencies()->AssumePrototypeMapsStable( |
- receiver_maps[0], isolate()->initial_object_prototype()); |
- dependencies()->AssumePropertyCell(factory()->array_protector()); |
+ if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { |
// Turn the hole into undefined. |
mode = CheckTaggedHoleMode::kConvertHoleToUndefined; |
} |
@@ -1152,16 +1129,7 @@ JSNativeContextSpecialization::BuildElementAccess( |
// Perform the hole check on the result. |
CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; |
// Check if we are allowed to return the hole directly. |
- // TODO(bmeurer): We might check the JSArray map from a different |
- // context here; may need reinvestigation. |
- if (receiver_maps.size() == 1 && |
- receiver_maps[0].is_identical_to( |
- handle(isolate()->get_initial_js_array_map(elements_kind))) && |
- isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
- // Add a code dependency on the array protector cell. |
- dependencies()->AssumePrototypeMapsStable( |
- receiver_maps[0], isolate()->initial_object_prototype()); |
- dependencies()->AssumePropertyCell(factory()->array_protector()); |
+ if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { |
// Return the signaling NaN hole directly if all uses are truncating. |
mode = CheckFloat64HoleMode::kAllowReturnHole; |
} |
@@ -1258,6 +1226,42 @@ void JSNativeContextSpecialization::AssumePrototypesStable( |
} |
} |
+bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( |
+ std::vector<Handle<Map>> const& receiver_maps, |
+ Handle<Context> native_context) { |
+ // Check if the array prototype chain is intact. |
+ if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; |
+ |
+ // Make sure both the initial Array and Object prototypes are stable. |
+ Handle<JSObject> initial_array_prototype( |
+ native_context->initial_array_prototype(), isolate()); |
+ Handle<JSObject> initial_object_prototype( |
+ native_context->initial_object_prototype(), isolate()); |
+ if (!initial_array_prototype->map()->is_stable() || |
+ !initial_object_prototype->map()->is_stable()) { |
+ return false; |
+ } |
+ |
+ // Check if all {receiver_maps} either have the initial Array.prototype |
+ // or the initial Object.prototype as their prototype, as those are |
+ // guarded by the array protector cell. |
+ for (Handle<Map> map : receiver_maps) { |
+ if (map->prototype() != *initial_array_prototype && |
+ map->prototype() != *initial_object_prototype) { |
+ return false; |
+ } |
+ } |
+ |
+ // Install code dependencies on the prototype maps. |
+ for (Handle<Map> map : receiver_maps) { |
+ dependencies()->AssumePrototypeMapsStable(map, initial_object_prototype); |
adamk
2016/08/08 22:02:00
Are you missing a call for initial_array_prototype
|
+ } |
+ |
+ // Install code dependency on the array protector cell. |
+ dependencies()->AssumePropertyCell(factory()->array_protector()); |
+ return true; |
+} |
+ |
bool JSNativeContextSpecialization::ExtractReceiverMaps( |
Node* receiver, Node* effect, FeedbackNexus const& nexus, |
MapHandleList* receiver_maps) { |