[turbofan] Better handling of empty type in simplified lowering.

The re-typer now only types a node if its inputs are all typed with the
exception of phi nodes. This works because all cycles in the graph have
to contain a phi node.

BUG=chromium:625558

Review-Url: https://codereview.chromium.org/2120243002
Cr-Commit-Position: refs/heads/master@{#37493}
This commit is contained in:
jarin 2016-07-04 01:42:24 -07:00 committed by Commit bot
parent 27965f19a4
commit 9fdacb9e55
4 changed files with 63 additions and 33 deletions

View File

@ -289,6 +289,10 @@ Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
// We can give more precise types for integers.
if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) ||
!rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) {
@ -311,6 +315,10 @@ Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
lhs = Rangify(lhs);
rhs = Rangify(rhs);
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
@ -324,6 +332,11 @@ Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) {
Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
lhs = Rangify(lhs);
rhs = Rangify(rhs);
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
@ -337,6 +350,10 @@ Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
// Division is tricky, so all we do is try ruling out nan.
bool maybe_nan =
@ -349,6 +366,11 @@ Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) {
Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
@ -403,6 +425,11 @@ Type* OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) {
lhs = ToPrimitive(lhs);
rhs = ToPrimitive(rhs);
if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
return Type::None();
}
if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
return Type::String();

View File

@ -357,17 +357,25 @@ class RepresentationSelector {
Type* type = info->feedback_type();
Type* new_type = type;
// For any non-phi node just wait until we get all inputs typed. We only
// allow untyped inputs for phi nodes because phis are the only places
// where cycles need to be broken.
if (node->opcode() != IrOpcode::kPhi) {
for (int i = 0; i < node->op()->ValueInputCount(); i++) {
if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) {
return false;
}
}
}
switch (node->opcode()) {
case IrOpcode::kSpeculativeNumberAdd: {
Type* lhs = FeedbackTypeOf(node->InputAt(0));
Type* rhs = FeedbackTypeOf(node->InputAt(1));
if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
// fail on a boolean. OperationTyper should have a function that
// computes a more precise type.
lhs = op_typer_.ToNumber(lhs);
rhs = op_typer_.ToNumber(rhs);
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericAdd(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
@ -379,15 +387,12 @@ class RepresentationSelector {
}
case IrOpcode::kSpeculativeNumberSubtract: {
Type* lhs = FeedbackTypeOf(node->InputAt(0));
Type* rhs = FeedbackTypeOf(node->InputAt(1));
if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
// fail on a boolean. OperationTyper should have a function that
// computes a more precise type.
lhs = op_typer_.ToNumber(lhs);
rhs = op_typer_.ToNumber(rhs);
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericSubtract(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
@ -399,15 +404,12 @@ class RepresentationSelector {
}
case IrOpcode::kSpeculativeNumberMultiply: {
Type* lhs = FeedbackTypeOf(node->InputAt(0));
Type* rhs = FeedbackTypeOf(node->InputAt(1));
if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
// fail on a boolean. OperationTyper should have a function that
// computes a more precise type.
lhs = op_typer_.ToNumber(lhs);
rhs = op_typer_.ToNumber(rhs);
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericMultiply(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
@ -419,15 +421,12 @@ class RepresentationSelector {
}
case IrOpcode::kSpeculativeNumberDivide: {
Type* lhs = FeedbackTypeOf(node->InputAt(0));
Type* rhs = FeedbackTypeOf(node->InputAt(1));
if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
// fail on a boolean. OperationTyper should have a function that
// computes a more precise type.
lhs = op_typer_.ToNumber(lhs);
rhs = op_typer_.ToNumber(rhs);
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericDivide(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
@ -439,15 +438,12 @@ class RepresentationSelector {
}
case IrOpcode::kSpeculativeNumberModulus: {
Type* lhs = FeedbackTypeOf(node->InputAt(0));
Type* rhs = FeedbackTypeOf(node->InputAt(1));
if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
// fail on a boolean. OperationTyper should have a function that
// computes a more precise type.
lhs = op_typer_.ToNumber(lhs);
rhs = op_typer_.ToNumber(rhs);
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericModulus(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
@ -945,7 +941,6 @@ class RepresentationSelector {
}
MachineSemantic DeoptValueSemanticOf(Type* type) {
CHECK(!type->Is(Type::None()));
// We only need signedness to do deopt correctly.
if (type->Is(Type::Signed32())) {
return MachineSemantic::kInt32;

View File

@ -0,0 +1,14 @@
// Copyright 2016 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
for (var global = 0; global <= 256; global++) { }
function f() {
global = "luft";
global += ++global;
}
f();

View File

@ -251,7 +251,7 @@
'debug-scopes': [PASS, SLOW],
'numops-fuzz-part*': [PASS, ['mode == debug', SLOW]],
'readonly': [PASS, SLOW],
'regress/regress-1200351': [PASS, ['mode == debug', SLOW]],
'regress/regress-1200351': [PASS, SLOW],
'regress/regress-crbug-474297': [PASS, ['mode == debug', SLOW]],
'es6/tail-call-megatest*': [PASS, SLOW, FAST_VARIANTS, ['tsan', SKIP]],
@ -413,12 +413,6 @@
'wasm/embenchen/fasta': [PASS, FAST_VARIANTS],
}], # 'gc_stress == True'
##############################################################################
['no_i18n == True and mode == debug', {
# Tests too slow for no18n debug.
'regress/regress-1200351': [SKIP],
}], # 'no_i18n == True and mode == debug'
##############################################################################
['byteorder == big', {
# Emscripten requires little-endian, skip all tests on big endian platforms.