[turbofan] Fix handling of null in -0 == null comparison

TurboFan truncated null to +0 even in contexts such as -0 == null
because it was not handling the TypeCheck correctly. This restricts
the type conversion case to not apply truncation in this case (see
comment in patch).

Change-Id: Ia38ace9608800c8d61988de402a31dd863d9160a
Bug: chromium:961237
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1609538
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61446}
This commit is contained in:
Sigurd Schneider 2019-05-13 14:55:29 +02:00 committed by Commit Bot
parent c5a16a397e
commit 210856603f
3 changed files with 27 additions and 3 deletions

View File

@ -863,8 +863,17 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
op = machine()->ChangeInt32ToFloat64();
} else if (output_type.Is(Type::Number())) {
op = simplified()->ChangeTaggedToFloat64();
} else if (output_type.Is(Type::NumberOrOddball())) {
// TODO(jarin) Here we should check that truncation is Number.
} else if ((output_type.Is(Type::NumberOrOddball()) &&
use_info.truncation().IsUsedAsFloat64()) ||
output_type.Is(Type::NumberOrHole())) {
// JavaScript 'null' is an Oddball that results in +0 when truncated to
// Number. In a context like -0 == null, which must evaluate to false,
// this truncation must not happen. For this reason we restrict this case
// to when either the user explicitly requested a float (and thus wants
// +0 if null is the input) or we know from the types that the input can
// only be Number | Hole. The latter is necessary to handle the operator
// CheckFloat64Hole. We did not put in the type (Number | Oddball \ Null)
// to discover more bugs related to this conversion via crashes.
op = simplified()->TruncateTaggedToFloat64();
} else if (use_info.type_check() == TypeCheckKind::kNumber ||
(use_info.type_check() == TypeCheckKind::kNumberOrOddball &&

View File

@ -544,7 +544,7 @@ TEST(SingleChanges) {
Type::Number(), MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kTruncateTaggedToFloat64,
MachineRepresentation::kTagged, Type::NumberOrUndefined(),
MachineRepresentation::kFloat64);
UseInfo(MachineRepresentation::kFloat64, Truncation::Float64()));
CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
Type::Signed31(), MachineRepresentation::kFloat64);

View File

@ -0,0 +1,15 @@
// 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
const a = 1.1;
const b = null;
function f(x) { return -0 == (x ? a : b); }
%PrepareFunctionForOptimization(f);
assertEquals(false, f(true));
assertEquals(false, f(true));
%OptimizeFunctionOnNextCall(f);
assertEquals(false, f(false));