Commit a0ac88db authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Fix various bugs in the type systems, and improve test coverage.

R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/230463003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20609 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a0355e37
......@@ -306,10 +306,14 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
template<class Config>
bool TypeImpl<Config>::NowIs(TypeImpl* that) {
return this->Is(that) ||
(this->IsConstant() && that->IsClass() &&
this->AsConstant()->IsHeapObject() &&
i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass());
if (this->Is(that)) return true;
if (this->IsConstant() && this->AsConstant()->IsHeapObject()) {
i::Handle<i::Map> map(i::HeapObject::cast(*this->AsConstant())->map());
for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
if (*it.Current() == *map) return true;
}
}
return false;
}
......@@ -358,8 +362,8 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) {
template<class Config>
bool TypeImpl<Config>::Contains(i::Object* value) {
if (this->IsConstant()) {
return *this->AsConstant() == value;
for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
if (*it.Current() == value) return true;
}
return Config::from_bitset(LubBitset(value))->Is(this);
}
......
......@@ -154,7 +154,7 @@ namespace internal {
V(Receiver, kObject | kProxy) \
V(NonNumber, kBoolean | kName | kNull | kReceiver | \
kUndefined | kInternal) \
V(Any, kNumber | kNonNumber)
V(Any, -1)
#define BITSET_TYPE_LIST(V) \
MASK_BITSET_TYPE_LIST(V) \
......@@ -220,6 +220,10 @@ class TypeImpl : public Config::Base {
return Of(*value, region);
}
bool IsInhabited() {
return !this->IsBitset() || IsInhabited(this->AsBitset());
}
bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
template<class TypeHandle>
bool Is(TypeHandle that) { return this->Is(*that); }
......
......@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <list>
#include "cctest.h"
#include "types.h"
......@@ -71,6 +73,43 @@ class Types {
ObjectConstant2 = Type::Constant(object2, region);
ArrayConstant1 = Type::Constant(array, region);
ArrayConstant2 = Type::Constant(array, region);
types.push_back(None);
types.push_back(Any);
types.push_back(Boolean);
types.push_back(Null);
types.push_back(Undefined);
types.push_back(Number);
types.push_back(SignedSmall);
types.push_back(Signed32);
types.push_back(Float);
types.push_back(Name);
types.push_back(UniqueName);
types.push_back(String);
types.push_back(InternalizedString);
types.push_back(Symbol);
types.push_back(Receiver);
types.push_back(Object);
types.push_back(Array);
types.push_back(Function);
types.push_back(Proxy);
types.push_back(ObjectClass);
types.push_back(ArrayClass);
types.push_back(SmiConstant);
types.push_back(Signed32Constant);
types.push_back(ObjectConstant1);
types.push_back(ObjectConstant2);
types.push_back(ArrayConstant1);
types.push_back(ArrayConstant2);
for (int i = 0; i < 300; ++i) {
types.push_back(Fuzz());
}
objects.push_back(smi);
objects.push_back(signed32);
objects.push_back(object1);
objects.push_back(object2);
objects.push_back(array);
}
TypeHandle Representation;
......@@ -114,6 +153,20 @@ class Types {
Handle<i::JSObject> object2;
Handle<i::JSArray> array;
typedef std::list<TypeHandle> TypeList;
TypeList types;
typedef std::list<Handle<i::Object> > ObjectList;
ObjectList objects;
TypeHandle Of(Handle<i::Object> obj) {
return Type::Of(obj, region_);
}
TypeHandle Constant(Handle<i::Object> obj) {
return Type::Constant(obj, region_);
}
TypeHandle Union(TypeHandle t1, TypeHandle t2) {
return Type::Union(t1, t2, region_);
}
......@@ -239,6 +292,10 @@ struct Tests : Rep {
HandleScope scope;
Zone zone;
Types<Type, TypeHandle, Region> T;
typedef typename Types<Type, TypeHandle, Region>::TypeList::iterator
TypeIterator;
typedef typename Types<Type, TypeHandle, Region>::ObjectList::iterator
ObjectIterator;
Tests() :
isolate(CcTest::i_isolate()),
......@@ -346,14 +403,49 @@ struct Tests : Rep {
}
void Is() {
// T->Is(None) implies T = None for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
if (type->Is(T.None)) CheckEqual(type, T.None);
}
// None->Is(T) for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(T.None->Is(type));
}
// Any->Is(T) implies T = Any for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
if (T.Any->Is(type)) CheckEqual(type, T.Any);
}
// T->Is(Any) for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(type->Is(T.Any));
}
// Reflexivity
CHECK(T.None->Is(T.None));
CHECK(T.Any->Is(T.Any));
CHECK(T.Object->Is(T.Object));
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(type->Is(type));
}
CHECK(T.ObjectClass->Is(T.ObjectClass));
CHECK(T.ObjectConstant1->Is(T.ObjectConstant1));
CHECK(T.ArrayConstant1->Is(T.ArrayConstant2));
// Transitivity
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle type3 = *it3;
CHECK(!type1->Is(type2) ||
!type2->Is(type3) ||
type1->Is(type3));
}
}
}
// Symmetry and Transitivity
CheckSub(T.None, T.Number);
......@@ -420,7 +512,111 @@ struct Tests : Rep {
CheckUnordered(T.ArrayConstant1, T.ObjectClass);
}
void NowIs() {
// T->NowIs(None) implies T = None for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
if (type->NowIs(T.None)) CheckEqual(type, T.None);
}
// None->NowIs(T) for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(T.None->NowIs(type));
}
// Any->NowIs(T) implies T = Any for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
if (T.Any->NowIs(type)) CheckEqual(type, T.Any);
}
// T->NowIs(Any) for all T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(type->NowIs(T.Any));
}
// Reflexivity
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(type->NowIs(type));
}
// Transitivity
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle type3 = *it3;
CHECK(!type1->NowIs(type2) ||
!type2->NowIs(type3) ||
type1->NowIs(type3));
}
}
}
// T1->Is(T2) implies T1->NowIs(T2) for all T1,T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
CHECK(!type1->Is(type2) || type1->NowIs(type2));
}
}
CHECK(T.ObjectConstant1->NowIs(T.ObjectClass));
CHECK(T.ObjectConstant2->NowIs(T.ObjectClass));
}
void Contains() {
// T->Contains(O) iff Constant(O)->Is(T) for all T,O
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ObjectIterator ot = T.objects.begin(); ot != T.objects.end(); ++ot) {
TypeHandle type = *it;
Handle<i::Object> obj = *ot;
CHECK(type->Contains(obj) == T.Constant(obj)->Is(type));
}
}
// Of(O)->Is(T) implies T->Contains(O) for all T,O
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ObjectIterator ot = T.objects.begin(); ot != T.objects.end(); ++ot) {
TypeHandle type = *it;
Handle<i::Object> obj = *ot;
CHECK(!T.Of(obj)->Is(type) || type->Contains(obj));
}
}
}
void Maybe() {
// T->Maybe(T) for all inhabited T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(type->Maybe(type) || !type->IsInhabited());
}
// Commutativity
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
CHECK(type1->Maybe(type2) == type2->Maybe(type1));
}
}
// T1->Is(T2) implies T1->Maybe(T2) or T1 is uninhabited for all T1,T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
CHECK(!type1->Is(type2) ||
type1->Maybe(type2) ||
!type1->IsInhabited());
}
}
CheckOverlap(T.Any, T.Any, T.Semantic);
CheckOverlap(T.Object, T.Object, T.Semantic);
......@@ -868,6 +1064,20 @@ TEST(Is) {
}
TEST(NowIs) {
CcTest::InitializeVM();
ZoneTests().NowIs();
HeapTests().NowIs();
}
TEST(Contains) {
CcTest::InitializeVM();
ZoneTests().Contains();
HeapTests().Contains();
}
TEST(Maybe) {
CcTest::InitializeVM();
ZoneTests().Maybe();
......
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