Extend some operations to range types.
This is a reland of 22945, which failed to build on Windows due to (some versions of?) Visual Studio lacking copysign(). R=rossberg@chromium.org BUG= Review URL: https://codereview.chromium.org/448093002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22977 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f263478eed
commit
c972e8e213
54
src/types.cc
54
src/types.cc
@ -10,6 +10,21 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Range-related custom order on doubles.
|
||||
// We want -0 to be less than +0.
|
||||
|
||||
static bool dle(double x, double y) {
|
||||
return x <= y && (x != 0 || IsMinusZero(x) || !IsMinusZero(y));
|
||||
}
|
||||
|
||||
|
||||
static bool deq(double x, double y) {
|
||||
return dle(x, y) && dle(y, x);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Glb and lub computation.
|
||||
|
||||
@ -48,6 +63,8 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
||||
type->AsClass()->Bound(NULL)->AsBitset();
|
||||
} else if (type->IsConstant()) {
|
||||
return type->AsConstant()->Bound()->AsBitset();
|
||||
} else if (type->IsRange()) {
|
||||
return type->AsRange()->Bound()->AsBitset();
|
||||
} else if (type->IsContext()) {
|
||||
return type->AsContext()->Bound()->AsBitset();
|
||||
} else if (type->IsArray()) {
|
||||
@ -78,6 +95,8 @@ int TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) {
|
||||
return Lub(*type->AsClass()->Map());
|
||||
} else if (type->IsConstant()) {
|
||||
return Lub(*type->AsConstant()->Value());
|
||||
} else if (type->IsRange()) {
|
||||
return Lub(type->AsRange()->Min(), type->AsRange()->Max());
|
||||
} else if (type->IsContext()) {
|
||||
return kInternal & kTaggedPtr;
|
||||
} else if (type->IsArray()) {
|
||||
@ -112,6 +131,18 @@ int TypeImpl<Config>::BitsetType::Lub(double value) {
|
||||
}
|
||||
|
||||
|
||||
template<class Config>
|
||||
int TypeImpl<Config>::BitsetType::Lub(double min, double max) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
DCHECK(dle(min, max));
|
||||
if (deq(min, max)) return BitsetType::Lub(min); // Singleton range.
|
||||
int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN);
|
||||
if (dle(0, min) || max < 0) bitset ^= SEMANTIC(BitsetType::kMinusZero);
|
||||
return bitset;
|
||||
// TODO(neis): Could refine this further by doing more checks on min/max.
|
||||
}
|
||||
|
||||
|
||||
template<class Config>
|
||||
int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
|
||||
if (value >= 0x40000000) {
|
||||
@ -256,6 +287,12 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
|
||||
&& *this->AsConstant()->Value() == *that->AsConstant()->Value()
|
||||
&& this->AsConstant()->Bound()->Is(that->AsConstant()->Bound());
|
||||
}
|
||||
if (that->IsRange()) {
|
||||
return this->IsRange()
|
||||
&& this->AsRange()->Bound()->Is(that->AsRange()->Bound())
|
||||
&& dle(that->AsRange()->Min(), this->AsRange()->Min())
|
||||
&& dle(this->AsRange()->Max(), that->AsRange()->Max());
|
||||
}
|
||||
if (that->IsContext()) {
|
||||
return this->IsContext()
|
||||
&& this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
|
||||
@ -388,6 +425,12 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) {
|
||||
template<class Config>
|
||||
bool TypeImpl<Config>::Contains(i::Object* value) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (this->IsRange()) {
|
||||
return value->IsNumber() &&
|
||||
dle(this->AsRange()->Min(), value->Number()) &&
|
||||
dle(value->Number(), this->AsRange()->Max()) &&
|
||||
BitsetType::Is(BitsetType::Lub(value), this->BitsetLub());
|
||||
}
|
||||
for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
|
||||
if (*it.Current() == value) return true;
|
||||
}
|
||||
@ -420,6 +463,9 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound(
|
||||
return ClassType::New(this->AsClass()->Map(), bound, region);
|
||||
} else if (this->IsConstant()) {
|
||||
return ConstantType::New(this->AsConstant()->Value(), bound, region);
|
||||
} else if (this->IsRange()) {
|
||||
return RangeType::New(
|
||||
this->AsRange()->Min(), this->AsRange()->Max(), bound, region);
|
||||
} else if (this->IsContext()) {
|
||||
return ContextType::New(this->AsContext()->Outer(), bound, region);
|
||||
} else if (this->IsArray()) {
|
||||
@ -508,8 +554,8 @@ int TypeImpl<Config>::ExtendUnion(
|
||||
}
|
||||
}
|
||||
} else if (!type->IsBitset()) {
|
||||
DCHECK(type->IsClass() || type->IsConstant() ||
|
||||
type->IsArray() || type->IsFunction() || type->IsContext());
|
||||
DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() ||
|
||||
type->IsContext() || type->IsArray() || type->IsFunction());
|
||||
int inherent_bound = type->InherentBitsetLub();
|
||||
int old_bound = type->BitsetLub();
|
||||
int other_bound = type->BoundBy(other->unhandle()) & inherent_bound;
|
||||
@ -752,6 +798,10 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
|
||||
} else if (type->IsConstant()) {
|
||||
TypeHandle bound = Convert<OtherType>(type->AsConstant()->Bound(), region);
|
||||
return ConstantType::New(type->AsConstant()->Value(), bound, region);
|
||||
} else if (type->IsRange()) {
|
||||
TypeHandle bound = Convert<OtherType>(type->AsRange()->Bound(), region);
|
||||
return RangeType::New(
|
||||
type->AsRange()->Min(), type->AsRange()->Max(), bound, region);
|
||||
} else if (type->IsContext()) {
|
||||
TypeHandle bound = Convert<OtherType>(type->AsContext()->Bound(), region);
|
||||
TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region);
|
||||
|
@ -286,7 +286,7 @@ class TypeImpl : public Config::Base {
|
||||
return ClassType::New(map, region);
|
||||
}
|
||||
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
|
||||
// TODO(neis): return RangeType for numerical values
|
||||
// TODO(neis): Return RangeType for numerical values.
|
||||
return ConstantType::New(value, region);
|
||||
}
|
||||
static TypeHandle Range(double min, double max, Region* region) {
|
||||
@ -518,6 +518,7 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
|
||||
static int Lub(int32_t value);
|
||||
static int Lub(uint32_t value);
|
||||
static int Lub(i::Map* map);
|
||||
static int Lub(double min, double max);
|
||||
static int InherentLub(TypeImpl* type);
|
||||
|
||||
static const char* Name(int bitset);
|
||||
@ -690,8 +691,7 @@ class TypeImpl<Config>::RangeType : public StructuralType {
|
||||
|
||||
static RangeHandle New(
|
||||
double min, double max, TypeHandle bound, Region* region) {
|
||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kNumber));
|
||||
DCHECK(!std::isnan(min) && !std::isnan(max) && min <= max);
|
||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max)));
|
||||
RangeHandle type = Config::template cast<RangeType>(
|
||||
StructuralType::New(StructuralType::kRangeTag, 3, region));
|
||||
type->Set(0, bound);
|
||||
@ -704,7 +704,7 @@ class TypeImpl<Config>::RangeType : public StructuralType {
|
||||
}
|
||||
|
||||
static RangeHandle New(double min, double max, Region* region) {
|
||||
TypeHandle bound = BitsetType::New(BitsetType::kNumber, region);
|
||||
TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region);
|
||||
return New(min, max, bound, region);
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ class Types {
|
||||
NumberFunction2 = Type::Function(Number, Number, Number, region);
|
||||
MethodFunction = Type::Function(String, Object, 0, region);
|
||||
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
types.push_back(Fuzz());
|
||||
}
|
||||
}
|
||||
@ -189,6 +189,21 @@ class Types {
|
||||
ValueVector values;
|
||||
DoubleVector doubles; // Some floating-point values, excluding NaN.
|
||||
|
||||
// Range type helper functions, partially copied from types.cc.
|
||||
// Note: dle(dmin(x,y), dmax(x,y)) holds iff neither x nor y is NaN.
|
||||
bool dle(double x, double y) {
|
||||
return x <= y && (x != 0 || IsMinusZero(x) || !IsMinusZero(y));
|
||||
}
|
||||
bool deq(double x, double y) {
|
||||
return dle(x, y) && dle(y, x);
|
||||
}
|
||||
double dmin(double x, double y) {
|
||||
return dle(x, y) ? x : y;
|
||||
}
|
||||
double dmax(double x, double y) {
|
||||
return dle(x, y) ? y : x;
|
||||
}
|
||||
|
||||
TypeHandle Of(Handle<i::Object> value) {
|
||||
return Type::Of(value, region_);
|
||||
}
|
||||
@ -549,8 +564,8 @@ struct Tests : Rep {
|
||||
// Constructor
|
||||
for (DoubleIterator i = T.doubles.begin(); i != T.doubles.end(); ++i) {
|
||||
for (DoubleIterator j = T.doubles.begin(); j != T.doubles.end(); ++j) {
|
||||
double min = std::min(*i, *j);
|
||||
double max = std::max(*i, *j);
|
||||
double min = T.dmin(*i, *j);
|
||||
double max = T.dmax(*i, *j);
|
||||
TypeHandle type = T.Range(min, max);
|
||||
CHECK(type->IsRange());
|
||||
}
|
||||
@ -559,8 +574,8 @@ struct Tests : Rep {
|
||||
// Range attributes
|
||||
for (DoubleIterator i = T.doubles.begin(); i != T.doubles.end(); ++i) {
|
||||
for (DoubleIterator j = T.doubles.begin(); j != T.doubles.end(); ++j) {
|
||||
double min = std::min(*i, *j);
|
||||
double max = std::max(*i, *j);
|
||||
double min = T.dmin(*i, *j);
|
||||
double max = T.dmax(*i, *j);
|
||||
printf("RangeType: min, max = %f, %f\n", min, max);
|
||||
TypeHandle type = T.Range(min, max);
|
||||
printf("RangeType: Min, Max = %f, %f\n",
|
||||
@ -579,13 +594,14 @@ struct Tests : Rep {
|
||||
// i2 != T.doubles.end(); ++i2) {
|
||||
// for (DoubleIterator j2 = T.doubles.begin();
|
||||
// j2 != T.doubles.end(); ++j2) {
|
||||
// double min1 = std::min(*i1, *j1);
|
||||
// double max1 = std::max(*i1, *j1);
|
||||
// double min2 = std::min(*i2, *j2);
|
||||
// double max2 = std::max(*i2, *j2);
|
||||
// double min1 = T.dmin(*i1, *j1);
|
||||
// double max1 = T.dmax(*i1, *j1);
|
||||
// double min2 = T.dmin(*i2, *j2);
|
||||
// double max2 = T.dmax(*i2, *j2);
|
||||
// TypeHandle type1 = T.Range(min1, max1);
|
||||
// TypeHandle type2 = T.Range(min2, max2);
|
||||
// CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2));
|
||||
// CHECK(Equal(type1, type2) ==
|
||||
// (T.deq(min1, min2) && T.deq(max1, max2)));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user