Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index d98d2fe..2bc0bb3 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -10,8 +10,9 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
-#include "src/compiler/node.h"
#include "src/compiler/node-properties.h"
+#include "src/compiler/node.h"
+#include "src/compiler/operation-typer.h"
#include "src/compiler/simplified-operator.h"
#include "src/objects-inl.h"
#include "src/type-cache.h"
@@ -37,14 +38,15 @@
dependencies_(dependencies),
function_type_(function_type),
decorator_(nullptr),
- cache_(TypeCache::Get()) {
+ cache_(TypeCache::Get()),
+ operation_typer_(isolate, zone()) {
Zone* zone = this->zone();
Factory* const factory = isolate->factory();
Type* infinity = Type::Constant(factory->infinity_value(), zone);
Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone);
- // TODO(neis): Unfortunately, the infinities created in other places might
- // be different ones (eg the result of NewNumber in TypeNumberConstant).
+ // Unfortunately, the infinities created in other places might be different
+ // ones (eg the result of NewNumber in TypeNumberConstant).
Type* truncating_to_zero =
Type::Union(Type::Union(infinity, minus_infinity, zone),
Type::MinusZeroOrNaN(), zone);
@@ -232,7 +234,6 @@
static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
static Type* Invert(Type*, Typer*);
static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
- static Type* Rangify(Type*, Typer*);
static Type* ToPrimitive(Type*, Typer*);
static Type* ToBoolean(Type*, Typer*);
@@ -242,6 +243,7 @@
static Type* ToNumber(Type*, Typer*);
static Type* ToObject(Type*, Typer*);
static Type* ToString(Type*, Typer*);
+ static Type* NumberAbs(Type*, Typer*);
static Type* NumberCeil(Type*, Typer*);
static Type* NumberFloor(Type*, Typer*);
static Type* NumberRound(Type*, Typer*);
@@ -256,11 +258,6 @@
static Type* ObjectIsString(Type*, Typer*);
static Type* ObjectIsUndetectable(Type*, Typer*);
- static Type* JSAddRanger(RangeType*, RangeType*, Typer*);
- static Type* JSSubtractRanger(RangeType*, RangeType*, Typer*);
- static Type* JSDivideRanger(RangeType*, RangeType*, Typer*);
- static Type* JSModulusRanger(RangeType*, RangeType*, Typer*);
-
static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*);
#define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
@@ -272,6 +269,7 @@
static Type* JSCallFunctionTyper(Type*, Typer*);
static Type* ReferenceEqualTyper(Type*, Type*, Typer*);
+ static Type* StringFromCharCodeTyper(Type*, Typer*);
Reduction UpdateType(Node* node, Type* current) {
if (NodeProperties::IsTyped(node)) {
@@ -380,27 +378,8 @@
return t->singleton_true_;
}
-
-Type* Typer::Visitor::Rangify(Type* type, Typer* t) {
- if (type->IsRange()) return type; // Shortcut.
- if (!type->Is(t->cache_.kInteger)) {
- return type; // Give up on non-integer types.
- }
- double min = type->Min();
- double max = type->Max();
- // Handle the degenerate case of empty bitset types (such as
- // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
- if (std::isnan(min)) {
- DCHECK(std::isnan(max));
- return type;
- }
- return Type::Range(min, max, t->zone());
-}
-
-
// Type conversion.
-
Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
return type;
@@ -501,6 +480,34 @@
}
// static
+Type* Typer::Visitor::NumberAbs(Type* type, Typer* t) {
+ DCHECK(type->Is(Type::Number()));
+ Factory* const f = t->isolate()->factory();
+ bool const maybe_nan = type->Maybe(Type::NaN());
+ bool const maybe_minuszero = type->Maybe(Type::MinusZero());
+ type = Type::Intersect(type, Type::PlainNumber(), t->zone());
+ double const max = type->Max();
+ double const min = type->Min();
+ if (min < 0) {
+ if (type->Is(t->cache_.kInteger)) {
+ type =
+ Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), t->zone());
+ } else if (min == max) {
+ type = Type::Constant(f->NewNumber(std::fabs(min)), t->zone());
+ } else {
+ type = Type::PlainNumber();
+ }
+ }
+ if (maybe_minuszero) {
+ type = Type::Union(type, t->cache_.kSingletonZero, t->zone());
+ }
+ if (maybe_nan) {
+ type = Type::Union(type, Type::NaN(), t->zone());
+ }
+ return type;
+}
+
+// static
Type* Typer::Visitor::NumberCeil(Type* type, Typer* t) {
DCHECK(type->Is(Type::Number()));
if (type->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) return type;
@@ -533,7 +540,6 @@
}
Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) {
- // TODO(neis): DCHECK(type->Is(Type::Number()));
if (type->Is(Type::Signed32())) return type;
if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero;
if (type->Is(t->signed32ish_)) {
@@ -546,7 +552,6 @@
Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) {
- // TODO(neis): DCHECK(type->Is(Type::Number()));
if (type->Is(Type::Unsigned32())) return type;
if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero;
if (type->Is(t->unsigned32ish_)) {
@@ -557,7 +562,6 @@
return Type::Unsigned32();
}
-
// Type checks.
Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
@@ -705,7 +709,7 @@
return Type::Intersect(input_type, guard_type, zone());
}
-Type* Typer::Visitor::TypeCheckPoint(Node* node) {
+Type* Typer::Visitor::TypeCheckpoint(Node* node) {
UNREACHABLE();
return nullptr;
}
@@ -765,7 +769,6 @@
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 earlier check.
- // TODO(neis): Extend this to Range(x,x), MinusZero, ...?
return t->singleton_true_;
}
return Type::Boolean();
@@ -876,7 +879,6 @@
return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
}
-
// JS bitwise operators.
@@ -909,7 +911,6 @@
max = std::min(max, -1.0);
}
return Type::Range(min, max, t->zone());
- // TODO(neis): Be precise for singleton inputs, here and elsewhere.
}
@@ -1010,64 +1011,6 @@
// JS arithmetic operators.
-
-// Returns the array's least element, ignoring NaN.
-// There must be at least one non-NaN element.
-// Any -0 is converted to 0.
-static double array_min(double a[], size_t n) {
- DCHECK(n != 0);
- double x = +V8_INFINITY;
- for (size_t i = 0; i < n; ++i) {
- if (!std::isnan(a[i])) {
- x = std::min(a[i], x);
- }
- }
- DCHECK(!std::isnan(x));
- return x == 0 ? 0 : x; // -0 -> 0
-}
-
-
-// Returns the array's greatest element, ignoring NaN.
-// There must be at least one non-NaN element.
-// Any -0 is converted to 0.
-static double array_max(double a[], size_t n) {
- DCHECK(n != 0);
- double x = -V8_INFINITY;
- for (size_t i = 0; i < n; ++i) {
- if (!std::isnan(a[i])) {
- x = std::max(a[i], x);
- }
- }
- DCHECK(!std::isnan(x));
- return x == 0 ? 0 : x; // -0 -> 0
-}
-
-Type* Typer::Visitor::JSAddRanger(RangeType* lhs, RangeType* rhs, Typer* t) {
- double results[4];
- results[0] = lhs->Min() + rhs->Min();
- results[1] = lhs->Min() + rhs->Max();
- results[2] = lhs->Max() + rhs->Min();
- results[3] = lhs->Max() + rhs->Max();
- // Since none of the inputs can be -0, the result cannot be -0 either.
- // However, it can be nan (the sum of two infinities of opposite sign).
- // On the other hand, if none of the "results" above is nan, then the actual
- // result cannot be nan either.
- int nans = 0;
- for (int i = 0; i < 4; ++i) {
- if (std::isnan(results[i])) ++nans;
- }
- if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa
- Type* range =
- Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
- return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
- // Examples:
- // [-inf, -inf] + [+inf, +inf] = NaN
- // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
- // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
- // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
-}
-
-
Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
lhs = ToPrimitive(lhs, t);
rhs = ToPrimitive(rhs, t);
@@ -1078,97 +1021,27 @@
return Type::NumberOrString();
}
}
- lhs = Rangify(ToNumber(lhs, t), t);
- rhs = Rangify(ToNumber(rhs, t), t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
- if (lhs->IsRange() && rhs->IsRange()) {
- return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t);
- }
- // TODO(neis): Deal with numeric bitsets here and elsewhere.
- return Type::Number();
+ // The addition must be numeric.
+ return t->operation_typer()->NumericAdd(ToNumber(lhs, t), ToNumber(rhs, t));
}
-Type* Typer::Visitor::JSSubtractRanger(RangeType* lhs, RangeType* rhs,
- Typer* t) {
- double results[4];
- results[0] = lhs->Min() - rhs->Min();
- results[1] = lhs->Min() - rhs->Max();
- results[2] = lhs->Max() - rhs->Min();
- results[3] = lhs->Max() - rhs->Max();
- // Since none of the inputs can be -0, the result cannot be -0.
- // However, it can be nan (the subtraction of two infinities of same sign).
- // On the other hand, if none of the "results" above is nan, then the actual
- // result cannot be nan either.
- int nans = 0;
- for (int i = 0; i < 4; ++i) {
- if (std::isnan(results[i])) ++nans;
- }
- if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
- Type* range =
- Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
- return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
- // Examples:
- // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
- // [-inf, -inf] - [-inf, -inf] = NaN
- // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
- // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
-}
-
-
Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
- lhs = Rangify(ToNumber(lhs, t), t);
- rhs = Rangify(ToNumber(rhs, t), t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
- if (lhs->IsRange() && rhs->IsRange()) {
- return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t);
- }
- return Type::Number();
+ return t->operation_typer()->NumericSubtract(ToNumber(lhs, t),
+ ToNumber(rhs, t));
}
-
Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
- lhs = Rangify(ToNumber(lhs, t), t);
- rhs = Rangify(ToNumber(rhs, t), t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
- if (lhs->IsRange() && rhs->IsRange()) {
- double results[4];
- double lmin = lhs->AsRange()->Min();
- double lmax = lhs->AsRange()->Max();
- double rmin = rhs->AsRange()->Min();
- double rmax = rhs->AsRange()->Max();
- results[0] = lmin * rmin;
- results[1] = lmin * rmax;
- results[2] = lmax * rmin;
- results[3] = lmax * rmax;
- // If the result may be nan, we give up on calculating a precise type,
- // because
- // the discontinuity makes it too complicated. Note that even if none of
- // the
- // "results" above is nan, the actual result may still be, so we have to do
- // a
- // different check:
- bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) &&
- (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
- (rhs->Maybe(t->cache_.kSingletonZero) &&
- (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
- if (maybe_nan) return t->cache_.kIntegerOrMinusZeroOrNaN; // Giving up.
- bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) ||
- (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0);
- Type* range =
- Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
- return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone())
- : range;
- }
- return Type::Number();
+ return t->operation_typer()->NumericMultiply(ToNumber(lhs, t),
+ ToNumber(rhs, t));
}
-
Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
+ return t->operation_typer()->NumericDivide(ToNumber(lhs, t),
+ ToNumber(rhs, t));
lhs = ToNumber(lhs, t);
rhs = ToNumber(rhs, t);
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
// Division is tricky, so all we do is try ruling out nan.
- // TODO(neis): try ruling out -0 as well?
bool maybe_nan =
lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) ||
((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
@@ -1176,56 +1049,9 @@
return maybe_nan ? Type::Number() : Type::OrderedNumber();
}
-Type* Typer::Visitor::JSModulusRanger(RangeType* lhs, RangeType* rhs,
- Typer* t) {
- double lmin = lhs->Min();
- double lmax = lhs->Max();
- double rmin = rhs->Min();
- double rmax = rhs->Max();
-
- double labs = std::max(std::abs(lmin), std::abs(lmax));
- double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
- double abs = std::min(labs, rabs);
- bool maybe_minus_zero = false;
- double omin = 0;
- double omax = 0;
- if (lmin >= 0) { // {lhs} positive.
- omin = 0;
- omax = abs;
- } else if (lmax <= 0) { // {lhs} negative.
- omin = 0 - abs;
- omax = 0;
- maybe_minus_zero = true;
- } else {
- omin = 0 - abs;
- omax = abs;
- maybe_minus_zero = true;
- }
-
- Type* result = Type::Range(omin, omax, t->zone());
- if (maybe_minus_zero)
- result = Type::Union(result, Type::MinusZero(), t->zone());
- return result;
-}
-
-
Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
- lhs = ToNumber(lhs, t);
- rhs = ToNumber(rhs, t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
-
- if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) ||
- lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) {
- // Result maybe NaN.
- return Type::Number();
- }
-
- lhs = Rangify(lhs, t);
- rhs = Rangify(rhs, t);
- if (lhs->IsRange() && rhs->IsRange()) {
- return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t);
- }
- return Type::OrderedNumber();
+ return t->operation_typer()->NumericModulus(ToNumber(lhs, t),
+ ToNumber(rhs, t));
}
@@ -1550,9 +1376,10 @@
case kMathTrunc:
return t->cache_.kIntegerOrMinusZeroOrNaN;
// Unary math functions.
+ case kMathExp:
+ return Type::Union(Type::PlainNumber(), Type::NaN(), t->zone());
case kMathAbs:
case kMathLog:
- case kMathExp:
case kMathSqrt:
case kMathCos:
case kMathSin:
@@ -1616,9 +1443,6 @@
case Runtime::kInlineDoubleLo:
case Runtime::kInlineDoubleHi:
return Type::Signed32();
- case Runtime::kInlineConstructDouble:
- case Runtime::kInlineMathAtan2:
- return Type::Number();
case Runtime::kInlineCreateIterResultObject:
case Runtime::kInlineRegExpConstructResult:
return Type::OtherObject();
@@ -1686,10 +1510,21 @@
return nullptr;
}
+Type* Typer::Visitor::TypeJSGeneratorStore(Node* node) {
+ UNREACHABLE();
+ return nullptr;
+}
+
+Type* Typer::Visitor::TypeJSGeneratorRestoreContinuation(Node* node) {
+ return typer_->cache_.kSmi;
+}
+
+Type* Typer::Visitor::TypeJSGeneratorRestoreRegister(Node* node) {
+ return Type::Any();
+}
Type* Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
-
// Simplified operators.
Type* Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
@@ -1706,10 +1541,42 @@
return Type::Boolean();
}
+Type* Typer::Visitor::TypeSpeculativeNumberEqual(Node* node) {
+ return Type::Boolean();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberLessThan(Node* node) {
+ return Type::Boolean();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
+ return Type::Boolean();
+}
+
Type* Typer::Visitor::TypeNumberAdd(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberSubtract(Node* node) { return Type::Number(); }
+Type* Typer::Visitor::TypeSpeculativeNumberAdd(Node* node) {
+ return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberSubtract(Node* node) {
+ return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberMultiply(Node* node) {
+ return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberDivide(Node* node) {
+ return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberModulus(Node* node) {
+ return Type::Number();
+}
+
Type* Typer::Visitor::TypeNumberMultiply(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberDivide(Node* node) { return Type::Number(); }
@@ -1745,8 +1612,24 @@
return Type::Unsigned32();
}
+Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
+ return TypeUnaryOp(node, ToNumber);
+}
+
+Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
+ return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
+ return Type::Number();
+}
+
Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); }
+Type* Typer::Visitor::TypeNumberAbs(Node* node) {
+ return TypeUnaryOp(node, NumberAbs);
+}
+
Type* Typer::Visitor::TypeNumberClz32(Node* node) {
return typer_->cache_.kZeroToThirtyTwo;
}
@@ -1759,10 +1642,43 @@
return TypeUnaryOp(node, NumberFloor);
}
+Type* Typer::Visitor::TypeNumberFround(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtan(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtan2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtanh(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberCos(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberExp(Node* node) {
+ return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
+}
+
+// TODO(mvstanton): Is this type sufficient, or should it look like Exp()?
+Type* Typer::Visitor::TypeNumberExpm1(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog1p(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog10(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberCbrt(Node* node) { return Type::Number(); }
+
Type* Typer::Visitor::TypeNumberRound(Node* node) {
return TypeUnaryOp(node, NumberRound);
}
+Type* Typer::Visitor::TypeNumberSin(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberSqrt(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberTan(Node* node) { return Type::Number(); }
+
Type* Typer::Visitor::TypeNumberTrunc(Node* node) {
return TypeUnaryOp(node, NumberTrunc);
}
@@ -1777,10 +1693,6 @@
}
-Type* Typer::Visitor::TypeNumberIsHoleNaN(Node* node) {
- return Type::Boolean();
-}
-
// static
Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
if (lhs->IsConstant() && rhs->Is(lhs)) {
@@ -1802,6 +1714,23 @@
return Type::Boolean();
}
+Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) {
+ type = NumberToUint32(ToNumber(type, t), t);
+ Factory* f = t->isolate()->factory();
+ double min = type->Min();
+ double max = type->Max();
+ if (min == max) {
+ uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU;
+ Handle<String> string = f->LookupSingleCharacterStringFromCode(code);
+ return Type::Constant(string, t->zone());
+ }
+ return Type::String();
+}
+
+Type* Typer::Visitor::TypeStringFromCharCode(Node* node) {
+ return TypeUnaryOp(node, StringFromCharCodeTyper);
+}
+
Type* Typer::Visitor::TypeStringToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
@@ -1817,33 +1746,45 @@
Type* Typer::Visitor::TypeChangeTaggedSignedToInt32(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Signed32()));
+ // TODO(jarin): DCHECK(arg->Is(Type::Signed32()));
+ // Many tests fail this check.
return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
}
Type* Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Signed32()));
+ DCHECK(arg->Is(Type::Signed32()));
return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
}
Type* Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Unsigned32()));
+ DCHECK(arg->Is(Type::Unsigned32()));
return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
}
Type* Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Number()));
+ DCHECK(arg->Is(Type::Number()));
+ return ChangeRepresentation(arg, Type::UntaggedFloat64(), zone());
+}
+
+Type* Typer::Visitor::TypeTruncateTaggedToFloat64(Node* node) {
+ Type* arg = Operand(node, 0);
+ // TODO(jarin) This DCHECK does not work because of speculative feedback.
+ // Re-enable once we record the speculative feedback in types.
+ // DCHECK(arg->Is(Type::NumberOrOddball()));
return ChangeRepresentation(arg, Type::UntaggedFloat64(), zone());
}
Type* Typer::Visitor::TypeChangeInt31ToTaggedSigned(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Signed31()));
+ // TODO(jarin): DCHECK(arg->Is(Type::Signed31()));
+ // Some mjsunit/asm and mjsunit/wasm tests fail this check.
+ // For instance, asm/int32-umod fails with Signed32/UntaggedIntegral32 in
+ // simplified-lowering (after propagation).
Type* rep =
arg->Is(Type::SignedSmall()) ? Type::TaggedSigned() : Type::Tagged();
return ChangeRepresentation(arg, rep, zone());
@@ -1851,41 +1792,109 @@
Type* Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Signed32()));
+ // TODO(jarin): DCHECK(arg->Is(Type::Signed32()));
+ // Two tests fail this check: mjsunit/asm/sqlite3/sqlite-safe-heap and
+ // mjsunit/wasm/embenchen/lua_binarytrees. The first one fails with Any/Any in
+ // simplified-lowering (after propagation).
Type* rep =
arg->Is(Type::SignedSmall()) ? Type::TaggedSigned() : Type::Tagged();
return ChangeRepresentation(arg, rep, zone());
}
-
Type* Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Unsigned32()));
+ // TODO(jarin): DCHECK(arg->Is(Type::Unsigned32()));
+ // This fails in benchmarks/octane/mandreel (--turbo).
return ChangeRepresentation(arg, Type::Tagged(), zone());
}
-
Type* Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): CHECK(arg.upper->Is(Type::Number()));
+ // TODO(jarin): DCHECK(arg->Is(Type::Number()));
+ // Some (or all) mjsunit/wasm/embenchen/ tests fail this check when run with
+ // --turbo and --always-opt.
return ChangeRepresentation(arg, Type::Tagged(), zone());
}
Type* Typer::Visitor::TypeChangeTaggedToBit(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
+ DCHECK(arg->Is(Type::Boolean()));
return ChangeRepresentation(arg, Type::UntaggedBit(), zone());
}
Type* Typer::Visitor::TypeChangeBitToTagged(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
return ChangeRepresentation(arg, Type::TaggedPointer(), zone());
}
+Type* Typer::Visitor::TypeCheckBounds(Node* node) {
+ // TODO(bmeurer): We could do better here based on the limit.
+ return Type::Unsigned31();
+}
+
+Type* Typer::Visitor::TypeCheckTaggedPointer(Node* node) {
+ Type* arg = Operand(node, 0);
+ return Type::Intersect(arg, Type::TaggedPointer(), zone());
+}
+
+Type* Typer::Visitor::TypeCheckTaggedSigned(Node* node) {
+ Type* arg = Operand(node, 0);
+ return Type::Intersect(arg, typer_->cache_.kSmi, zone());
+}
+
+Type* Typer::Visitor::TypeCheckedInt32Add(Node* node) {
+ return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypeCheckedInt32Sub(Node* node) {
+ return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypeCheckedUint32ToInt32(Node* node) {
+ return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedFloat64ToInt32(Node* node) {
+ return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedTaggedToInt32(Node* node) {
+ return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedTaggedToFloat64(Node* node) {
+ return Type::Number();
+}
+
+Type* Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
+ Type* type = Operand(node, 0);
+ return type;
+}
+
+Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) {
+ CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
+ Type* type = Operand(node, 0);
+ type = Type::Intersect(type, Type::NonInternal(), zone());
+ switch (mode) {
+ case CheckTaggedHoleMode::kConvertHoleToUndefined: {
+ // The hole is turned into undefined.
+ type = Type::Union(type, Type::Undefined(), zone());
+ break;
+ }
+ case CheckTaggedHoleMode::kNeverReturnHole: {
+ // We deoptimize in case of the hole.
+ break;
+ }
+ }
+ return type;
+}
+
Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
Type* arg = Operand(node, 0);
- // TODO(neis): DCHECK(arg->Is(Type::Number()));
+ // TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined()));
+ // Several mjsunit and cctest tests fail this check. For instance,
+ // mjsunit/compiler/regress-607493 fails with Any/Any in simplified-lowering
+ // (after propagation).
return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
}
@@ -2008,6 +2017,10 @@
// Machine operators.
+Type* Typer::Visitor::TypeDebugBreak(Node* node) { return Type::None(); }
+
+Type* Typer::Visitor::TypeComment(Node* node) { return Type::None(); }
+
Type* Typer::Visitor::TypeLoad(Node* node) { return Type::Any(); }
Type* Typer::Visitor::TypeStackSlot(Node* node) { return Type::Any(); }
@@ -2210,6 +2223,9 @@
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
}
+Type* Typer::Visitor::TypeNumberSilenceNaN(Node* node) {
+ return Type::Number();
+}
Type* Typer::Visitor::TypeChangeFloat64ToUint32(Node* node) {
return Type::Intersect(Type::Unsigned32(), Type::UntaggedIntegral32(),
@@ -2256,6 +2272,9 @@
return Type::Intersect(Type::Signed32(), Type::UntaggedFloat64(), zone());
}
+Type* Typer::Visitor::TypeFloat64SilenceNaN(Node* node) {
+ return Type::UntaggedFloat64();
+}
Type* Typer::Visitor::TypeChangeInt32ToInt64(Node* node) {
return Type::Internal();
@@ -2349,6 +2368,8 @@
return Type::Number();
}
+Type* Typer::Visitor::TypeFloat32Neg(Node* node) { return Type::Number(); }
+
Type* Typer::Visitor::TypeFloat32Mul(Node* node) { return Type::Number(); }
@@ -2392,6 +2413,8 @@
return Type::Number();
}
+Type* Typer::Visitor::TypeFloat64Neg(Node* node) { return Type::Number(); }
+
Type* Typer::Visitor::TypeFloat64Mul(Node* node) { return Type::Number(); }
@@ -2412,9 +2435,33 @@
return Type::Number();
}
+Type* Typer::Visitor::TypeFloat64Atan(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Atan2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Atanh(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Cos(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Exp(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Expm1(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log1p(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log10(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Cbrt(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Sin(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sqrt(Node* node) { return Type::Number(); }
+Type* Typer::Visitor::TypeFloat64Tan(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Equal(Node* node) { return Type::Boolean(); }
@@ -2547,6 +2594,7 @@
#define SIMD_RETURN_SIMD(Name) \
Type* Typer::Visitor::Type##Name(Node* node) { return Type::Simd(); }
MACHINE_SIMD_RETURN_SIMD_OP_LIST(SIMD_RETURN_SIMD)
+MACHINE_SIMD_GENERIC_OP_LIST(SIMD_RETURN_SIMD)
#undef SIMD_RETURN_SIMD
#define SIMD_RETURN_NUM(Name) \