Commit 56b6b6a8 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Make sure we use only serialized elements kind transitions.

Currently, we call the MapRef::AsElementsKind method on an initial
map multiple times (from JSCreateLowering::ReduceJSCreateArray).
However, this does not does not play well with the heap copier/broker,
which only expectes AsElementsKind to be called on initial maps.

This CL makes sure we only call AsElementsKind once (on the initial map).

Bug: chromium:890620
Change-Id: If44421d3900abb7629ea8f789a005b8d8ebaf881
Reviewed-on: https://chromium-review.googlesource.com/1253105Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56307}
parent ee984ee0
...@@ -475,7 +475,8 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) { ...@@ -475,7 +475,8 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
// Constructs an array with a variable {length} when no upper bound // Constructs an array with a variable {length} when no upper bound
// is known for the capacity. // is known for the capacity.
Reduction JSCreateLowering::ReduceNewArray( Reduction JSCreateLowering::ReduceNewArray(
Node* node, Node* length, MapRef initial_map, PretenureFlag pretenure, Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind,
PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction) { const SlackTrackingPrediction& slack_tracking_prediction) {
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
...@@ -484,8 +485,8 @@ Reduction JSCreateLowering::ReduceNewArray( ...@@ -484,8 +485,8 @@ Reduction JSCreateLowering::ReduceNewArray(
// Constructing an Array via new Array(N) where N is an unsigned // Constructing an Array via new Array(N) where N is an unsigned
// integer, always creates a holey backing store. // integer, always creates a holey backing store.
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING( ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind( initial_map,
GetHoleyElementsKind(initial_map.elements_kind()))); initial_map.AsElementsKind(GetHoleyElementsKind(elements_kind)));
// Check that the {limit} is an unsigned integer in the valid range. // Check that the {limit} is an unsigned integer in the valid range.
// This has to be kept in sync with src/runtime/runtime-array.cc, // This has to be kept in sync with src/runtime/runtime-array.cc,
...@@ -524,7 +525,7 @@ Reduction JSCreateLowering::ReduceNewArray( ...@@ -524,7 +525,7 @@ Reduction JSCreateLowering::ReduceNewArray(
// upper bound is known for the {capacity}. // upper bound is known for the {capacity}.
Reduction JSCreateLowering::ReduceNewArray( Reduction JSCreateLowering::ReduceNewArray(
Node* node, Node* length, int capacity, MapRef initial_map, Node* node, Node* length, int capacity, MapRef initial_map,
PretenureFlag pretenure, ElementsKind elements_kind, PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction) { const SlackTrackingPrediction& slack_tracking_prediction) {
DCHECK(node->opcode() == IrOpcode::kJSCreateArray || DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray); node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
...@@ -532,12 +533,11 @@ Reduction JSCreateLowering::ReduceNewArray( ...@@ -532,12 +533,11 @@ Reduction JSCreateLowering::ReduceNewArray(
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
// Determine the appropriate elements kind. // Determine the appropriate elements kind.
ElementsKind elements_kind = initial_map.elements_kind();
if (NodeProperties::GetType(length).Max() > 0.0) { if (NodeProperties::GetType(length).Max() > 0.0) {
elements_kind = GetHoleyElementsKind(elements_kind); elements_kind = GetHoleyElementsKind(elements_kind);
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind(elements_kind));
} }
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind(elements_kind));
DCHECK(IsFastElementsKind(elements_kind)); DCHECK(IsFastElementsKind(elements_kind));
// Setup elements and properties. // Setup elements and properties.
...@@ -569,15 +569,16 @@ Reduction JSCreateLowering::ReduceNewArray( ...@@ -569,15 +569,16 @@ Reduction JSCreateLowering::ReduceNewArray(
Reduction JSCreateLowering::ReduceNewArray( Reduction JSCreateLowering::ReduceNewArray(
Node* node, std::vector<Node*> values, MapRef initial_map, Node* node, std::vector<Node*> values, MapRef initial_map,
PretenureFlag pretenure, ElementsKind elements_kind, PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction) { const SlackTrackingPrediction& slack_tracking_prediction) {
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
// Determine the appropriate elements kind. // Determine the appropriate elements kind.
ElementsKind elements_kind = initial_map.elements_kind();
DCHECK(IsFastElementsKind(elements_kind)); DCHECK(IsFastElementsKind(elements_kind));
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind(elements_kind));
// Check {values} based on the {elements_kind}. These checks are guarded // Check {values} based on the {elements_kind}. These checks are guarded
// by the {elements_kind} feedback on the {site}, so it's safe to just // by the {elements_kind} feedback on the {site}, so it's safe to just
...@@ -663,10 +664,9 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -663,10 +664,9 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
bool can_inline_call = false; bool can_inline_call = false;
// Check if we have a feedback {site} on the {node}. // Check if we have a feedback {site} on the {node}.
ElementsKind elements_kind = initial_map.elements_kind();
if (site_ref) { if (site_ref) {
ElementsKind elements_kind = site_ref->GetElementsKind(); elements_kind = site_ref->GetElementsKind();
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind(elements_kind));
can_inline_call = site_ref->CanInlineCall(); can_inline_call = site_ref->CanInlineCall();
pretenure = dependencies()->DependOnPretenureMode(*site_ref); pretenure = dependencies()->DependOnPretenureMode(*site_ref);
dependencies()->DependOnElementsKind(*site_ref); dependencies()->DependOnElementsKind(*site_ref);
...@@ -677,7 +677,8 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -677,7 +677,8 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
if (arity == 0) { if (arity == 0) {
Node* length = jsgraph()->ZeroConstant(); Node* length = jsgraph()->ZeroConstant();
int capacity = JSArray::kPreallocatedArrayElements; int capacity = JSArray::kPreallocatedArrayElements;
return ReduceNewArray(node, length, capacity, initial_map, pretenure, return ReduceNewArray(node, length, capacity, initial_map,
elements_kind, pretenure,
slack_tracking_prediction); slack_tracking_prediction);
} else if (arity == 1) { } else if (arity == 1) {
Node* length = NodeProperties::GetValueInput(node, 2); Node* length = NodeProperties::GetValueInput(node, 2);
...@@ -685,26 +686,25 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -685,26 +686,25 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
if (!length_type.Maybe(Type::Number())) { if (!length_type.Maybe(Type::Number())) {
// Handle the single argument case, where we know that the value // Handle the single argument case, where we know that the value
// cannot be a valid Array length. // cannot be a valid Array length.
ElementsKind elements_kind = initial_map.elements_kind();
elements_kind = GetMoreGeneralElementsKind( elements_kind = GetMoreGeneralElementsKind(
elements_kind, IsHoleyElementsKind(elements_kind) elements_kind, IsHoleyElementsKind(elements_kind)
? HOLEY_ELEMENTS ? HOLEY_ELEMENTS
: PACKED_ELEMENTS); : PACKED_ELEMENTS);
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
initial_map, initial_map.AsElementsKind(elements_kind));
return ReduceNewArray(node, std::vector<Node*>{length}, initial_map, return ReduceNewArray(node, std::vector<Node*>{length}, initial_map,
pretenure, slack_tracking_prediction); elements_kind, pretenure,
slack_tracking_prediction);
} }
if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 && if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 &&
length_type.Max() <= kElementLoopUnrollLimit && length_type.Max() <= kElementLoopUnrollLimit &&
length_type.Min() == length_type.Max()) { length_type.Min() == length_type.Max()) {
int capacity = static_cast<int>(length_type.Max()); int capacity = static_cast<int>(length_type.Max());
return ReduceNewArray(node, length, capacity, initial_map, pretenure, return ReduceNewArray(node, length, capacity, initial_map,
elements_kind, pretenure,
slack_tracking_prediction); slack_tracking_prediction);
} }
if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) { if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
return ReduceNewArray(node, length, initial_map, pretenure, return ReduceNewArray(node, length, initial_map, elements_kind,
slack_tracking_prediction); pretenure, slack_tracking_prediction);
} }
} else if (arity <= JSArray::kInitialMaxFastElementArray) { } else if (arity <= JSArray::kInitialMaxFastElementArray) {
// Gather the values to store into the newly created array. // Gather the values to store into the newly created array.
...@@ -728,7 +728,6 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -728,7 +728,6 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
} }
// Try to figure out the ideal elements kind statically. // Try to figure out the ideal elements kind statically.
ElementsKind elements_kind = initial_map.elements_kind();
if (values_all_smis) { if (values_all_smis) {
// Smis can be stored with any elements kind. // Smis can be stored with any elements kind.
} else if (values_all_numbers) { } else if (values_all_numbers) {
...@@ -749,10 +748,8 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -749,10 +748,8 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
// we cannot inline this invocation of the Array constructor here. // we cannot inline this invocation of the Array constructor here.
return NoChange(); return NoChange();
} }
ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING( return ReduceNewArray(node, values, initial_map, elements_kind,
initial_map, initial_map.AsElementsKind(elements_kind)); pretenure, slack_tracking_prediction);
return ReduceNewArray(node, values, initial_map, pretenure,
slack_tracking_prediction);
} }
} }
} }
...@@ -1097,7 +1094,8 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) { ...@@ -1097,7 +1094,8 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
DCHECK(!initial_map.IsInobjectSlackTrackingInProgress()); DCHECK(!initial_map.IsInobjectSlackTrackingInProgress());
SlackTrackingPrediction slack_tracking_prediction( SlackTrackingPrediction slack_tracking_prediction(
initial_map, initial_map.instance_size()); initial_map, initial_map.instance_size());
return ReduceNewArray(node, length, 0, initial_map, pretenure, return ReduceNewArray(node, length, 0, initial_map,
initial_map.elements_kind(), pretenure,
slack_tracking_prediction); slack_tracking_prediction);
} }
return NoChange(); return NoChange();
......
...@@ -67,15 +67,16 @@ class V8_EXPORT_PRIVATE JSCreateLowering final ...@@ -67,15 +67,16 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
Reduction ReduceJSCreateBlockContext(Node* node); Reduction ReduceJSCreateBlockContext(Node* node);
Reduction ReduceJSCreateGeneratorObject(Node* node); Reduction ReduceJSCreateGeneratorObject(Node* node);
Reduction ReduceNewArray( Reduction ReduceNewArray(
Node* node, Node* length, MapRef initial_map, PretenureFlag pretenure, Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind,
PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction); const SlackTrackingPrediction& slack_tracking_prediction);
Reduction ReduceNewArray( Reduction ReduceNewArray(
Node* node, Node* length, int capacity, MapRef initial_map, Node* node, Node* length, int capacity, MapRef initial_map,
PretenureFlag pretenure, ElementsKind elements_kind, PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction); const SlackTrackingPrediction& slack_tracking_prediction);
Reduction ReduceNewArray( Reduction ReduceNewArray(
Node* node, std::vector<Node*> values, MapRef initial_map, Node* node, std::vector<Node*> values, MapRef initial_map,
PretenureFlag pretenure, ElementsKind elements_kind, PretenureFlag pretenure,
const SlackTrackingPrediction& slack_tracking_prediction); const SlackTrackingPrediction& slack_tracking_prediction);
Reduction ReduceJSCreateObject(Node* node); Reduction ReduceJSCreateObject(Node* node);
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var a = 42;
function g(n) {
while (n > 0) {
a = new Array(n);
n--;
}
}
g(1);
function f() {
g();
}
f();
%OptimizeFunctionOnNextCall(f);
f();
assertEquals(1, a.length);
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