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 0868f5d1cb091cad2164dec1713f426406eecf41..061f1642bef674731c747d6447c0104b23cfc834 100644 |
--- a/src/compiler/js-native-context-specialization.cc |
+++ b/src/compiler/js-native-context-specialization.cc |
@@ -426,13 +426,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( |
// Not much we can do if deoptimization support is disabled. |
if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
- // TODO(bmeurer): Add support for non-standard stores. |
- if (store_mode != STANDARD_STORE && |
- store_mode != STORE_NO_TRANSITION_HANDLE_COW && |
- store_mode != STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
- return NoChange(); |
- } |
- |
// Retrieve the native context from the given {node}. |
Handle<Context> native_context; |
if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); |
@@ -1068,13 +1061,12 @@ JSNativeContextSpecialization::BuildElementAccess( |
} |
} |
} else { |
- // TODO(turbofan): Add support for additional store modes. |
- DCHECK(store_mode == STANDARD_STORE || |
- store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
+ // Check if the {receiver} is a JSArray. |
+ bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); |
// Load the length of the {receiver}. |
Node* length = effect = |
- HasOnlyJSArrayMaps(receiver_maps) |
+ receiver_is_jsarray |
? graph()->NewNode( |
simplified()->LoadField( |
AccessBuilder::ForJSArrayLength(elements_kind)), |
@@ -1083,9 +1075,20 @@ JSNativeContextSpecialization::BuildElementAccess( |
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), |
elements, effect, control); |
- // Check that the {index} is in the valid range for the {receiver}. |
- index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
- length, effect, control); |
+ // Check if we might need to grow the {elements} backing store. |
+ if (IsGrowStoreMode(store_mode)) { |
+ DCHECK_EQ(AccessMode::kStore, access_mode); |
+ |
+ // Check that the {index} is a valid array index; the actual checking |
+ // happens below right before the element store. |
+ index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
+ jsgraph()->Constant(Smi::kMaxValue), |
+ effect, control); |
+ } else { |
+ // Check that the {index} is in the valid range for the {receiver}. |
+ index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
+ length, effect, control); |
+ } |
// Compute the element access. |
Type* element_type = Type::Any(); |
@@ -1157,6 +1160,24 @@ JSNativeContextSpecialization::BuildElementAccess( |
elements = effect = |
graph()->NewNode(simplified()->EnsureWritableFastElements(), |
receiver, elements, effect, control); |
+ } else if (IsGrowStoreMode(store_mode)) { |
+ // Grow {elements} backing store if necessary. Also updates the |
+ // "length" property for JSArray {receiver}s, hence there must |
+ // not be any other check after this operation, as the write |
+ // to the "length" property is observable. |
+ GrowFastElementsFlags flags = GrowFastElementsFlag::kNone; |
+ if (receiver_is_jsarray) { |
+ flags |= GrowFastElementsFlag::kArrayObject; |
+ } |
+ if (IsHoleyElementsKind(elements_kind)) { |
+ flags |= GrowFastElementsFlag::kHoleyElements; |
+ } |
+ if (IsFastDoubleElementsKind(elements_kind)) { |
+ flags |= GrowFastElementsFlag::kDoubleElements; |
+ } |
+ elements = effect = graph()->NewNode( |
+ simplified()->MaybeGrowFastElements(flags), receiver, elements, |
+ index, length, effect, control); |
} |
// Perform the actual element access. |