[TurboFan] Loop variable analysis requires more sensitivity
Loop variable analysis doesn't recognize that the initial type of the
loop variable phi combined with the increment type may produce a NaN
result through the addition of two infinities of differing sign.
This leads to unreachable code and a SIGINT crash.
The fix is to consider this case before typing the loop variable phi,
falling back to more conservative typing if discovered.
R=neis@chromium.org
Bug: chromium:1028863
Change-Id: Ic4b5189c4c50c5bbe29e46050de630fd0673de9f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1946352
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65291}
diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc
index 9a0dea6..91b4b51 100644
--- a/src/compiler/graph-reducer.cc
+++ b/src/compiler/graph-reducer.cc
@@ -94,7 +94,8 @@
// all the other reducers for this node, as now there may be more
// opportunities for reduction.
if (FLAG_trace_turbo_reduction) {
- StdoutStream{} << "- In-place update of " << *node << " by reducer "
+ AllowHandleDereference allow_deref;
+ StdoutStream{} << "- In-place update of #" << *node << " by reducer "
<< (*i)->reducer_name() << std::endl;
}
skip = i;
@@ -103,7 +104,8 @@
} else {
// {node} was replaced by another node.
if (FLAG_trace_turbo_reduction) {
- StdoutStream{} << "- Replacement of " << *node << " with "
+ AllowHandleDereference allow_deref;
+ StdoutStream{} << "- Replacement of #" << *node << " with #"
<< *(reduction.replacement()) << " by reducer "
<< (*i)->reducer_name() << std::endl;
}
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index b3d7d49..7e0f81d 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -847,13 +847,30 @@
DCHECK_EQ(IrOpcode::kLoop, NodeProperties::GetControlInput(node)->opcode());
DCHECK_EQ(2, NodeProperties::GetControlInput(node)->InputCount());
+ auto res = induction_vars_->induction_variables().find(node->id());
+ DCHECK(res != induction_vars_->induction_variables().end());
+ InductionVariable* induction_var = res->second;
+ InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
Type initial_type = Operand(node, 0);
Type increment_type = Operand(node, 2);
+ const bool both_types_integer = initial_type.Is(typer_->cache_->kInteger) &&
+ increment_type.Is(typer_->cache_->kInteger);
+ bool maybe_nan = false;
+ // The addition or subtraction could still produce a NaN, if the integer
+ // ranges touch infinity.
+ if (both_types_integer) {
+ Type resultant_type =
+ (arithmetic_type == InductionVariable::ArithmeticType::kAddition)
+ ? typer_->operation_typer()->NumberAdd(initial_type, increment_type)
+ : typer_->operation_typer()->NumberSubtract(initial_type,
+ increment_type);
+ maybe_nan = resultant_type.Maybe(Type::NaN());
+ }
+
// We only handle integer induction variables (otherwise ranges
// do not apply and we cannot do anything).
- if (!initial_type.Is(typer_->cache_->kInteger) ||
- !increment_type.Is(typer_->cache_->kInteger)) {
+ if (!both_types_integer || maybe_nan) {
// Fallback to normal phi typing, but ensure monotonicity.
// (Unfortunately, without baking in the previous type, monotonicity might
// be violated because we might not yet have retyped the incrementing
@@ -874,12 +891,6 @@
}
// Now process the bounds.
- auto res = induction_vars_->induction_variables().find(node->id());
- DCHECK(res != induction_vars_->induction_variables().end());
- InductionVariable* induction_var = res->second;
-
- InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
-
double min = -V8_INFINITY;
double max = V8_INFINITY;
diff --git a/test/mjsunit/regress/regress-crbug-1028863.js b/test/mjsunit/regress/regress-crbug-1028863.js
new file mode 100644
index 0000000..d210663
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-1028863.js
@@ -0,0 +1,24 @@
+// Copyright 2019 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
+
+function write(begin, end, step) {
+ for (var i = begin; i >= end; i += step) {
+ step = end - begin;
+ begin >>>= 805306382;
+ }
+}
+
+function bar() {
+ for (let i = 0; i < 10000; i++) {
+ write(Infinity, 1, 1);
+ }
+}
+
+%PrepareFunctionForOptimization(write);
+%PrepareFunctionForOptimization(bar);
+bar();
+%OptimizeFunctionOnNextCall(bar);
+bar();