From: neis@chromium.org Date: Tue, 22 Jul 2014 17:33:22 +0000 (+0000) Subject: Add constructor for range types. X-Git-Tag: upstream/4.7.83~8108 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6176dee6ea5ddffcc59aa581bcda4d617b75790a;p=platform%2Fupstream%2Fv8.git Add constructor for range types. R=rossberg@chromium.org BUG= Review URL: https://codereview.chromium.org/409543004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22535 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/types-inl.h b/src/types-inl.h index 0bdd4638f..f086e8b84 100644 --- a/src/types-inl.h +++ b/src/types-inl.h @@ -19,7 +19,7 @@ namespace internal { template TypeImpl* TypeImpl::cast(typename Config::Base* object) { TypeImpl* t = static_cast(object); - ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || + ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsRange() || t->IsUnion() || t->IsArray() || t->IsFunction() || t->IsContext()); return t; } diff --git a/src/types.cc b/src/types.cc index 3cd349b89..db638ed14 100644 --- a/src/types.cc +++ b/src/types.cc @@ -911,6 +911,11 @@ void TypeImpl::PrintTo(OStream& os, PrintDimension dim) { // NOLINT << " : "; BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim); os << ")"; + } else if (this->IsRange()) { + os << "Range(" << this->AsRange()->Min() + << ".." << this->AsRange()->Max() << " : "; + BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim); + os << ")"; } else if (this->IsContext()) { os << "Context("; this->AsContext()->Outer()->PrintTo(os, dim); diff --git a/src/types.h b/src/types.h index 79a29e071..1b2cf66c9 100644 --- a/src/types.h +++ b/src/types.h @@ -5,6 +5,7 @@ #ifndef V8_TYPES_H_ #define V8_TYPES_H_ +#include "src/factory.h" #include "src/handles.h" #include "src/ostreams.h" @@ -254,6 +255,7 @@ class TypeImpl : public Config::Base { class ClassType; class ConstantType; + class RangeType; class ContextType; class ArrayType; class FunctionType; @@ -261,6 +263,7 @@ class TypeImpl : public Config::Base { typedef typename Config::template Handle::type TypeHandle; typedef typename Config::template Handle::type ClassHandle; typedef typename Config::template Handle::type ConstantHandle; + typedef typename Config::template Handle::type RangeHandle; typedef typename Config::template Handle::type ContextHandle; typedef typename Config::template Handle::type ArrayHandle; typedef typename Config::template Handle::type FunctionHandle; @@ -281,8 +284,12 @@ class TypeImpl : public Config::Base { return ClassType::New(map, region); } static TypeHandle Constant(i::Handle value, Region* region) { + // TODO(neis): return RangeType for numerical values return ConstantType::New(value, region); } + static TypeHandle Range(double min, double max, Region* region) { + return RangeType::New(min, max, region); + } static TypeHandle Context(TypeHandle outer, Region* region) { return ContextType::New(outer, region); } @@ -375,6 +382,9 @@ class TypeImpl : public Config::Base { bool IsConstant() { return Config::is_struct(this, StructuralType::kConstantTag); } + bool IsRange() { + return Config::is_struct(this, StructuralType::kRangeTag); + } bool IsContext() { return Config::is_struct(this, StructuralType::kContextTag); } @@ -387,6 +397,7 @@ class TypeImpl : public Config::Base { ClassType* AsClass() { return ClassType::cast(this); } ConstantType* AsConstant() { return ConstantType::cast(this); } + RangeType* AsRange() { return RangeType::cast(this); } ContextType* AsContext() { return ContextType::cast(this); } ArrayType* AsArray() { return ArrayType::cast(this); } FunctionType* AsFunction() { return FunctionType::cast(this); } @@ -520,6 +531,7 @@ class TypeImpl::StructuralType : public TypeImpl { enum Tag { kClassTag, kConstantTag, + kRangeTag, kContextTag, kArrayTag, kFunctionTag, @@ -655,6 +667,42 @@ class TypeImpl::ConstantType : public StructuralType { }; +// ----------------------------------------------------------------------------- +// Range types. + +template +class TypeImpl::RangeType : public StructuralType { + public: + TypeHandle Bound() { return this->Get(0); } + double Min() { return this->template GetValue(1)->value(); } + double Max() { return this->template GetValue(2)->value(); } + + static RangeHandle New( + double min, double max, TypeHandle bound, Region* region) { + ASSERT(SEMANTIC(bound->AsBitset() | BitsetType::kNumber) + == SEMANTIC(BitsetType::kNumber)); + ASSERT(!std::isnan(min) && !std::isnan(max) && min <= max); + RangeHandle type = Config::template cast( + StructuralType::New(StructuralType::kRangeTag, 3, region)); + type->Set(0, bound); + Factory* factory = Config::isolate(region)->factory(); + type->SetValue(1, factory->NewHeapNumber(min)); + type->SetValue(2, factory->NewHeapNumber(max)); + return type; + } + + static RangeHandle New(double min, double max, Region* region) { + TypeHandle bound = BitsetType::New(BitsetType::kNumber, region); + return New(min, max, bound, region); + } + + static RangeType* cast(TypeImpl* type) { + ASSERT(type->IsRange()); + return static_cast(type); + } +}; + + // ----------------------------------------------------------------------------- // Context types. @@ -791,6 +839,11 @@ struct ZoneTypeConfig { typedef i::Zone Region; template struct Handle { typedef T* type; }; + // TODO(neis): This will be removed again once we have struct_get_double(). + static inline i::Isolate* isolate(Region* region) { + return region->isolate(); + } + template static inline T* handle(T* type); template static inline T* cast(Type* type); @@ -833,6 +886,11 @@ struct HeapTypeConfig { typedef i::Isolate Region; template struct Handle { typedef i::Handle type; }; + // TODO(neis): This will be removed again once we have struct_get_double(). + static inline i::Isolate* isolate(Region* region) { + return region; + } + template static inline i::Handle handle(T* type); template static inline i::Handle cast(i::Handle type); diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc index 8120a6d94..5c6a0591e 100644 --- a/test/cctest/test-types.cc +++ b/test/cctest/test-types.cc @@ -21,10 +21,11 @@ struct ZoneRep { static bool IsBitset(Type* t) { return reinterpret_cast(t) & 1; } static bool IsClass(Type* t) { return IsStruct(t, 0); } static bool IsConstant(Type* t) { return IsStruct(t, 1); } - static bool IsContext(Type* t) { return IsStruct(t, 2); } - static bool IsArray(Type* t) { return IsStruct(t, 3); } - static bool IsFunction(Type* t) { return IsStruct(t, 4); } - static bool IsUnion(Type* t) { return IsStruct(t, 5); } + static bool IsRange(Type* t) { return IsStruct(t, 2); } + static bool IsContext(Type* t) { return IsStruct(t, 3); } + static bool IsArray(Type* t) { return IsStruct(t, 4); } + static bool IsFunction(Type* t) { return IsStruct(t, 5); } + static bool IsUnion(Type* t) { return IsStruct(t, 6); } static Struct* AsStruct(Type* t) { return reinterpret_cast(t); @@ -70,10 +71,11 @@ struct HeapRep { return t->IsMap() || IsStruct(t, 0); } static bool IsConstant(Handle t) { return IsStruct(t, 1); } - static bool IsContext(Handle t) { return IsStruct(t, 2); } - static bool IsArray(Handle t) { return IsStruct(t, 3); } - static bool IsFunction(Handle t) { return IsStruct(t, 4); } - static bool IsUnion(Handle t) { return IsStruct(t, 5); } + static bool IsRange(Handle t) { return IsStruct(t, 2); } + static bool IsContext(Handle t) { return IsStruct(t, 3); } + static bool IsArray(Handle t) { return IsStruct(t, 4); } + static bool IsFunction(Handle t) { return IsStruct(t, 5); } + static bool IsUnion(Handle t) { return IsStruct(t, 6); } static Struct* AsStruct(Handle t) { return FixedArray::cast(*t); } static int AsBitset(Handle t) { return Smi::cast(*t)->value(); } @@ -149,6 +151,15 @@ class Types { types.push_back(Type::Constant(*it, region)); } + doubles.push_back(-0.0); + doubles.push_back(+0.0); + doubles.push_back(-std::numeric_limits::infinity()); + doubles.push_back(+std::numeric_limits::infinity()); + for (int i = 0; i < 10; ++i) { + doubles.push_back(rng_->NextInt()); + doubles.push_back(rng_->NextDouble() * rng_->NextInt()); + } + NumberArray = Type::Array(Number, region); StringArray = Type::Array(String, region); AnyArray = Type::Array(Any, region); @@ -201,9 +212,12 @@ class Types { typedef std::vector TypeVector; typedef std::vector > MapVector; typedef std::vector > ValueVector; + typedef std::vector DoubleVector; + TypeVector types; MapVector maps; ValueVector values; + DoubleVector doubles; TypeHandle Of(Handle value) { return Type::Of(value, region_); @@ -217,6 +231,10 @@ class Types { return Type::Constant(value, region_); } + TypeHandle Range(double min, double max) { + return Type::Range(min, max, region_); + } + TypeHandle Class(Handle map) { return Type::Class(map, region_); } @@ -327,6 +345,7 @@ struct Tests : Rep { typedef typename TypesInstance::TypeVector::iterator TypeIterator; typedef typename TypesInstance::MapVector::iterator MapIterator; typedef typename TypesInstance::ValueVector::iterator ValueIterator; + typedef typename TypesInstance::DoubleVector::iterator DoubleIterator; Isolate* isolate; HandleScope scope; @@ -346,6 +365,7 @@ struct Tests : Rep { Rep::IsBitset(type1) == Rep::IsBitset(type2) && Rep::IsClass(type1) == Rep::IsClass(type2) && Rep::IsConstant(type1) == Rep::IsConstant(type2) && + Rep::IsRange(type1) == Rep::IsRange(type2) && Rep::IsContext(type1) == Rep::IsContext(type2) && Rep::IsArray(type1) == Rep::IsArray(type2) && Rep::IsFunction(type1) == Rep::IsFunction(type2) && @@ -358,8 +378,11 @@ struct Tests : Rep { Rep::AsClass(type1) == Rep::AsClass(type2)) && (!Rep::IsConstant(type1) || Rep::AsConstant(type1) == Rep::AsConstant(type2)) && + (!Rep::IsRange(type1) || + (type1->AsRange()->Min() == type2->AsRange()->Min() && + type1->AsRange()->Max() == type2->AsRange()->Max())) && // TODO(rossberg): Check details of arrays, functions, bounds. - (!Rep::IsUnion(type1) || + (!Rep::IsUnion(type1) || Rep::Length(Rep::AsUnion(type1)) == Rep::Length(Rep::AsUnion(type2))); } @@ -566,6 +589,50 @@ struct Tests : Rep { CHECK(T.Constant(fac->NewNumber(-V8_INFINITY))->Is(T.OtherNumber)); } + void Range() { + // 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); + TypeHandle type = T.Range(min, max); + CHECK(this->IsRange(type)); + } + } + + // 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); + TypeHandle type = T.Range(min, max); + CHECK(min == type->AsRange()->Min()); + CHECK(max == type->AsRange()->Max()); + } + } + +// TODO(neis): enable once subtyping is updated. +// // Functionality & Injectivity: Range(min1, max1) = Range(min2, max2) <=> +// // min1 = min2 /\ max1 = max2 +// for (DoubleIterator i1 = T.doubles.begin(); i1 != T.doubles.end(); ++i1) { +// for (DoubleIterator j1 = T.doubles.begin(); j1 != T.doubles.end(); ++j1) { +// for (DoubleIterator i2 = T.doubles.begin(); +// 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); +// TypeHandle type1 = T.Range(min1, max1); +// TypeHandle type2 = T.Range(min2, max2); +// CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2)); +// } +// } +// } +// } + } + void Array() { // Constructor for (int i = 0; i < 20; ++i) { @@ -1794,6 +1861,13 @@ TEST(ConstantType) { } +TEST(RangeType) { + CcTest::InitializeVM(); + ZoneTests().Range(); + HeapTests().Range(); +} + + TEST(ArrayType) { CcTest::InitializeVM(); ZoneTests().Array();