Commit d9c9b003 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Fix wrong optimization of Number.parseInt

We incorrectly used a TurboFan typer check for {0,10,undefined} on the
radix argument on Number.parseInt, which was internally widened to the
checking whether radix is in range 0-10 or undefined. This CL introduces
two separate checks.

Bug: chromium:838766
Change-Id: I5ebfc1c82bad5b9794b4f844e79e4df01f541a83
Reviewed-on: https://chromium-review.googlesource.com/1039197Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52914}
parent c77c869c
...@@ -2227,8 +2227,11 @@ Reduction JSTypedLowering::ReduceJSParseInt(Node* node) { ...@@ -2227,8 +2227,11 @@ Reduction JSTypedLowering::ReduceJSParseInt(Node* node) {
Type value_type = NodeProperties::GetType(value); Type value_type = NodeProperties::GetType(value);
Node* radix = NodeProperties::GetValueInput(node, 1); Node* radix = NodeProperties::GetValueInput(node, 1);
Type radix_type = NodeProperties::GetType(radix); Type radix_type = NodeProperties::GetType(radix);
// We need kTenOrUndefined and kZeroOrUndefined because
// the type representing {0,10} would become the range 1-10.
if (value_type.Is(type_cache_.kSafeInteger) && if (value_type.Is(type_cache_.kSafeInteger) &&
radix_type.Is(type_cache_.kZeroOrTenOrUndefined)) { (radix_type.Is(type_cache_.kTenOrUndefined) ||
radix_type.Is(type_cache_.kZeroOrUndefined))) {
// Number.parseInt(a:safe-integer) -> a // Number.parseInt(a:safe-integer) -> a
// Number.parseInt(a:safe-integer,b:#0\/undefined) -> a // Number.parseInt(a:safe-integer,b:#0\/undefined) -> a
// Number.parseInt(a:safe-integer,b:#10\/undefined) -> a // Number.parseInt(a:safe-integer,b:#10\/undefined) -> a
......
...@@ -49,8 +49,8 @@ class TypeCache final { ...@@ -49,8 +49,8 @@ class TypeCache final {
Type::Union(kSingletonZero, Type::MinusZero(), zone()); Type::Union(kSingletonZero, Type::MinusZero(), zone());
Type const kZeroOrUndefined = Type const kZeroOrUndefined =
Type::Union(kSingletonZero, Type::Undefined(), zone()); Type::Union(kSingletonZero, Type::Undefined(), zone());
Type const kZeroOrTenOrUndefined = Type const kTenOrUndefined =
Type::Union(kZeroOrUndefined, kSingletonTen, zone()); Type::Union(kSingletonTen, Type::Undefined(), zone());
Type const kMinusOneOrZero = CreateRange(-1.0, 0.0); Type const kMinusOneOrZero = CreateRange(-1.0, 0.0);
Type const kMinusOneToOneOrMinusZeroOrNaN = Type::Union( Type const kMinusOneToOneOrMinusZeroOrNaN = Type::Union(
Type::Union(CreateRange(-1.0, 1.0), Type::MinusZero(), zone()), Type::Union(CreateRange(-1.0, 1.0), Type::MinusZero(), zone()),
......
// 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
function foo(x) {
x = x | 2147483648;
return Number.parseInt(x + 65535, 8);
}
assertEquals(-72161, foo());
assertEquals(-72161, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(-72161, foo());
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