Commit 69f897d5 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[compiler] Further clean up Type::Min/Max and their usage.

They can no longer return nan. They basically intersect their argument
type with Type::OrderedNumber before analysing it. Never call them on
Type::NaN.

Bug: 
Change-Id: I7e7b46aa9fcde4f2644b81b3a34e76b092f633a4
Reviewed-on: https://chromium-review.googlesource.com/763410
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49375}
parent ca0270d9
......@@ -492,7 +492,7 @@ Maybe<int> OffsetOfElementsAccess(const Operator* op, Node* index_node) {
DCHECK(op->opcode() == IrOpcode::kLoadElement ||
op->opcode() == IrOpcode::kStoreElement);
Type* index_type = NodeProperties::GetType(index_node);
if (!index_type->Is(Type::Number())) return Nothing<int>();
if (!index_type->Is(Type::OrderedNumber())) return Nothing<int>();
double max = index_type->Max();
double min = index_type->Min();
int index = static_cast<int>(min);
......
......@@ -116,15 +116,7 @@ Type* OperationTyper::Rangify(Type* type) {
if (!type->Is(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, zone());
return Type::Range(type->Min(), type->Max(), zone());
}
namespace {
......
......@@ -209,7 +209,7 @@ class InputUseInfos {
bool CanOverflowSigned32(const Operator* op, Type* left, Type* right,
Zone* type_zone) {
// We assume the inputs are checked Signed32 (or known statically
// to be Signed32). Technically, theinputs could also be minus zero, but
// to be Signed32). Technically, the inputs could also be minus zero, but
// that cannot cause overflow.
left = Type::Intersect(left, Type::Signed32(), type_zone);
right = Type::Intersect(right, Type::Signed32(), type_zone);
......@@ -229,6 +229,10 @@ bool CanOverflowSigned32(const Operator* op, Type* left, Type* right,
return true;
}
bool IsSomePositiveOrderedNumber(Type* type) {
return type->Is(Type::OrderedNumber()) && !type->IsNone() && type->Min() > 0;
}
} // namespace
class RepresentationSelector {
......@@ -1249,10 +1253,8 @@ class RepresentationSelector {
// there is no need to return -0.
CheckForMinusZeroMode mz_mode =
truncation.IdentifiesZeroAndMinusZero() ||
(input0_type->Is(Type::OrderedNumber()) &&
input0_type->Min() > 0) ||
(input1_type->Is(Type::OrderedNumber()) &&
input1_type->Min() > 0)
IsSomePositiveOrderedNumber(input0_type) ||
IsSomePositiveOrderedNumber(input1_type)
? CheckForMinusZeroMode::kDontCheckForMinusZero
: CheckForMinusZeroMode::kCheckForMinusZero;
......
......@@ -461,8 +461,8 @@ Type* Typer::Visitor::ToInteger(Type* type, Typer* t) {
// static
Type* Typer::Visitor::ToLength(Type* type, Typer* t) {
// ES6 section 7.1.15 ToLength ( argument )
type = ToInteger(type, t);
if (type->IsNone()) return type;
type = ToInteger(type, t);
double min = type->Min();
double max = type->Max();
if (max <= 0.0) {
......@@ -1855,6 +1855,7 @@ Type* Typer::Visitor::TypeStringIndexOf(Node* node) { UNREACHABLE(); }
Type* Typer::Visitor::TypeCheckBounds(Node* node) {
Type* index = Operand(node, 0);
Type* length = Operand(node, 1);
DCHECK(length->Is(Type::Unsigned31()));
if (index->Maybe(Type::MinusZero())) {
index = Type::Union(index, typer_->cache_.kSingletonZero, zone());
}
......
......@@ -68,7 +68,7 @@ bool Type::Contains(RangeType* range, i::Object* val) {
double Type::Min() {
DCHECK(this->Is(Number()));
DCHECK(!this->IsNone());
DCHECK(!this->Is(NaN()));
if (this->IsBitset()) return BitsetType::Min(this->AsBitset());
if (this->IsUnion()) {
double min = +V8_INFINITY;
......@@ -76,18 +76,17 @@ double Type::Min() {
min = std::min(min, this->AsUnion()->Get(i)->Min());
}
Type* bitset = this->AsUnion()->Get(0);
if (!bitset->IsNone()) min = std::min(min, bitset->Min());
if (!bitset->Is(NaN())) min = std::min(min, bitset->Min());
return min;
}
if (this->IsRange()) return this->AsRange()->Min();
if (this->IsOtherNumberConstant())
return this->AsOtherNumberConstant()->Value();
UNREACHABLE();
DCHECK(this->IsOtherNumberConstant());
return this->AsOtherNumberConstant()->Value();
}
double Type::Max() {
DCHECK(this->Is(Number()));
DCHECK(!this->IsNone());
DCHECK(!this->Is(NaN()));
if (this->IsBitset()) return BitsetType::Max(this->AsBitset());
if (this->IsUnion()) {
double max = -V8_INFINITY;
......@@ -95,13 +94,12 @@ double Type::Max() {
max = std::max(max, this->AsUnion()->Get(i)->Max());
}
Type* bitset = this->AsUnion()->Get(0);
if (!bitset->IsNone()) max = std::max(max, bitset->Max());
if (!bitset->Is(NaN())) max = std::max(max, bitset->Max());
return max;
}
if (this->IsRange()) return this->AsRange()->Max();
if (this->IsOtherNumberConstant())
return this->AsOtherNumberConstant()->Value();
UNREACHABLE();
DCHECK(this->IsOtherNumberConstant());
return this->AsOtherNumberConstant()->Value();
}
// -----------------------------------------------------------------------------
......@@ -401,6 +399,7 @@ Type::bitset BitsetType::Glb(double min, double max) {
double BitsetType::Min(bitset bits) {
DisallowHeapAllocation no_allocation;
DCHECK(Is(bits, kNumber));
DCHECK(!Is(bits, kNaN));
const Boundary* mins = Boundaries();
bool mz = bits & kMinusZero;
for (size_t i = 0; i < BoundariesSize(); ++i) {
......@@ -408,13 +407,14 @@ double BitsetType::Min(bitset bits) {
return mz ? std::min(0.0, mins[i].min) : mins[i].min;
}
}
if (mz) return 0;
return std::numeric_limits<double>::quiet_NaN();
DCHECK(mz);
return 0;
}
double BitsetType::Max(bitset bits) {
DisallowHeapAllocation no_allocation;
DCHECK(Is(bits, kNumber));
DCHECK(!Is(bits, kNaN));
const Boundary* mins = Boundaries();
bool mz = bits & kMinusZero;
if (BitsetType::Is(mins[BoundariesSize() - 1].internal, bits)) {
......@@ -425,8 +425,8 @@ double BitsetType::Max(bitset bits) {
return mz ? std::max(0.0, mins[i + 1].min - 1) : mins[i + 1].min - 1;
}
}
if (mz) return 0;
return std::numeric_limits<double>::quiet_NaN();
DCHECK(mz);
return 0;
}
// static
......
......@@ -605,9 +605,9 @@ class V8_EXPORT_PRIVATE Type {
TupleType* AsTuple() { return TupleType::cast(this); }
// Minimum and maximum of a numeric type.
// These functions do not distinguish between -0 and +0. If the type equals
// kNaN, they return NaN; otherwise kNaN is ignored. Only call these
// functions on subtypes of Number, but not on None!
// These functions do not distinguish between -0 and +0. NaN is ignored.
// Only call them on subtypes of Number whose intersection with OrderedNumber
// is not empty.
double Min();
double Max();
......
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