Commit 34ed15cc authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[turbofan] Improve inlining of Array.prototype.map

We can use the known ElementsKind to improve typing on the receiver
element load. We can allow multiple maps, as long as they have the
same ElementsKind.

Bug: v8:6896
Change-Id: Ida7df943f7d315454b58bcf4e0bbd2346406c488
Reviewed-on: https://chromium-review.googlesource.com/704921
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48367}
parent 6ddb5e7d
...@@ -834,44 +834,46 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function, ...@@ -834,44 +834,46 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
if (result != NodeProperties::kReliableReceiverMaps) { if (result != NodeProperties::kReliableReceiverMaps) {
return NoChange(); return NoChange();
} }
if (receiver_maps.size() != 1) return NoChange();
Handle<Map> receiver_map(receiver_maps[0]); // Ensure that any changes to the Array species constructor cause deopt.
ElementsKind kind = receiver_map->elements_kind(); if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
if (receiver_maps.size() == 0) return NoChange();
const ElementsKind kind = receiver_maps[0]->elements_kind();
// TODO(danno): Handle holey Smi and Object fast elements kinds and double // TODO(danno): Handle holey Smi and Object fast elements kinds and double
// packed. // packed.
if (!IsFastPackedElementsKind(kind) || IsDoubleElementsKind(kind)) { if (!IsFastPackedElementsKind(kind) || IsDoubleElementsKind(kind)) {
return NoChange(); return NoChange();
} }
// We want the input to be a generic Array. for (Handle<Map> receiver_map : receiver_maps) {
if (!CanInlineArrayIteratingBuiltin(receiver_map)) {
return NoChange();
}
// We can handle different maps, as long as their elements kind are the
// same.
if (receiver_map->elements_kind() != kind) {
return NoChange();
}
}
dependencies()->AssumePropertyCell(factory()->species_protector());
Handle<JSFunction> handle_constructor( Handle<JSFunction> handle_constructor(
JSFunction::cast( JSFunction::cast(
native_context()->GetInitialJSArrayMap(kind)->GetConstructor()), native_context()->GetInitialJSArrayMap(kind)->GetConstructor()),
isolate()); isolate());
Node* array_constructor = jsgraph()->HeapConstant(handle_constructor); Node* array_constructor = jsgraph()->HeapConstant(handle_constructor);
if (receiver_map->prototype() !=
native_context()->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
return NoChange();
}
// And ensure that any changes to the Array species constructor cause deopt.
if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
dependencies()->AssumePropertyCell(factory()->species_protector());
Node* k = jsgraph()->ZeroConstant(); Node* k = jsgraph()->ZeroConstant();
Node* orig_map = jsgraph()->HeapConstant(receiver_map);
// Make sure the map hasn't changed before we construct the output array. // Make sure the map hasn't changed before we construct the output array.
{ effect = graph()->NewNode(
Node* array_map = effect = simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), effect, control);
receiver, effect, control);
Node* check_map =
graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map);
effect =
graph()->NewNode(simplified()->CheckIf(), check_map, effect, control);
}
Node* original_length = graph()->NewNode( Node* original_length = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS)), simplified()->LoadField(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS)),
...@@ -933,19 +935,15 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function, ...@@ -933,19 +935,15 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
graph()->NewNode(common()->Checkpoint(), frame_state, effect, control); graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
// Make sure the map hasn't changed during the iteration // Make sure the map hasn't changed during the iteration
Node* array_map = effect = effect = graph()->NewNode(
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
receiver, effect, control); effect, control);
Node* check_map =
graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map);
effect =
graph()->NewNode(simplified()->CheckIf(), check_map, effect, control);
// Make sure that the access is still in bounds, since the callback could have // Make sure that the access is still in bounds, since the callback could have
// changed the array's size. // changed the array's size.
Node* length = graph()->NewNode( Node* length = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS)), simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
receiver, effect, control); effect, control);
k = effect = k = effect =
graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control); graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control);
...@@ -957,7 +955,7 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function, ...@@ -957,7 +955,7 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
effect, control); effect, control);
Node* element = graph()->NewNode( Node* element = graph()->NewNode(
simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
elements, k, effect, control); elements, k, effect, control);
Node* next_k = Node* next_k =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment