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