Reviewers: Benedikt Meurer,
Message:
Could you take a look, please?
Description:
[turbofan] Fix typing of comparisons.
BUG=chromium:459955
LOG=n
[email protected]
Please review this at https://codereview.chromium.org/943483002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+63, -21 lines):
M src/compiler/typer.cc
A + test/mjsunit/regress/regress-459955.js
Index: src/compiler/typer.cc
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index
e9f3a3564ffd8da3e93b35b4eb8c644fb7baad32..f646d19ba13d3ab03a318e328b93316639823c94
100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/base/flags.h"
#include "src/bootstrapper.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
@@ -325,8 +326,16 @@ class Typer::Visitor : public Reducer {
Bounds TypeUnaryOp(Node* node, UnaryTyperFun);
Bounds TypeBinaryOp(Node* node, BinaryTyperFun);
+ enum ComparisonOutcomeFlags {
+ kComparisonTrue = 1,
+ kComparisonFalse = 2,
+ kComparisonUndefined = 4
+ };
+ typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome;
+
+ static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
static Type* Invert(Type*, Typer*);
- static Type* FalsifyUndefined(Type*, Typer*);
+ static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
static Type* Rangify(Type*, Typer*);
static Type* ToPrimitive(Type*, Typer*);
@@ -342,7 +351,7 @@ class Typer::Visitor : public Reducer {
static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*);
static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*);
- static Type* JSCompareTyper(Type*, Type*, Typer*);
+ static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*);
#define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
@@ -468,15 +477,33 @@ Bounds Typer::Visitor::TypeBinaryOp(Node* node,
BinaryTyperFun f) {
Type* Typer::Visitor::Invert(Type* type, Typer* t) {
+ DCHECK(type->Is(Type::Boolean()));
+ DCHECK(type->IsInhabited());
if (type->Is(t->singleton_false)) return t->singleton_true;
if (type->Is(t->singleton_true)) return t->singleton_false;
return type;
}
-Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) {
- if (type->Is(Type::Undefined())) return t->singleton_false;
- return type;
+Typer::Visitor::ComparisonOutcome Typer::Visitor::Invert(
+ ComparisonOutcome outcome, Typer* t) {
+ ComparisonOutcome result(0);
+ if ((outcome & kComparisonUndefined) != 0) result |=
kComparisonUndefined;
+ if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
+ if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
+ return result;
+}
+
+
+Type* Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer*
t) {
+ if ((outcome & kComparisonFalse) != 0 ||
+ (outcome & kComparisonUndefined) != 0) {
+ return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
+ : t->singleton_false;
+ }
+ // Type should be non empty, so we know it should be true.
+ DCHECK((outcome & kComparisonTrue) != 0);
+ return t->singleton_true;
}
@@ -773,26 +800,41 @@ Type* Typer::Visitor::JSStrictNotEqualTyper(Type*
lhs, Type* rhs, Typer* t) {
// (<, <=, >=, >) with the help of a single abstract one. It behaves like
<
// but returns undefined when the inputs cannot be compared.
// We implement the typing analogously.
-Type* Typer::Visitor::JSCompareTyper(Type* lhs, Type* rhs, Typer* t) {
+Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs,
+ Type* rhs,
+ Typer* t)
{
lhs = ToPrimitive(lhs, t);
rhs = ToPrimitive(rhs, t);
if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) {
- return Type::Boolean();
+ return ComparisonOutcome(kComparisonTrue) |
+ ComparisonOutcome(kComparisonFalse);
}
lhs = ToNumber(lhs, t);
rhs = ToNumber(rhs, t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return
Type::Undefined();
+
+ // Shortcut for NaNs.
+ if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return
kComparisonUndefined;
+
+ ComparisonOutcome result;
if (lhs->IsConstant() && rhs->Is(lhs)) {
- // Types are equal and are inhabited only by a single semantic value,
- // which is not NaN due to the previous check.
- return t->singleton_false;
+ // Types are equal and are inhabited only by a single semantic value.
+ result = kComparisonFalse;
+ } else if (lhs->Min() >= rhs->Max()) {
+ result = kComparisonFalse;
+ } else if (lhs->Max() < rhs->Min()) {
+ result = kComparisonTrue;
+ } else {
+ // We cannot figure out the result, return both true and false. (We do
not
+ // have to return undefined because that cannot affect the result of
+ // FalsifyUndefined.)
+ return ComparisonOutcome(kComparisonTrue) |
+ ComparisonOutcome(kComparisonFalse);
}
- if (lhs->Min() >= rhs->Max()) return t->singleton_false;
- if (lhs->Max() < rhs->Min() &&
- !lhs->Maybe(Type::NaN()) && !rhs->Maybe(Type::NaN())) {
- return t->singleton_true;
+ // Add the undefined if we could see NaN.
+ if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
+ result |= kComparisonUndefined;
}
- return Type::Boolean();
+ return result;
}
Index: test/mjsunit/regress/regress-459955.js
diff --git a/test/message/super-in-function.js
b/test/mjsunit/regress/regress-459955.js
similarity index 68%
copy from test/message/super-in-function.js
copy to test/mjsunit/regress/regress-459955.js
index
edaa0e4eadc7befdb7ed28a3e06eaa827c4388f0..24eff6d40ca3ea359b0f3f843a86011d4cf0781f
100644
--- a/test/message/super-in-function.js
+++ b/test/mjsunit/regress/regress-459955.js
@@ -1,10 +1,10 @@
// Copyright 2015 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: --harmony-classes
-'use strict';
-function f() {
- super.x();
+function f(x) {
+ var v;
+ if (x) v = 0;
+ return v <= 1;
}
+assertFalse(f(false));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.