Commit c85aa830 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Harden type-based elimination of MaybeGrowFastElements

... against potential typer bugs. Instead of simply eliminating the
operation, insert an aborting bounds check instead.

Also move this transformation out of SimplifiedLowering, which is
already complex enough without doing these kinds of optimizations.
Unfortunately this will result in some missed optimization opportunities
because we may have more precise types during SimplifiedLowering. Let's
see if this makes a visible performance difference.

Change-Id: I9c16ad33104c29fdba39bf729d69ee03fc9797d6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2129633
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67222}
parent 3df19d31
...@@ -3580,25 +3580,12 @@ class RepresentationSelector { ...@@ -3580,25 +3580,12 @@ class RepresentationSelector {
return VisitBinop(node, UseInfo::AnyTagged(), return VisitBinop(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer); MachineRepresentation::kTaggedPointer);
case IrOpcode::kMaybeGrowFastElements: { case IrOpcode::kMaybeGrowFastElements: {
Type const index_type = TypeOf(node->InputAt(2));
Type const length_type = TypeOf(node->InputAt(3));
ProcessInput(node, 0, UseInfo::AnyTagged()); // object ProcessInput(node, 0, UseInfo::AnyTagged()); // object
ProcessInput(node, 1, UseInfo::AnyTagged()); // elements ProcessInput(node, 1, UseInfo::AnyTagged()); // elements
ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index
ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length
ProcessRemainingInputs(node, 4); ProcessRemainingInputs(node, 4);
SetOutput(node, MachineRepresentation::kTaggedPointer); SetOutput(node, MachineRepresentation::kTaggedPointer);
if (lower()) {
// If the index is known to be less than the length (or if
// we're in dead code), we know that we don't need to grow
// the elements, so we can just remove this operation all
// together and replace it with the elements that we have
// on the inputs.
if (index_type.IsNone() || length_type.IsNone() ||
index_type.Max() < length_type.Min()) {
DeferReplacement(node, node->InputAt(1));
}
}
return; return;
} }
......
...@@ -38,6 +38,8 @@ Reduction TypedOptimization::Reduce(Node* node) { ...@@ -38,6 +38,8 @@ Reduction TypedOptimization::Reduce(Node* node) {
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kConvertReceiver: case IrOpcode::kConvertReceiver:
return ReduceConvertReceiver(node); return ReduceConvertReceiver(node);
case IrOpcode::kMaybeGrowFastElements:
return ReduceMaybeGrowFastElements(node);
case IrOpcode::kCheckHeapObject: case IrOpcode::kCheckHeapObject:
return ReduceCheckHeapObject(node); return ReduceCheckHeapObject(node);
case IrOpcode::kCheckNotTaggedHole: case IrOpcode::kCheckNotTaggedHole:
...@@ -159,6 +161,31 @@ Reduction TypedOptimization::ReduceCheckHeapObject(Node* node) { ...@@ -159,6 +161,31 @@ Reduction TypedOptimization::ReduceCheckHeapObject(Node* node) {
return NoChange(); return NoChange();
} }
Reduction TypedOptimization::ReduceMaybeGrowFastElements(Node* node) {
Node* const elements = NodeProperties::GetValueInput(node, 1);
Node* const index = NodeProperties::GetValueInput(node, 2);
Node* const length = NodeProperties::GetValueInput(node, 3);
Node* const effect = NodeProperties::GetEffectInput(node);
Node* const control = NodeProperties::GetControlInput(node);
Type const index_type = NodeProperties::GetType(index);
Type const length_type = NodeProperties::GetType(length);
CHECK(index_type.Is(Type::Unsigned31()));
CHECK(length_type.Is(Type::Unsigned31()));
if (!index_type.IsNone() && !length_type.IsNone() &&
index_type.Max() < length_type.Min()) {
Node* check_bounds = graph()->NewNode(
simplified()->CheckBounds(FeedbackSource{},
CheckBoundsParameters::kAbortOnOutOfBounds),
index, length, effect, control);
ReplaceWithValue(node, elements);
return Replace(check_bounds);
}
return NoChange();
}
Reduction TypedOptimization::ReduceCheckNotTaggedHole(Node* node) { Reduction TypedOptimization::ReduceCheckNotTaggedHole(Node* node) {
Node* const input = NodeProperties::GetValueInput(node, 0); Node* const input = NodeProperties::GetValueInput(node, 0);
Type const input_type = NodeProperties::GetType(input); Type const input_type = NodeProperties::GetType(input);
...@@ -285,7 +312,7 @@ Reduction TypedOptimization::ReduceNumberFloor(Node* node) { ...@@ -285,7 +312,7 @@ Reduction TypedOptimization::ReduceNumberFloor(Node* node) {
// NumberToUint32(NumberDivide(lhs, rhs)) // NumberToUint32(NumberDivide(lhs, rhs))
// //
// and just smash the type [0...lhs.Max] on the {node}, // and just smash the type [0...lhs.Max] on the {node},
// as the truncated result must be loewr than {lhs}'s maximum // as the truncated result must be lower than {lhs}'s maximum
// value (note that {rhs} cannot be less than 1 due to the // value (note that {rhs} cannot be less than 1 due to the
// plain-number type constraint on the {node}). // plain-number type constraint on the {node}).
NodeProperties::ChangeOp(node, simplified()->NumberToUint32()); NodeProperties::ChangeOp(node, simplified()->NumberToUint32());
......
...@@ -37,6 +37,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final ...@@ -37,6 +37,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final
private: private:
Reduction ReduceConvertReceiver(Node* node); Reduction ReduceConvertReceiver(Node* node);
Reduction ReduceMaybeGrowFastElements(Node* node);
Reduction ReduceCheckHeapObject(Node* node); Reduction ReduceCheckHeapObject(Node* node);
Reduction ReduceCheckMaps(Node* node); Reduction ReduceCheckMaps(Node* node);
Reduction ReduceCheckNumber(Node* node); Reduction ReduceCheckNumber(Node* node);
......
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