• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <vector>
29 
30 #include "src/hydrogen-types.h"
31 #include "src/types.h"
32 #include "src/utils/random-number-generator.h"
33 #include "test/cctest/cctest.h"
34 
35 using namespace v8::internal;
36 
37 // Testing auxiliaries (breaking the Type abstraction).
38 struct ZoneRep {
39   typedef void* Struct;
40 
IsStructZoneRep41   static bool IsStruct(Type* t, int tag) {
42     return !IsBitset(t) && reinterpret_cast<intptr_t>(AsStruct(t)[0]) == tag;
43   }
IsBitsetZoneRep44   static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
IsClassZoneRep45   static bool IsClass(Type* t) { return IsStruct(t, 0); }
IsConstantZoneRep46   static bool IsConstant(Type* t) { return IsStruct(t, 1); }
IsContextZoneRep47   static bool IsContext(Type* t) { return IsStruct(t, 2); }
IsArrayZoneRep48   static bool IsArray(Type* t) { return IsStruct(t, 3); }
IsFunctionZoneRep49   static bool IsFunction(Type* t) { return IsStruct(t, 4); }
IsUnionZoneRep50   static bool IsUnion(Type* t) { return IsStruct(t, 5); }
51 
AsStructZoneRep52   static Struct* AsStruct(Type* t) {
53     return reinterpret_cast<Struct*>(t);
54   }
AsBitsetZoneRep55   static int AsBitset(Type* t) {
56     return static_cast<int>(reinterpret_cast<intptr_t>(t) >> 1);
57   }
AsClassZoneRep58   static Map* AsClass(Type* t) {
59     return *static_cast<Map**>(AsStruct(t)[3]);
60   }
AsConstantZoneRep61   static Object* AsConstant(Type* t) {
62     return *static_cast<Object**>(AsStruct(t)[3]);
63   }
AsContextZoneRep64   static Type* AsContext(Type* t) {
65     return *static_cast<Type**>(AsStruct(t)[2]);
66   }
AsUnionZoneRep67   static Struct* AsUnion(Type* t) {
68     return AsStruct(t);
69   }
LengthZoneRep70   static int Length(Struct* structured) {
71     return static_cast<int>(reinterpret_cast<intptr_t>(structured[1]));
72   }
73 
ToRegionZoneRep74   static Zone* ToRegion(Zone* zone, Isolate* isolate) { return zone; }
75 
76   struct BitsetType : Type::BitsetType {
77     using Type::BitsetType::New;
78     using Type::BitsetType::Glb;
79     using Type::BitsetType::Lub;
80     using Type::BitsetType::InherentLub;
81   };
82 };
83 
84 
85 struct HeapRep {
86   typedef FixedArray Struct;
87 
IsStructHeapRep88   static bool IsStruct(Handle<HeapType> t, int tag) {
89     return t->IsFixedArray() && Smi::cast(AsStruct(t)->get(0))->value() == tag;
90   }
IsBitsetHeapRep91   static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
IsClassHeapRep92   static bool IsClass(Handle<HeapType> t) {
93     return t->IsMap() || IsStruct(t, 0);
94   }
IsConstantHeapRep95   static bool IsConstant(Handle<HeapType> t) { return IsStruct(t, 1); }
IsContextHeapRep96   static bool IsContext(Handle<HeapType> t) { return IsStruct(t, 2); }
IsArrayHeapRep97   static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 3); }
IsFunctionHeapRep98   static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 4); }
IsUnionHeapRep99   static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 5); }
100 
AsStructHeapRep101   static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
AsBitsetHeapRep102   static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
AsClassHeapRep103   static Map* AsClass(Handle<HeapType> t) {
104     return t->IsMap() ? Map::cast(*t) : Map::cast(AsStruct(t)->get(2));
105   }
AsConstantHeapRep106   static Object* AsConstant(Handle<HeapType> t) { return AsStruct(t)->get(2); }
AsContextHeapRep107   static HeapType* AsContext(Handle<HeapType> t) {
108     return HeapType::cast(AsStruct(t)->get(1));
109   }
AsUnionHeapRep110   static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
LengthHeapRep111   static int Length(Struct* structured) { return structured->length() - 1; }
112 
ToRegionHeapRep113   static Isolate* ToRegion(Zone* zone, Isolate* isolate) { return isolate; }
114 
115   struct BitsetType : HeapType::BitsetType {
116     using HeapType::BitsetType::New;
117     using HeapType::BitsetType::Glb;
118     using HeapType::BitsetType::Lub;
119     using HeapType::BitsetType::InherentLub;
GlbHeapRep::BitsetType120     static int Glb(Handle<HeapType> type) { return Glb(*type); }
LubHeapRep::BitsetType121     static int Lub(Handle<HeapType> type) { return Lub(*type); }
InherentLubHeapRep::BitsetType122     static int InherentLub(Handle<HeapType> type) { return InherentLub(*type); }
123   };
124 };
125 
126 
127 template<class Type, class TypeHandle, class Region>
128 class Types {
129  public:
Types(Region * region,Isolate * isolate)130   Types(Region* region, Isolate* isolate) : region_(region) {
131     #define DECLARE_TYPE(name, value) \
132       name = Type::name(region); \
133       types.push_back(name);
134     BITSET_TYPE_LIST(DECLARE_TYPE)
135     #undef DECLARE_TYPE
136 
137     object_map = isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize);
138     array_map = isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize);
139     uninitialized_map = isolate->factory()->uninitialized_map();
140     ObjectClass = Type::Class(object_map, region);
141     ArrayClass = Type::Class(array_map, region);
142     UninitializedClass = Type::Class(uninitialized_map, region);
143 
144     maps.push_back(object_map);
145     maps.push_back(array_map);
146     maps.push_back(uninitialized_map);
147     for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
148       types.push_back(Type::Class(*it, region));
149     }
150 
151     smi = handle(Smi::FromInt(666), isolate);
152     signed32 = isolate->factory()->NewHeapNumber(0x40000000);
153     object1 = isolate->factory()->NewJSObjectFromMap(object_map);
154     object2 = isolate->factory()->NewJSObjectFromMap(object_map);
155     array = isolate->factory()->NewJSArray(20);
156     uninitialized = isolate->factory()->uninitialized_value();
157     SmiConstant = Type::Constant(smi, region);
158     Signed32Constant = Type::Constant(signed32, region);
159     ObjectConstant1 = Type::Constant(object1, region);
160     ObjectConstant2 = Type::Constant(object2, region);
161     ArrayConstant = Type::Constant(array, region);
162     UninitializedConstant = Type::Constant(uninitialized, region);
163 
164     values.push_back(smi);
165     values.push_back(signed32);
166     values.push_back(object1);
167     values.push_back(object2);
168     values.push_back(array);
169     values.push_back(uninitialized);
170     for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) {
171       types.push_back(Type::Constant(*it, region));
172     }
173 
174     NumberArray = Type::Array(Number, region);
175     StringArray = Type::Array(String, region);
176     AnyArray = Type::Array(Any, region);
177 
178     SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
179     NumberFunction1 = Type::Function(Number, Number, region);
180     NumberFunction2 = Type::Function(Number, Number, Number, region);
181     MethodFunction = Type::Function(String, Object, 0, region);
182 
183     for (int i = 0; i < 50; ++i) {
184       types.push_back(Fuzz());
185     }
186   }
187 
188   Handle<i::Map> object_map;
189   Handle<i::Map> array_map;
190   Handle<i::Map> uninitialized_map;
191 
192   Handle<i::Smi> smi;
193   Handle<i::HeapNumber> signed32;
194   Handle<i::JSObject> object1;
195   Handle<i::JSObject> object2;
196   Handle<i::JSArray> array;
197   Handle<i::Oddball> uninitialized;
198 
199   #define DECLARE_TYPE(name, value) TypeHandle name;
200   BITSET_TYPE_LIST(DECLARE_TYPE)
201   #undef DECLARE_TYPE
202 
203   TypeHandle ObjectClass;
204   TypeHandle ArrayClass;
205   TypeHandle UninitializedClass;
206 
207   TypeHandle SmiConstant;
208   TypeHandle Signed32Constant;
209   TypeHandle ObjectConstant1;
210   TypeHandle ObjectConstant2;
211   TypeHandle ArrayConstant;
212   TypeHandle UninitializedConstant;
213 
214   TypeHandle NumberArray;
215   TypeHandle StringArray;
216   TypeHandle AnyArray;
217 
218   TypeHandle SignedFunction1;
219   TypeHandle NumberFunction1;
220   TypeHandle NumberFunction2;
221   TypeHandle MethodFunction;
222 
223   typedef std::vector<TypeHandle> TypeVector;
224   typedef std::vector<Handle<i::Map> > MapVector;
225   typedef std::vector<Handle<i::Object> > ValueVector;
226   TypeVector types;
227   MapVector maps;
228   ValueVector values;
229 
Of(Handle<i::Object> value)230   TypeHandle Of(Handle<i::Object> value) {
231     return Type::Of(value, region_);
232   }
233 
NowOf(Handle<i::Object> value)234   TypeHandle NowOf(Handle<i::Object> value) {
235     return Type::NowOf(value, region_);
236   }
237 
Constant(Handle<i::Object> value)238   TypeHandle Constant(Handle<i::Object> value) {
239     return Type::Constant(value, region_);
240   }
241 
Class(Handle<i::Map> map)242   TypeHandle Class(Handle<i::Map> map) {
243     return Type::Class(map, region_);
244   }
245 
Array1(TypeHandle element)246   TypeHandle Array1(TypeHandle element) {
247     return Type::Array(element, region_);
248   }
249 
Function0(TypeHandle result,TypeHandle receiver)250   TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
251     return Type::Function(result, receiver, 0, region_);
252   }
253 
Function1(TypeHandle result,TypeHandle receiver,TypeHandle arg)254   TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) {
255     TypeHandle type = Type::Function(result, receiver, 1, region_);
256     type->AsFunction()->InitParameter(0, arg);
257     return type;
258   }
259 
Function2(TypeHandle result,TypeHandle arg1,TypeHandle arg2)260   TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) {
261     return Type::Function(result, arg1, arg2, region_);
262   }
263 
Union(TypeHandle t1,TypeHandle t2)264   TypeHandle Union(TypeHandle t1, TypeHandle t2) {
265     return Type::Union(t1, t2, region_);
266   }
Intersect(TypeHandle t1,TypeHandle t2)267   TypeHandle Intersect(TypeHandle t1, TypeHandle t2) {
268     return Type::Intersect(t1, t2, region_);
269   }
270 
271   template<class Type2, class TypeHandle2>
Convert(TypeHandle2 t)272   TypeHandle Convert(TypeHandle2 t) {
273     return Type::template Convert<Type2>(t, region_);
274   }
275 
Random()276   TypeHandle Random() {
277     return types[rng_.NextInt(static_cast<int>(types.size()))];
278   }
279 
Fuzz(int depth=5)280   TypeHandle Fuzz(int depth = 5) {
281     switch (rng_.NextInt(depth == 0 ? 3 : 20)) {
282       case 0: {  // bitset
283         int n = 0
284         #define COUNT_BITSET_TYPES(type, value) + 1
285         BITSET_TYPE_LIST(COUNT_BITSET_TYPES)
286         #undef COUNT_BITSET_TYPES
287         ;
288         int i = rng_.NextInt(n);
289         #define PICK_BITSET_TYPE(type, value) \
290           if (i-- == 0) return Type::type(region_);
291         BITSET_TYPE_LIST(PICK_BITSET_TYPE)
292         #undef PICK_BITSET_TYPE
293         UNREACHABLE();
294       }
295       case 1: {  // class
296         int i = rng_.NextInt(static_cast<int>(maps.size()));
297         return Type::Class(maps[i], region_);
298       }
299       case 2: {  // constant
300         int i = rng_.NextInt(static_cast<int>(values.size()));
301         return Type::Constant(values[i], region_);
302       }
303       case 3: {  // context
304         int depth = rng_.NextInt(3);
305         TypeHandle type = Type::Internal(region_);
306         for (int i = 0; i < depth; ++i) type = Type::Context(type, region_);
307         return type;
308       }
309       case 4: {  // array
310         TypeHandle element = Fuzz(depth / 2);
311         return Type::Array(element, region_);
312       }
313       case 5:
314       case 6:
315       case 7: {  // function
316         TypeHandle result = Fuzz(depth / 2);
317         TypeHandle receiver = Fuzz(depth / 2);
318         int arity = rng_.NextInt(3);
319         TypeHandle type = Type::Function(result, receiver, arity, region_);
320         for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
321           TypeHandle parameter = Fuzz(depth - 1);
322           type->AsFunction()->InitParameter(i, parameter);
323         }
324       }
325       default: {  // union
326         int n = rng_.NextInt(10);
327         TypeHandle type = None;
328         for (int i = 0; i < n; ++i) {
329           TypeHandle operand = Fuzz(depth - 1);
330           type = Type::Union(type, operand, region_);
331         }
332         return type;
333       }
334     }
335     UNREACHABLE();
336   }
337 
region()338   Region* region() { return region_; }
339 
340  private:
341   Region* region_;
342   RandomNumberGenerator rng_;
343 };
344 
345 
346 template<class Type, class TypeHandle, class Region, class Rep>
347 struct Tests : Rep {
348   typedef Types<Type, TypeHandle, Region> TypesInstance;
349   typedef typename TypesInstance::TypeVector::iterator TypeIterator;
350   typedef typename TypesInstance::MapVector::iterator MapIterator;
351   typedef typename TypesInstance::ValueVector::iterator ValueIterator;
352 
353   Isolate* isolate;
354   HandleScope scope;
355   Zone zone;
356   TypesInstance T;
357 
TestsTests358   Tests() :
359       isolate(CcTest::i_isolate()),
360       scope(isolate),
361       zone(isolate),
362       T(Rep::ToRegion(&zone, isolate), isolate) {
363   }
364 
EqualTests365   bool Equal(TypeHandle type1, TypeHandle type2) {
366     return
367         type1->Is(type2) && type2->Is(type1) &&
368         Rep::IsBitset(type1) == Rep::IsBitset(type2) &&
369         Rep::IsClass(type1) == Rep::IsClass(type2) &&
370         Rep::IsConstant(type1) == Rep::IsConstant(type2) &&
371         Rep::IsContext(type1) == Rep::IsContext(type2) &&
372         Rep::IsArray(type1) == Rep::IsArray(type2) &&
373         Rep::IsFunction(type1) == Rep::IsFunction(type2) &&
374         Rep::IsUnion(type1) == Rep::IsUnion(type2) &&
375         type1->NumClasses() == type2->NumClasses() &&
376         type1->NumConstants() == type2->NumConstants() &&
377         (!Rep::IsBitset(type1) ||
378           Rep::AsBitset(type1) == Rep::AsBitset(type2)) &&
379         (!Rep::IsClass(type1) ||
380           Rep::AsClass(type1) == Rep::AsClass(type2)) &&
381         (!Rep::IsConstant(type1) ||
382           Rep::AsConstant(type1) == Rep::AsConstant(type2)) &&
383           // TODO(rossberg): Check details of arrays, functions, bounds.
384           (!Rep::IsUnion(type1) ||
385           Rep::Length(Rep::AsUnion(type1)) == Rep::Length(Rep::AsUnion(type2)));
386   }
387 
CheckEqualTests388   void CheckEqual(TypeHandle type1, TypeHandle type2) {
389     CHECK(Equal(type1, type2));
390   }
391 
CheckSubTests392   void CheckSub(TypeHandle type1, TypeHandle type2) {
393     CHECK(type1->Is(type2));
394     CHECK(!type2->Is(type1));
395     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
396       CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2));
397     }
398   }
399 
CheckUnorderedTests400   void CheckUnordered(TypeHandle type1, TypeHandle type2) {
401     CHECK(!type1->Is(type2));
402     CHECK(!type2->Is(type1));
403     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
404       CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2));
405     }
406   }
407 
CheckOverlapTests408   void CheckOverlap(TypeHandle type1, TypeHandle type2, TypeHandle mask) {
409     CHECK(type1->Maybe(type2));
410     CHECK(type2->Maybe(type1));
411     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
412       CHECK_NE(0,
413           Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
414     }
415   }
416 
CheckDisjointTests417   void CheckDisjoint(TypeHandle type1, TypeHandle type2, TypeHandle mask) {
418     CHECK(!type1->Is(type2));
419     CHECK(!type2->Is(type1));
420     CHECK(!type1->Maybe(type2));
421     CHECK(!type2->Maybe(type1));
422     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
423       CHECK_EQ(0,
424           Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
425     }
426   }
427 
BitsetTests428   void Bitset() {
429     // None and Any are bitsets.
430     CHECK(this->IsBitset(T.None));
431     CHECK(this->IsBitset(T.Any));
432 
433     CHECK_EQ(0, this->AsBitset(T.None));
434     CHECK_EQ(-1, this->AsBitset(T.Any));
435 
436     // Union(T1, T2) is bitset for bitsets T1,T2
437     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
438       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
439         TypeHandle type1 = *it1;
440         TypeHandle type2 = *it2;
441         TypeHandle union12 = T.Union(type1, type2);
442         CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
443               this->IsBitset(union12));
444       }
445     }
446 
447     // Intersect(T1, T2) is bitset for bitsets T1,T2
448     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
449       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
450         TypeHandle type1 = *it1;
451         TypeHandle type2 = *it2;
452         TypeHandle intersect12 = T.Intersect(type1, type2);
453         CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
454               this->IsBitset(intersect12));
455       }
456     }
457 
458     // Union(T1, T2) is bitset if T2 is bitset and T1->Is(T2)
459     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
460       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
461         TypeHandle type1 = *it1;
462         TypeHandle type2 = *it2;
463         TypeHandle union12 = T.Union(type1, type2);
464         CHECK(!(this->IsBitset(type2) && type1->Is(type2)) ||
465               this->IsBitset(union12));
466       }
467     }
468 
469     // Union(T1, T2) is bitwise disjunction for bitsets T1,T2
470     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
471       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
472         TypeHandle type1 = *it1;
473         TypeHandle type2 = *it2;
474         TypeHandle union12 = T.Union(type1, type2);
475         if (this->IsBitset(type1) && this->IsBitset(type2)) {
476           CHECK_EQ(
477               this->AsBitset(type1) | this->AsBitset(type2),
478               this->AsBitset(union12));
479         }
480       }
481     }
482 
483     // Intersect(T1, T2) is bitwise conjunction for bitsets T1,T2
484     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
485       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
486         TypeHandle type1 = *it1;
487         TypeHandle type2 = *it2;
488         TypeHandle intersect12 = T.Intersect(type1, type2);
489         if (this->IsBitset(type1) && this->IsBitset(type2)) {
490           CHECK_EQ(
491               this->AsBitset(type1) & this->AsBitset(type2),
492               this->AsBitset(intersect12));
493         }
494       }
495     }
496   }
497 
ClassTests498   void Class() {
499     // Constructor
500     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
501       Handle<i::Map> map = *mt;
502       TypeHandle type = T.Class(map);
503       CHECK(this->IsClass(type));
504     }
505 
506     // Map attribute
507     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
508       Handle<i::Map> map = *mt;
509       TypeHandle type = T.Class(map);
510       CHECK(*map == *type->AsClass()->Map());
511     }
512 
513     // Functionality & Injectivity: Class(M1) = Class(M2) iff M1 = M2
514     for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
515       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
516         Handle<i::Map> map1 = *mt1;
517         Handle<i::Map> map2 = *mt2;
518         TypeHandle type1 = T.Class(map1);
519         TypeHandle type2 = T.Class(map2);
520         CHECK(Equal(type1, type2) == (*map1 == *map2));
521       }
522     }
523   }
524 
ConstantTests525   void Constant() {
526     // Constructor
527     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
528       Handle<i::Object> value = *vt;
529       TypeHandle type = T.Constant(value);
530       CHECK(this->IsConstant(type));
531     }
532 
533     // Value attribute
534     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
535       Handle<i::Object> value = *vt;
536       TypeHandle type = T.Constant(value);
537       CHECK(*value == *type->AsConstant()->Value());
538     }
539 
540     // Functionality & Injectivity: Constant(V1) = Constant(V2) iff V1 = V2
541     for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
542       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
543         Handle<i::Object> value1 = *vt1;
544         Handle<i::Object> value2 = *vt2;
545         TypeHandle type1 = T.Constant(value1);
546         TypeHandle type2 = T.Constant(value2);
547         CHECK(Equal(type1, type2) == (*value1 == *value2));
548       }
549     }
550 
551     // Typing of numbers
552     Factory* fac = isolate->factory();
553     CHECK(T.Constant(fac->NewNumber(0))->Is(T.UnsignedSmall));
554     CHECK(T.Constant(fac->NewNumber(1))->Is(T.UnsignedSmall));
555     CHECK(T.Constant(fac->NewNumber(0x3fffffff))->Is(T.UnsignedSmall));
556     CHECK(T.Constant(fac->NewNumber(-1))->Is(T.OtherSignedSmall));
557     CHECK(T.Constant(fac->NewNumber(-0x3fffffff))->Is(T.OtherSignedSmall));
558     CHECK(T.Constant(fac->NewNumber(-0x40000000))->Is(T.OtherSignedSmall));
559     if (SmiValuesAre31Bits()) {
560       CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31));
561       CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31));
562       CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
563       CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
564       CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
565     } else {
566       CHECK(SmiValuesAre32Bits());
567       CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
568       CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
569       CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31));
570       CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31));
571       CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSignedSmall));
572       CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSignedSmall));
573       CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSignedSmall));
574       CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
575       CHECK(!T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
576       CHECK(!T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
577     }
578     CHECK(T.Constant(fac->NewNumber(0x80000000u))->Is(T.OtherUnsigned32));
579     CHECK(T.Constant(fac->NewNumber(0xffffffffu))->Is(T.OtherUnsigned32));
580     CHECK(T.Constant(fac->NewNumber(0xffffffffu+1.0))->Is(T.OtherNumber));
581     CHECK(T.Constant(fac->NewNumber(-0x7fffffff-2.0))->Is(T.OtherNumber));
582     CHECK(T.Constant(fac->NewNumber(0.1))->Is(T.OtherNumber));
583     CHECK(T.Constant(fac->NewNumber(-10.1))->Is(T.OtherNumber));
584     CHECK(T.Constant(fac->NewNumber(10e60))->Is(T.OtherNumber));
585     CHECK(T.Constant(fac->NewNumber(-1.0*0.0))->Is(T.MinusZero));
586     CHECK(T.Constant(fac->NewNumber(OS::nan_value()))->Is(T.NaN));
587     CHECK(T.Constant(fac->NewNumber(V8_INFINITY))->Is(T.OtherNumber));
588     CHECK(T.Constant(fac->NewNumber(-V8_INFINITY))->Is(T.OtherNumber));
589   }
590 
ArrayTests591   void Array() {
592     // Constructor
593     for (int i = 0; i < 20; ++i) {
594       TypeHandle type = T.Random();
595       TypeHandle array = T.Array1(type);
596       CHECK(this->IsArray(array));
597     }
598 
599     // Attributes
600     for (int i = 0; i < 20; ++i) {
601       TypeHandle type = T.Random();
602       TypeHandle array = T.Array1(type);
603       CheckEqual(type, array->AsArray()->Element());
604     }
605 
606     // Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
607     for (int i = 0; i < 20; ++i) {
608       for (int j = 0; j < 20; ++j) {
609         TypeHandle type1 = T.Random();
610         TypeHandle type2 = T.Random();
611         TypeHandle array1 = T.Array1(type1);
612         TypeHandle array2 = T.Array1(type2);
613         CHECK(Equal(array1, array2) == Equal(type1, type2));
614       }
615     }
616   }
617 
FunctionTests618   void Function() {
619     // Constructors
620     for (int i = 0; i < 20; ++i) {
621       for (int j = 0; j < 20; ++j) {
622         for (int k = 0; k < 20; ++k) {
623           TypeHandle type1 = T.Random();
624           TypeHandle type2 = T.Random();
625           TypeHandle type3 = T.Random();
626           TypeHandle function0 = T.Function0(type1, type2);
627           TypeHandle function1 = T.Function1(type1, type2, type3);
628           TypeHandle function2 = T.Function2(type1, type2, type3);
629           CHECK(function0->IsFunction());
630           CHECK(function1->IsFunction());
631           CHECK(function2->IsFunction());
632         }
633       }
634     }
635 
636     // Attributes
637     for (int i = 0; i < 20; ++i) {
638       for (int j = 0; j < 20; ++j) {
639         for (int k = 0; k < 20; ++k) {
640           TypeHandle type1 = T.Random();
641           TypeHandle type2 = T.Random();
642           TypeHandle type3 = T.Random();
643           TypeHandle function0 = T.Function0(type1, type2);
644           TypeHandle function1 = T.Function1(type1, type2, type3);
645           TypeHandle function2 = T.Function2(type1, type2, type3);
646           CHECK_EQ(0, function0->AsFunction()->Arity());
647           CHECK_EQ(1, function1->AsFunction()->Arity());
648           CHECK_EQ(2, function2->AsFunction()->Arity());
649           CheckEqual(type1, function0->AsFunction()->Result());
650           CheckEqual(type1, function1->AsFunction()->Result());
651           CheckEqual(type1, function2->AsFunction()->Result());
652           CheckEqual(type2, function0->AsFunction()->Receiver());
653           CheckEqual(type2, function1->AsFunction()->Receiver());
654           CheckEqual(T.Any, function2->AsFunction()->Receiver());
655           CheckEqual(type3, function1->AsFunction()->Parameter(0));
656           CheckEqual(type2, function2->AsFunction()->Parameter(0));
657           CheckEqual(type3, function2->AsFunction()->Parameter(1));
658         }
659       }
660     }
661 
662     // Functionality & Injectivity: Function(Ts1) = Function(Ts2) iff Ts1 = Ts2
663     for (int i = 0; i < 20; ++i) {
664       for (int j = 0; j < 20; ++j) {
665         for (int k = 0; k < 20; ++k) {
666           TypeHandle type1 = T.Random();
667           TypeHandle type2 = T.Random();
668           TypeHandle type3 = T.Random();
669           TypeHandle function01 = T.Function0(type1, type2);
670           TypeHandle function02 = T.Function0(type1, type3);
671           TypeHandle function03 = T.Function0(type3, type2);
672           TypeHandle function11 = T.Function1(type1, type2, type2);
673           TypeHandle function12 = T.Function1(type1, type2, type3);
674           TypeHandle function21 = T.Function2(type1, type2, type2);
675           TypeHandle function22 = T.Function2(type1, type2, type3);
676           TypeHandle function23 = T.Function2(type1, type3, type2);
677           CHECK(Equal(function01, function02) == Equal(type2, type3));
678           CHECK(Equal(function01, function03) == Equal(type1, type3));
679           CHECK(Equal(function11, function12) == Equal(type2, type3));
680           CHECK(Equal(function21, function22) == Equal(type2, type3));
681           CHECK(Equal(function21, function23) == Equal(type2, type3));
682         }
683       }
684     }
685   }
686 
OfTests687   void Of() {
688     // Constant(V)->Is(Of(V))
689     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
690       Handle<i::Object> value = *vt;
691       TypeHandle const_type = T.Constant(value);
692       TypeHandle of_type = T.Of(value);
693       CHECK(const_type->Is(of_type));
694     }
695 
696     // Constant(V)->Is(T) iff Of(V)->Is(T) or T->Maybe(Constant(V))
697     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
698       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
699         Handle<i::Object> value = *vt;
700         TypeHandle type = *it;
701         TypeHandle const_type = T.Constant(value);
702         TypeHandle of_type = T.Of(value);
703         CHECK(const_type->Is(type) ==
704               (of_type->Is(type) || type->Maybe(const_type)));
705       }
706     }
707   }
708 
NowOfTests709   void NowOf() {
710     // Constant(V)->NowIs(NowOf(V))
711     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
712       Handle<i::Object> value = *vt;
713       TypeHandle const_type = T.Constant(value);
714       TypeHandle nowof_type = T.NowOf(value);
715       CHECK(const_type->NowIs(nowof_type));
716     }
717 
718     // NowOf(V)->Is(Of(V))
719     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
720       Handle<i::Object> value = *vt;
721       TypeHandle nowof_type = T.NowOf(value);
722       TypeHandle of_type = T.Of(value);
723       CHECK(nowof_type->Is(of_type));
724     }
725 
726     // Constant(V)->NowIs(T) iff NowOf(V)->NowIs(T) or T->Maybe(Constant(V))
727     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
728       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
729         Handle<i::Object> value = *vt;
730         TypeHandle type = *it;
731         TypeHandle const_type = T.Constant(value);
732         TypeHandle nowof_type = T.NowOf(value);
733         CHECK(const_type->NowIs(type) ==
734               (nowof_type->NowIs(type) || type->Maybe(const_type)));
735       }
736     }
737 
738     // Constant(V)->Is(T) implies NowOf(V)->Is(T) or T->Maybe(Constant(V))
739     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
740       for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
741         Handle<i::Object> value = *vt;
742         TypeHandle type = *it;
743         TypeHandle const_type = T.Constant(value);
744         TypeHandle nowof_type = T.NowOf(value);
745         CHECK(!const_type->Is(type) ||
746               (nowof_type->Is(type) || type->Maybe(const_type)));
747       }
748     }
749   }
750 
BoundsTests751   void Bounds() {
752     // Ordering: (T->BitsetGlb())->Is(T->BitsetLub())
753     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
754       TypeHandle type = *it;
755       TypeHandle glb =
756           Rep::BitsetType::New(Rep::BitsetType::Glb(type), T.region());
757       TypeHandle lub =
758           Rep::BitsetType::New(Rep::BitsetType::Lub(type), T.region());
759       CHECK(glb->Is(lub));
760     }
761 
762     // Lower bound: (T->BitsetGlb())->Is(T)
763     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
764       TypeHandle type = *it;
765       TypeHandle glb =
766           Rep::BitsetType::New(Rep::BitsetType::Glb(type), T.region());
767       CHECK(glb->Is(type));
768     }
769 
770     // Upper bound: T->Is(T->BitsetLub())
771     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
772       TypeHandle type = *it;
773       TypeHandle lub =
774           Rep::BitsetType::New(Rep::BitsetType::Lub(type), T.region());
775       CHECK(type->Is(lub));
776     }
777 
778     // Inherent bound: (T->BitsetLub())->Is(T->InherentBitsetLub())
779     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
780       TypeHandle type = *it;
781       TypeHandle lub =
782           Rep::BitsetType::New(Rep::BitsetType::Lub(type), T.region());
783       TypeHandle inherent =
784           Rep::BitsetType::New(Rep::BitsetType::InherentLub(type), T.region());
785       CHECK(lub->Is(inherent));
786     }
787   }
788 
IsTests789   void Is() {
790     // Least Element (Bottom): None->Is(T)
791     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
792       TypeHandle type = *it;
793       CHECK(T.None->Is(type));
794     }
795 
796     // Greatest Element (Top): T->Is(Any)
797     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
798       TypeHandle type = *it;
799       CHECK(type->Is(T.Any));
800     }
801 
802     // Bottom Uniqueness: T->Is(None) implies T = None
803     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
804       TypeHandle type = *it;
805       if (type->Is(T.None)) CheckEqual(type, T.None);
806     }
807 
808     // Top Uniqueness: Any->Is(T) implies T = Any
809     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
810       TypeHandle type = *it;
811       if (T.Any->Is(type)) CheckEqual(type, T.Any);
812     }
813 
814     // Reflexivity: T->Is(T)
815     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
816       TypeHandle type = *it;
817       CHECK(type->Is(type));
818     }
819 
820     // Transitivity: T1->Is(T2) and T2->Is(T3) implies T1->Is(T3)
821     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
822       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
823         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
824           TypeHandle type1 = *it1;
825           TypeHandle type2 = *it2;
826           TypeHandle type3 = *it3;
827           CHECK(!(type1->Is(type2) && type2->Is(type3)) || type1->Is(type3));
828         }
829       }
830     }
831 
832     // Antisymmetry: T1->Is(T2) and T2->Is(T1) iff T1 = T2
833     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
834       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
835         TypeHandle type1 = *it1;
836         TypeHandle type2 = *it2;
837         CHECK((type1->Is(type2) && type2->Is(type1)) == Equal(type1, type2));
838       }
839     }
840 
841     // Constant(V1)->Is(Constant(V2)) iff V1 = V2
842     for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
843       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
844         Handle<i::Object> value1 = *vt1;
845         Handle<i::Object> value2 = *vt2;
846         TypeHandle const_type1 = T.Constant(value1);
847         TypeHandle const_type2 = T.Constant(value2);
848         CHECK(const_type1->Is(const_type2) == (*value1 == *value2));
849       }
850     }
851 
852     // Class(M1)->Is(Class(M2)) iff M1 = M2
853     for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
854       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
855         Handle<i::Map> map1 = *mt1;
856         Handle<i::Map> map2 = *mt2;
857         TypeHandle class_type1 = T.Class(map1);
858         TypeHandle class_type2 = T.Class(map2);
859         CHECK(class_type1->Is(class_type2) == (*map1 == *map2));
860       }
861     }
862 
863     // Constant(V)->Is(Class(M)) never
864     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
865       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
866         Handle<i::Map> map = *mt;
867         Handle<i::Object> value = *vt;
868         TypeHandle constant_type = T.Constant(value);
869         TypeHandle class_type = T.Class(map);
870         CHECK(!constant_type->Is(class_type));
871       }
872     }
873 
874     // Class(M)->Is(Constant(V)) never
875     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
876       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
877         Handle<i::Map> map = *mt;
878         Handle<i::Object> value = *vt;
879         TypeHandle constant_type = T.Constant(value);
880         TypeHandle class_type = T.Class(map);
881         CHECK(!class_type->Is(constant_type));
882       }
883     }
884 
885     // Basic types
886     CheckUnordered(T.Boolean, T.Null);
887     CheckUnordered(T.Undefined, T.Null);
888     CheckUnordered(T.Boolean, T.Undefined);
889 
890     CheckSub(T.SignedSmall, T.Number);
891     CheckSub(T.Signed32, T.Number);
892     CheckSub(T.SignedSmall, T.Signed32);
893     CheckUnordered(T.SignedSmall, T.MinusZero);
894     CheckUnordered(T.Signed32, T.Unsigned32);
895 
896     CheckSub(T.UniqueName, T.Name);
897     CheckSub(T.String, T.Name);
898     CheckSub(T.InternalizedString, T.String);
899     CheckSub(T.InternalizedString, T.UniqueName);
900     CheckSub(T.InternalizedString, T.Name);
901     CheckSub(T.Symbol, T.UniqueName);
902     CheckSub(T.Symbol, T.Name);
903     CheckUnordered(T.String, T.UniqueName);
904     CheckUnordered(T.String, T.Symbol);
905     CheckUnordered(T.InternalizedString, T.Symbol);
906 
907     CheckSub(T.Object, T.Receiver);
908     CheckSub(T.Array, T.Object);
909     CheckSub(T.Function, T.Object);
910     CheckSub(T.Proxy, T.Receiver);
911     CheckUnordered(T.Object, T.Proxy);
912     CheckUnordered(T.Array, T.Function);
913 
914     // Structural types
915     CheckSub(T.ObjectClass, T.Object);
916     CheckSub(T.ArrayClass, T.Object);
917     CheckSub(T.ArrayClass, T.Array);
918     CheckSub(T.UninitializedClass, T.Internal);
919     CheckUnordered(T.ObjectClass, T.ArrayClass);
920     CheckUnordered(T.UninitializedClass, T.Null);
921     CheckUnordered(T.UninitializedClass, T.Undefined);
922 
923     CheckSub(T.SmiConstant, T.SignedSmall);
924     CheckSub(T.SmiConstant, T.Signed32);
925     CheckSub(T.SmiConstant, T.Number);
926     CheckSub(T.ObjectConstant1, T.Object);
927     CheckSub(T.ObjectConstant2, T.Object);
928     CheckSub(T.ArrayConstant, T.Object);
929     CheckSub(T.ArrayConstant, T.Array);
930     CheckSub(T.UninitializedConstant, T.Internal);
931     CheckUnordered(T.ObjectConstant1, T.ObjectConstant2);
932     CheckUnordered(T.ObjectConstant1, T.ArrayConstant);
933     CheckUnordered(T.UninitializedConstant, T.Null);
934     CheckUnordered(T.UninitializedConstant, T.Undefined);
935 
936     CheckUnordered(T.ObjectConstant1, T.ObjectClass);
937     CheckUnordered(T.ObjectConstant2, T.ObjectClass);
938     CheckUnordered(T.ObjectConstant1, T.ArrayClass);
939     CheckUnordered(T.ObjectConstant2, T.ArrayClass);
940     CheckUnordered(T.ArrayConstant, T.ObjectClass);
941 
942     CheckSub(T.NumberArray, T.Array);
943     CheckSub(T.NumberArray, T.Object);
944     CheckUnordered(T.StringArray, T.AnyArray);
945 
946     CheckSub(T.MethodFunction, T.Function);
947     CheckSub(T.NumberFunction1, T.Object);
948     CheckUnordered(T.SignedFunction1, T.NumberFunction1);
949     CheckUnordered(T.NumberFunction1, T.NumberFunction2);
950   }
951 
NowIsTests952   void NowIs() {
953     // Least Element (Bottom): None->NowIs(T)
954     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
955       TypeHandle type = *it;
956       CHECK(T.None->NowIs(type));
957     }
958 
959     // Greatest Element (Top): T->NowIs(Any)
960     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
961       TypeHandle type = *it;
962       CHECK(type->NowIs(T.Any));
963     }
964 
965     // Bottom Uniqueness: T->NowIs(None) implies T = None
966     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
967       TypeHandle type = *it;
968       if (type->NowIs(T.None)) CheckEqual(type, T.None);
969     }
970 
971     // Top Uniqueness: Any->NowIs(T) implies T = Any
972     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
973       TypeHandle type = *it;
974       if (T.Any->NowIs(type)) CheckEqual(type, T.Any);
975     }
976 
977     // Reflexivity: T->NowIs(T)
978     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
979       TypeHandle type = *it;
980       CHECK(type->NowIs(type));
981     }
982 
983     // Transitivity: T1->NowIs(T2) and T2->NowIs(T3) implies T1->NowIs(T3)
984     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
985       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
986         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
987           TypeHandle type1 = *it1;
988           TypeHandle type2 = *it2;
989           TypeHandle type3 = *it3;
990           CHECK(!(type1->NowIs(type2) && type2->NowIs(type3)) ||
991                 type1->NowIs(type3));
992         }
993       }
994     }
995 
996     // Antisymmetry: T1->NowIs(T2) and T2->NowIs(T1) iff T1 = T2
997     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
998       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
999         TypeHandle type1 = *it1;
1000         TypeHandle type2 = *it2;
1001         CHECK((type1->NowIs(type2) && type2->NowIs(type1)) ==
1002               Equal(type1, type2));
1003       }
1004     }
1005 
1006     // T1->Is(T2) implies T1->NowIs(T2)
1007     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1008       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1009         TypeHandle type1 = *it1;
1010         TypeHandle type2 = *it2;
1011         CHECK(!type1->Is(type2) || type1->NowIs(type2));
1012       }
1013     }
1014 
1015     // Constant(V1)->NowIs(Constant(V2)) iff V1 = V2
1016     for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
1017       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
1018         Handle<i::Object> value1 = *vt1;
1019         Handle<i::Object> value2 = *vt2;
1020         TypeHandle const_type1 = T.Constant(value1);
1021         TypeHandle const_type2 = T.Constant(value2);
1022         CHECK(const_type1->NowIs(const_type2) == (*value1 == *value2));
1023       }
1024     }
1025 
1026     // Class(M1)->NowIs(Class(M2)) iff M1 = M2
1027     for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
1028       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
1029         Handle<i::Map> map1 = *mt1;
1030         Handle<i::Map> map2 = *mt2;
1031         TypeHandle class_type1 = T.Class(map1);
1032         TypeHandle class_type2 = T.Class(map2);
1033         CHECK(class_type1->NowIs(class_type2) == (*map1 == *map2));
1034       }
1035     }
1036 
1037     // Constant(V)->NowIs(Class(M)) iff V has map M
1038     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
1039       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1040         Handle<i::Map> map = *mt;
1041         Handle<i::Object> value = *vt;
1042         TypeHandle const_type = T.Constant(value);
1043         TypeHandle class_type = T.Class(map);
1044         CHECK((value->IsHeapObject() &&
1045                i::HeapObject::cast(*value)->map() == *map)
1046               == const_type->NowIs(class_type));
1047       }
1048     }
1049 
1050     // Class(M)->NowIs(Constant(V)) never
1051     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
1052       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1053         Handle<i::Map> map = *mt;
1054         Handle<i::Object> value = *vt;
1055         TypeHandle const_type = T.Constant(value);
1056         TypeHandle class_type = T.Class(map);
1057         CHECK(!class_type->NowIs(const_type));
1058       }
1059     }
1060   }
1061 
ContainsTests1062   void Contains() {
1063     // T->Contains(V) iff Constant(V)->Is(T)
1064     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1065       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1066         TypeHandle type = *it;
1067         Handle<i::Object> value = *vt;
1068         TypeHandle const_type = T.Constant(value);
1069         CHECK(type->Contains(value) == const_type->Is(type));
1070       }
1071     }
1072 
1073     // Of(V)->Is(T) implies T->Contains(V)
1074     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1075       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1076         TypeHandle type = *it;
1077         Handle<i::Object> value = *vt;
1078         TypeHandle of_type = T.Of(value);
1079         CHECK(!of_type->Is(type) || type->Contains(value));
1080       }
1081     }
1082   }
1083 
NowContainsTests1084   void NowContains() {
1085     // T->NowContains(V) iff Constant(V)->NowIs(T)
1086     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1087       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1088         TypeHandle type = *it;
1089         Handle<i::Object> value = *vt;
1090         TypeHandle const_type = T.Constant(value);
1091         CHECK(type->NowContains(value) == const_type->NowIs(type));
1092       }
1093     }
1094 
1095     // T->Contains(V) implies T->NowContains(V)
1096     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1097       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1098         TypeHandle type = *it;
1099         Handle<i::Object> value = *vt;
1100         CHECK(!type->Contains(value) || type->NowContains(value));
1101       }
1102     }
1103 
1104     // NowOf(V)->Is(T) implies T->NowContains(V)
1105     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1106       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1107         TypeHandle type = *it;
1108         Handle<i::Object> value = *vt;
1109         TypeHandle nowof_type = T.Of(value);
1110         CHECK(!nowof_type->NowIs(type) || type->NowContains(value));
1111       }
1112     }
1113 
1114     // NowOf(V)->NowIs(T) implies T->NowContains(V)
1115     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1116       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1117         TypeHandle type = *it;
1118         Handle<i::Object> value = *vt;
1119         TypeHandle nowof_type = T.Of(value);
1120         CHECK(!nowof_type->NowIs(type) || type->NowContains(value));
1121       }
1122     }
1123   }
1124 
MaybeTests1125   void Maybe() {
1126     // T->Maybe(Any) iff T inhabited
1127     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1128       TypeHandle type = *it;
1129       CHECK(type->Maybe(T.Any) == type->IsInhabited());
1130     }
1131 
1132     // T->Maybe(None) never
1133     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1134       TypeHandle type = *it;
1135       CHECK(!type->Maybe(T.None));
1136     }
1137 
1138     // Reflexivity upto Inhabitation: T->Maybe(T) iff T inhabited
1139     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1140       TypeHandle type = *it;
1141       CHECK(type->Maybe(type) == type->IsInhabited());
1142     }
1143 
1144     // Symmetry: T1->Maybe(T2) iff T2->Maybe(T1)
1145     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1146       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1147         TypeHandle type1 = *it1;
1148         TypeHandle type2 = *it2;
1149         CHECK(type1->Maybe(type2) == type2->Maybe(type1));
1150       }
1151     }
1152 
1153     // T1->Maybe(T2) implies T1, T2 inhabited
1154     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1155       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1156         TypeHandle type1 = *it1;
1157         TypeHandle type2 = *it2;
1158         CHECK(!type1->Maybe(type2) ||
1159               (type1->IsInhabited() && type2->IsInhabited()));
1160       }
1161     }
1162 
1163     // T1->Maybe(T2) implies Intersect(T1, T2) inhabited
1164     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1165       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1166         TypeHandle type1 = *it1;
1167         TypeHandle type2 = *it2;
1168         TypeHandle intersect12 = T.Intersect(type1, type2);
1169         CHECK(!type1->Maybe(type2) || intersect12->IsInhabited());
1170       }
1171     }
1172 
1173     // T1->Is(T2) and T1 inhabited implies T1->Maybe(T2)
1174     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1175       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1176         TypeHandle type1 = *it1;
1177         TypeHandle type2 = *it2;
1178         CHECK(!(type1->Is(type2) && type1->IsInhabited()) ||
1179               type1->Maybe(type2));
1180       }
1181     }
1182 
1183     // Constant(V1)->Maybe(Constant(V2)) iff V1 = V2
1184     for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
1185       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
1186         Handle<i::Object> value1 = *vt1;
1187         Handle<i::Object> value2 = *vt2;
1188         TypeHandle const_type1 = T.Constant(value1);
1189         TypeHandle const_type2 = T.Constant(value2);
1190         CHECK(const_type1->Maybe(const_type2) == (*value1 == *value2));
1191       }
1192     }
1193 
1194     // Class(M1)->Maybe(Class(M2)) iff M1 = M2
1195     for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
1196       for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
1197         Handle<i::Map> map1 = *mt1;
1198         Handle<i::Map> map2 = *mt2;
1199         TypeHandle class_type1 = T.Class(map1);
1200         TypeHandle class_type2 = T.Class(map2);
1201         CHECK(class_type1->Maybe(class_type2) == (*map1 == *map2));
1202       }
1203     }
1204 
1205     // Constant(V)->Maybe(Class(M)) never
1206     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
1207       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1208         Handle<i::Map> map = *mt;
1209         Handle<i::Object> value = *vt;
1210         TypeHandle const_type = T.Constant(value);
1211         TypeHandle class_type = T.Class(map);
1212         CHECK(!const_type->Maybe(class_type));
1213       }
1214     }
1215 
1216     // Class(M)->Maybe(Constant(V)) never
1217     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
1218       for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
1219         Handle<i::Map> map = *mt;
1220         Handle<i::Object> value = *vt;
1221         TypeHandle const_type = T.Constant(value);
1222         TypeHandle class_type = T.Class(map);
1223         CHECK(!class_type->Maybe(const_type));
1224       }
1225     }
1226 
1227     // Basic types
1228     CheckDisjoint(T.Boolean, T.Null, T.Semantic);
1229     CheckDisjoint(T.Undefined, T.Null, T.Semantic);
1230     CheckDisjoint(T.Boolean, T.Undefined, T.Semantic);
1231 
1232     CheckOverlap(T.SignedSmall, T.Number, T.Semantic);
1233     CheckOverlap(T.NaN, T.Number, T.Semantic);
1234     CheckDisjoint(T.Signed32, T.NaN, T.Semantic);
1235 
1236     CheckOverlap(T.UniqueName, T.Name, T.Semantic);
1237     CheckOverlap(T.String, T.Name, T.Semantic);
1238     CheckOverlap(T.InternalizedString, T.String, T.Semantic);
1239     CheckOverlap(T.InternalizedString, T.UniqueName, T.Semantic);
1240     CheckOverlap(T.InternalizedString, T.Name, T.Semantic);
1241     CheckOverlap(T.Symbol, T.UniqueName, T.Semantic);
1242     CheckOverlap(T.Symbol, T.Name, T.Semantic);
1243     CheckOverlap(T.String, T.UniqueName, T.Semantic);
1244     CheckDisjoint(T.String, T.Symbol, T.Semantic);
1245     CheckDisjoint(T.InternalizedString, T.Symbol, T.Semantic);
1246 
1247     CheckOverlap(T.Object, T.Receiver, T.Semantic);
1248     CheckOverlap(T.Array, T.Object, T.Semantic);
1249     CheckOverlap(T.Function, T.Object, T.Semantic);
1250     CheckOverlap(T.Proxy, T.Receiver, T.Semantic);
1251     CheckDisjoint(T.Object, T.Proxy, T.Semantic);
1252     CheckDisjoint(T.Array, T.Function, T.Semantic);
1253 
1254     // Structural types
1255     CheckOverlap(T.ObjectClass, T.Object, T.Semantic);
1256     CheckOverlap(T.ArrayClass, T.Object, T.Semantic);
1257     CheckOverlap(T.ObjectClass, T.ObjectClass, T.Semantic);
1258     CheckOverlap(T.ArrayClass, T.ArrayClass, T.Semantic);
1259     CheckDisjoint(T.ObjectClass, T.ArrayClass, T.Semantic);
1260 
1261     CheckOverlap(T.SmiConstant, T.SignedSmall, T.Semantic);
1262     CheckOverlap(T.SmiConstant, T.Signed32, T.Semantic);
1263     CheckOverlap(T.SmiConstant, T.Number, T.Semantic);
1264     CheckOverlap(T.ObjectConstant1, T.Object, T.Semantic);
1265     CheckOverlap(T.ObjectConstant2, T.Object, T.Semantic);
1266     CheckOverlap(T.ArrayConstant, T.Object, T.Semantic);
1267     CheckOverlap(T.ArrayConstant, T.Array, T.Semantic);
1268     CheckOverlap(T.ObjectConstant1, T.ObjectConstant1, T.Semantic);
1269     CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2, T.Semantic);
1270     CheckDisjoint(T.ObjectConstant1, T.ArrayConstant, T.Semantic);
1271 
1272     CheckDisjoint(T.ObjectConstant1, T.ObjectClass, T.Semantic);
1273     CheckDisjoint(T.ObjectConstant2, T.ObjectClass, T.Semantic);
1274     CheckDisjoint(T.ObjectConstant1, T.ArrayClass, T.Semantic);
1275     CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
1276     CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);
1277 
1278     CheckOverlap(T.NumberArray, T.Array, T.Semantic);
1279     CheckDisjoint(T.NumberArray, T.AnyArray, T.Semantic);
1280     CheckDisjoint(T.NumberArray, T.StringArray, T.Semantic);
1281 
1282     CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
1283     CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
1284     CheckDisjoint(T.SignedFunction1, T.NumberFunction2, T.Semantic);
1285     CheckDisjoint(T.NumberFunction1, T.NumberFunction2, T.Semantic);
1286     CheckDisjoint(T.SignedFunction1, T.MethodFunction, T.Semantic);
1287   }
1288 
Union1Tests1289   void Union1() {
1290     // Identity: Union(T, None) = T
1291     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1292       TypeHandle type = *it;
1293       TypeHandle union_type = T.Union(type, T.None);
1294       CheckEqual(union_type, type);
1295     }
1296 
1297     // Domination: Union(T, Any) = Any
1298     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1299       TypeHandle type = *it;
1300       TypeHandle union_type = T.Union(type, T.Any);
1301       CheckEqual(union_type, T.Any);
1302     }
1303 
1304     // Idempotence: Union(T, T) = T
1305     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1306       TypeHandle type = *it;
1307       TypeHandle union_type = T.Union(type, type);
1308       CheckEqual(union_type, type);
1309     }
1310 
1311     // Commutativity: Union(T1, T2) = Union(T2, T1)
1312     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1313       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1314         TypeHandle type1 = *it1;
1315         TypeHandle type2 = *it2;
1316         TypeHandle union12 = T.Union(type1, type2);
1317         TypeHandle union21 = T.Union(type2, type1);
1318         CheckEqual(union12, union21);
1319       }
1320     }
1321 
1322     // Associativity: Union(T1, Union(T2, T3)) = Union(Union(T1, T2), T3)
1323     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1324       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1325         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1326           TypeHandle type1 = *it1;
1327           TypeHandle type2 = *it2;
1328           TypeHandle type3 = *it3;
1329           TypeHandle union12 = T.Union(type1, type2);
1330           TypeHandle union23 = T.Union(type2, type3);
1331           TypeHandle union1_23 = T.Union(type1, union23);
1332           TypeHandle union12_3 = T.Union(union12, type3);
1333           CheckEqual(union1_23, union12_3);
1334         }
1335       }
1336     }
1337 
1338     // Meet: T1->Is(Union(T1, T2)) and T2->Is(Union(T1, T2))
1339     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1340       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1341         TypeHandle type1 = *it1;
1342         TypeHandle type2 = *it2;
1343         TypeHandle union12 = T.Union(type1, type2);
1344         CHECK(type1->Is(union12));
1345         CHECK(type2->Is(union12));
1346       }
1347     }
1348 
1349     // Upper Boundedness: T1->Is(T2) implies Union(T1, T2) = T2
1350     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1351       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1352         TypeHandle type1 = *it1;
1353         TypeHandle type2 = *it2;
1354         TypeHandle union12 = T.Union(type1, type2);
1355         if (type1->Is(type2)) CheckEqual(union12, type2);
1356       }
1357     }
1358   }
1359 
Union2Tests1360   void Union2() {
1361     // Monotonicity: T1->Is(T2) implies Union(T1, T3)->Is(Union(T2, T3))
1362     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1363       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1364         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1365           TypeHandle type1 = *it1;
1366           TypeHandle type2 = *it2;
1367           TypeHandle type3 = *it3;
1368           TypeHandle union13 = T.Union(type1, type3);
1369           TypeHandle union23 = T.Union(type2, type3);
1370           CHECK(!type1->Is(type2) || union13->Is(union23));
1371         }
1372       }
1373     }
1374 
1375     // Monotonicity: T1->Is(T3) and T2->Is(T3) implies Union(T1, T2)->Is(T3)
1376     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1377       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1378         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1379           TypeHandle type1 = *it1;
1380           TypeHandle type2 = *it2;
1381           TypeHandle type3 = *it3;
1382           TypeHandle union12 = T.Union(type1, type2);
1383           CHECK(!(type1->Is(type3) && type2->Is(type3)) || union12->Is(type3));
1384         }
1385       }
1386     }
1387 
1388     // Monotonicity: T1->Is(T2) or T1->Is(T3) implies T1->Is(Union(T2, T3))
1389     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1390       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1391         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1392           TypeHandle type1 = *it1;
1393           TypeHandle type2 = *it2;
1394           TypeHandle type3 = *it3;
1395           TypeHandle union23 = T.Union(type2, type3);
1396           CHECK(!(type1->Is(type2) || type1->Is(type3)) || type1->Is(union23));
1397         }
1398       }
1399     }
1400 
1401     // Class-class
1402     CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object);
1403     CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.Array);
1404     CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array, T.Semantic);
1405     CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number, T.Semantic);
1406 
1407     // Constant-constant
1408     CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object);
1409     CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayConstant), T.Array);
1410     CheckUnordered(
1411         T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass);
1412     CheckOverlap(
1413         T.Union(T.ObjectConstant1, T.ArrayConstant), T.Array, T.Semantic);
1414     CheckDisjoint(
1415         T.Union(T.ObjectConstant1, T.ArrayConstant), T.Number, T.Semantic);
1416     CheckDisjoint(
1417         T.Union(T.ObjectConstant1, T.ArrayConstant), T.ObjectClass, T.Semantic);
1418 
1419     // Bitset-array
1420     CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array)));
1421     CHECK(this->IsUnion(T.Union(T.NumberArray, T.Number)));
1422 
1423     CheckEqual(T.Union(T.AnyArray, T.Array), T.Array);
1424     CheckUnordered(T.Union(T.AnyArray, T.String), T.Array);
1425     CheckOverlap(T.Union(T.NumberArray, T.String), T.Object, T.Semantic);
1426     CheckDisjoint(T.Union(T.NumberArray, T.String), T.Number, T.Semantic);
1427 
1428     // Bitset-function
1429     CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
1430     CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
1431 
1432     CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function);
1433     CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function);
1434     CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic);
1435     CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
1436 
1437     // Bitset-class
1438     CheckSub(
1439         T.Union(T.ObjectClass, T.SignedSmall), T.Union(T.Object, T.Number));
1440     CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
1441     CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
1442     CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object, T.Semantic);
1443     CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number, T.Semantic);
1444 
1445     // Bitset-constant
1446     CheckSub(
1447         T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
1448     CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
1449     CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array);
1450     CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object, T.Semantic);
1451     CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number, T.Semantic);
1452 
1453     // Class-constant
1454     CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object);
1455     CheckUnordered(T.ObjectClass, T.Union(T.ObjectConstant1, T.ArrayClass));
1456     CheckSub(
1457         T.Union(T.ObjectConstant1, T.ArrayClass), T.Union(T.Array, T.Object));
1458     CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant);
1459     CheckDisjoint(
1460         T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2,
1461         T.Semantic);
1462     CheckDisjoint(
1463         T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass, T.Semantic);
1464 
1465     // Bitset-union
1466     CheckSub(
1467         T.NaN,
1468         T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
1469     CheckSub(
1470         T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Signed32),
1471         T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
1472 
1473     // Class-union
1474     CheckSub(
1475         T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
1476         T.Object);
1477     CheckEqual(
1478         T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass),
1479         T.Union(T.ArrayClass, T.ObjectConstant2));
1480 
1481     // Constant-union
1482     CheckEqual(
1483         T.Union(
1484             T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
1485         T.Union(T.ObjectConstant2, T.ObjectConstant1));
1486     CheckEqual(
1487         T.Union(
1488             T.Union(T.ArrayConstant, T.ObjectConstant2), T.ObjectConstant1),
1489         T.Union(
1490             T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
1491 
1492     // Array-union
1493     CheckEqual(
1494         T.Union(T.AnyArray, T.Union(T.NumberArray, T.AnyArray)),
1495         T.Union(T.AnyArray, T.NumberArray));
1496     CheckSub(T.Union(T.AnyArray, T.NumberArray), T.Array);
1497 
1498     // Function-union
1499     CheckEqual(
1500         T.Union(T.NumberFunction1, T.NumberFunction2),
1501         T.Union(T.NumberFunction2, T.NumberFunction1));
1502     CheckSub(T.Union(T.SignedFunction1, T.MethodFunction), T.Function);
1503 
1504     // Union-union
1505     CheckEqual(
1506         T.Union(
1507             T.Union(T.ObjectConstant2, T.ObjectConstant1),
1508             T.Union(T.ObjectConstant1, T.ObjectConstant2)),
1509         T.Union(T.ObjectConstant2, T.ObjectConstant1));
1510     CheckEqual(
1511         T.Union(
1512             T.Union(T.Number, T.ArrayClass),
1513             T.Union(T.SignedSmall, T.Array)),
1514         T.Union(T.Number, T.Array));
1515   }
1516 
Intersect1Tests1517   void Intersect1() {
1518     // Identity: Intersect(T, Any) = T
1519     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1520       TypeHandle type = *it;
1521       TypeHandle intersect_type = T.Intersect(type, T.Any);
1522       CheckEqual(intersect_type, type);
1523     }
1524 
1525     // Domination: Intersect(T, None) = None
1526     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1527       TypeHandle type = *it;
1528       TypeHandle intersect_type = T.Intersect(type, T.None);
1529       CheckEqual(intersect_type, T.None);
1530     }
1531 
1532     // Idempotence: Intersect(T, T) = T
1533     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1534       TypeHandle type = *it;
1535       TypeHandle intersect_type = T.Intersect(type, type);
1536       CheckEqual(intersect_type, type);
1537     }
1538 
1539     // Commutativity: Intersect(T1, T2) = Intersect(T2, T1)
1540     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1541       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1542         TypeHandle type1 = *it1;
1543         TypeHandle type2 = *it2;
1544         TypeHandle intersect12 = T.Intersect(type1, type2);
1545         TypeHandle intersect21 = T.Intersect(type2, type1);
1546         CheckEqual(intersect12, intersect21);
1547       }
1548     }
1549 
1550     // Associativity:
1551     // Intersect(T1, Intersect(T2, T3)) = Intersect(Intersect(T1, T2), T3)
1552     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1553       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1554         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1555           TypeHandle type1 = *it1;
1556           TypeHandle type2 = *it2;
1557           TypeHandle type3 = *it3;
1558           TypeHandle intersect12 = T.Intersect(type1, type2);
1559           TypeHandle intersect23 = T.Intersect(type2, type3);
1560           TypeHandle intersect1_23 = T.Intersect(type1, intersect23);
1561           TypeHandle intersect12_3 = T.Intersect(intersect12, type3);
1562           CheckEqual(intersect1_23, intersect12_3);
1563         }
1564       }
1565     }
1566 
1567     // Join: Intersect(T1, T2)->Is(T1) and Intersect(T1, T2)->Is(T2)
1568     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1569       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1570         TypeHandle type1 = *it1;
1571         TypeHandle type2 = *it2;
1572         TypeHandle intersect12 = T.Intersect(type1, type2);
1573         CHECK(intersect12->Is(type1));
1574         CHECK(intersect12->Is(type2));
1575       }
1576     }
1577 
1578     // Lower Boundedness: T1->Is(T2) implies Intersect(T1, T2) = T1
1579     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1580       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1581         TypeHandle type1 = *it1;
1582         TypeHandle type2 = *it2;
1583         TypeHandle intersect12 = T.Intersect(type1, type2);
1584         if (type1->Is(type2)) CheckEqual(intersect12, type1);
1585       }
1586     }
1587   }
1588 
Intersect2Tests1589   void Intersect2() {
1590     // Monotonicity: T1->Is(T2) implies Intersect(T1, T3)->Is(Intersect(T2, T3))
1591     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1592       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1593         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1594           TypeHandle type1 = *it1;
1595           TypeHandle type2 = *it2;
1596           TypeHandle type3 = *it3;
1597           TypeHandle intersect13 = T.Intersect(type1, type3);
1598           TypeHandle intersect23 = T.Intersect(type2, type3);
1599           CHECK(!type1->Is(type2) || intersect13->Is(intersect23));
1600         }
1601       }
1602     }
1603 
1604     // Monotonicity: T1->Is(T3) or T2->Is(T3) implies Intersect(T1, T2)->Is(T3)
1605     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1606       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1607         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1608           TypeHandle type1 = *it1;
1609           TypeHandle type2 = *it2;
1610           TypeHandle type3 = *it3;
1611           TypeHandle intersect12 = T.Intersect(type1, type2);
1612           CHECK(!(type1->Is(type3) || type2->Is(type3)) ||
1613                 intersect12->Is(type3));
1614         }
1615       }
1616     }
1617 
1618     // Monotonicity: T1->Is(T2) and T1->Is(T3) implies T1->Is(Intersect(T2, T3))
1619     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1620       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1621         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1622           TypeHandle type1 = *it1;
1623           TypeHandle type2 = *it2;
1624           TypeHandle type3 = *it3;
1625           TypeHandle intersect23 = T.Intersect(type2, type3);
1626           CHECK(!(type1->Is(type2) && type1->Is(type3)) ||
1627                 type1->Is(intersect23));
1628         }
1629       }
1630     }
1631 
1632     // Bitset-class
1633     CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
1634     CheckSub(T.Intersect(T.ObjectClass, T.Array), T.Representation);
1635     CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
1636 
1637     // Bitset-array
1638     CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
1639     CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation);
1640 
1641     // Bitset-function
1642     CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
1643     CheckSub(T.Intersect(T.NumberFunction1, T.Array), T.Representation);
1644 
1645     // Bitset-union
1646     CheckEqual(
1647         T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
1648         T.Union(T.ObjectConstant1, T.ObjectClass));
1649     CHECK(
1650         !T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number)
1651             ->IsInhabited());
1652 
1653     // Class-constant
1654     CHECK(!T.Intersect(T.ObjectConstant1, T.ObjectClass)->IsInhabited());
1655     CHECK(!T.Intersect(T.ArrayClass, T.ObjectConstant2)->IsInhabited());
1656 
1657     // Array-union
1658     CheckEqual(
1659         T.Intersect(T.NumberArray, T.Union(T.NumberArray, T.ArrayClass)),
1660         T.NumberArray);
1661     CheckEqual(
1662         T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
1663         T.AnyArray);
1664     CHECK(
1665         !T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.NumberArray)
1666             ->IsInhabited());
1667 
1668     // Function-union
1669     CheckEqual(
1670         T.Intersect(T.MethodFunction, T.Union(T.String, T.MethodFunction)),
1671         T.MethodFunction);
1672     CheckEqual(
1673         T.Intersect(T.NumberFunction1, T.Union(T.Object, T.SmiConstant)),
1674         T.NumberFunction1);
1675     CHECK(
1676         !T.Intersect(T.Union(T.MethodFunction, T.Name), T.NumberFunction2)
1677             ->IsInhabited());
1678 
1679     // Class-union
1680     CheckEqual(
1681         T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
1682         T.ArrayClass);
1683     CheckEqual(
1684         T.Intersect(T.ArrayClass, T.Union(T.Object, T.SmiConstant)),
1685         T.ArrayClass);
1686     CHECK(
1687         !T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant), T.ArrayClass)
1688             ->IsInhabited());
1689 
1690     // Constant-union
1691     CheckEqual(
1692         T.Intersect(
1693             T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
1694         T.ObjectConstant1);
1695     CheckEqual(
1696         T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)),
1697         T.SmiConstant);
1698     CHECK(
1699         !T.Intersect(
1700             T.Union(T.ArrayConstant, T.ObjectClass), T.ObjectConstant1)
1701                 ->IsInhabited());
1702 
1703     // Union-union
1704     CheckEqual(
1705         T.Intersect(
1706             T.Union(T.Number, T.ArrayClass),
1707             T.Union(T.SignedSmall, T.Array)),
1708         T.Union(T.SignedSmall, T.ArrayClass));
1709     CheckEqual(
1710         T.Intersect(
1711             T.Union(T.Number, T.ObjectClass),
1712             T.Union(T.Signed32, T.Array)),
1713         T.Signed32);
1714     CheckEqual(
1715         T.Intersect(
1716             T.Union(T.ObjectConstant2, T.ObjectConstant1),
1717             T.Union(T.ObjectConstant1, T.ObjectConstant2)),
1718         T.Union(T.ObjectConstant2, T.ObjectConstant1));
1719     CheckEqual(
1720         T.Intersect(
1721             T.Union(
1722                 T.Union(T.ObjectConstant2, T.ObjectConstant1), T.ArrayClass),
1723             T.Union(
1724                 T.ObjectConstant1,
1725                 T.Union(T.ArrayConstant, T.ObjectConstant2))),
1726         T.Union(T.ObjectConstant2, T.ObjectConstant1));
1727   }
1728 
Distributivity1Tests1729   void Distributivity1() {
1730     // Distributivity:
1731     // Union(T1, Intersect(T2, T3)) = Intersect(Union(T1, T2), Union(T1, T3))
1732     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1733       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1734         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1735           TypeHandle type1 = *it1;
1736           TypeHandle type2 = *it2;
1737           TypeHandle type3 = *it3;
1738           TypeHandle union12 = T.Union(type1, type2);
1739           TypeHandle union13 = T.Union(type1, type3);
1740           TypeHandle intersect23 = T.Intersect(type2, type3);
1741           TypeHandle union1_23 = T.Union(type1, intersect23);
1742           TypeHandle intersect12_13 = T.Intersect(union12, union13);
1743           CHECK(Equal(union1_23, intersect12_13));
1744         }
1745       }
1746     }
1747   }
1748 
Distributivity2Tests1749   void Distributivity2() {
1750     // Distributivity:
1751     // Intersect(T1, Union(T2, T3)) = Union(Intersect(T1, T2), Intersect(T1,T3))
1752     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1753       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1754         for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1755           TypeHandle type1 = *it1;
1756           TypeHandle type2 = *it2;
1757           TypeHandle type3 = *it3;
1758           TypeHandle intersect12 = T.Intersect(type1, type2);
1759           TypeHandle intersect13 = T.Intersect(type1, type3);
1760           TypeHandle union23 = T.Union(type2, type3);
1761           TypeHandle intersect1_23 = T.Intersect(type1, union23);
1762           TypeHandle union12_13 = T.Union(intersect12, intersect13);
1763           CHECK(Equal(intersect1_23, union12_13));
1764         }
1765       }
1766     }
1767   }
1768 
1769   template<class Type2, class TypeHandle2, class Region2, class Rep2>
ConvertTests1770   void Convert() {
1771     Types<Type2, TypeHandle2, Region2> T2(
1772         Rep2::ToRegion(&zone, isolate), isolate);
1773     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
1774       TypeHandle type1 = *it;
1775       TypeHandle2 type2 = T2.template Convert<Type>(type1);
1776       TypeHandle type3 = T.template Convert<Type2>(type2);
1777       CheckEqual(type1, type3);
1778     }
1779   }
1780 
HTypeFromTypeTests1781   void HTypeFromType() {
1782     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1783       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
1784         TypeHandle type1 = *it1;
1785         TypeHandle type2 = *it2;
1786         HType htype1 = HType::FromType<Type>(type1);
1787         HType htype2 = HType::FromType<Type>(type2);
1788         CHECK(!type1->Is(type2) || htype1.IsSubtypeOf(htype2));
1789       }
1790     }
1791   }
1792 };
1793 
1794 typedef Tests<Type, Type*, Zone, ZoneRep> ZoneTests;
1795 typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
1796 
1797 
TEST(BitsetType)1798 TEST(BitsetType) {
1799   CcTest::InitializeVM();
1800   ZoneTests().Bitset();
1801   HeapTests().Bitset();
1802 }
1803 
1804 
TEST(ClassType)1805 TEST(ClassType) {
1806   CcTest::InitializeVM();
1807   ZoneTests().Class();
1808   HeapTests().Class();
1809 }
1810 
1811 
TEST(ConstantType)1812 TEST(ConstantType) {
1813   CcTest::InitializeVM();
1814   ZoneTests().Constant();
1815   HeapTests().Constant();
1816 }
1817 
1818 
TEST(ArrayType)1819 TEST(ArrayType) {
1820   CcTest::InitializeVM();
1821   ZoneTests().Array();
1822   HeapTests().Array();
1823 }
1824 
1825 
TEST(FunctionType)1826 TEST(FunctionType) {
1827   CcTest::InitializeVM();
1828   ZoneTests().Function();
1829   HeapTests().Function();
1830 }
1831 
1832 
TEST(Of)1833 TEST(Of) {
1834   CcTest::InitializeVM();
1835   ZoneTests().Of();
1836   HeapTests().Of();
1837 }
1838 
1839 
TEST(NowOf)1840 TEST(NowOf) {
1841   CcTest::InitializeVM();
1842   ZoneTests().NowOf();
1843   HeapTests().NowOf();
1844 }
1845 
1846 
TEST(Bounds)1847 TEST(Bounds) {
1848   CcTest::InitializeVM();
1849   ZoneTests().Bounds();
1850   HeapTests().Bounds();
1851 }
1852 
1853 
TEST(Is)1854 TEST(Is) {
1855   CcTest::InitializeVM();
1856   ZoneTests().Is();
1857   HeapTests().Is();
1858 }
1859 
1860 
TEST(NowIs)1861 TEST(NowIs) {
1862   CcTest::InitializeVM();
1863   ZoneTests().NowIs();
1864   HeapTests().NowIs();
1865 }
1866 
1867 
TEST(Contains)1868 TEST(Contains) {
1869   CcTest::InitializeVM();
1870   ZoneTests().Contains();
1871   HeapTests().Contains();
1872 }
1873 
1874 
TEST(NowContains)1875 TEST(NowContains) {
1876   CcTest::InitializeVM();
1877   ZoneTests().NowContains();
1878   HeapTests().NowContains();
1879 }
1880 
1881 
TEST(Maybe)1882 TEST(Maybe) {
1883   CcTest::InitializeVM();
1884   ZoneTests().Maybe();
1885   HeapTests().Maybe();
1886 }
1887 
1888 
TEST(Union1)1889 TEST(Union1) {
1890   CcTest::InitializeVM();
1891   ZoneTests().Union1();
1892   HeapTests().Union1();
1893 }
1894 
1895 
TEST(Union2)1896 TEST(Union2) {
1897   CcTest::InitializeVM();
1898   ZoneTests().Union2();
1899   HeapTests().Union2();
1900 }
1901 
1902 
TEST(Intersect1)1903 TEST(Intersect1) {
1904   CcTest::InitializeVM();
1905   ZoneTests().Intersect1();
1906   HeapTests().Intersect1();
1907 }
1908 
1909 
TEST(Intersect2)1910 TEST(Intersect2) {
1911   CcTest::InitializeVM();
1912   ZoneTests().Intersect2();
1913   HeapTests().Intersect2();
1914 }
1915 
1916 
TEST(Distributivity1)1917 TEST(Distributivity1) {
1918   CcTest::InitializeVM();
1919   ZoneTests().Distributivity1();
1920   HeapTests().Distributivity1();
1921 }
1922 
1923 
TEST(Distributivity2)1924 TEST(Distributivity2) {
1925   CcTest::InitializeVM();
1926   ZoneTests().Distributivity2();
1927   HeapTests().Distributivity2();
1928 }
1929 
1930 
TEST(Convert)1931 TEST(Convert) {
1932   CcTest::InitializeVM();
1933   ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>();
1934   HeapTests().Convert<Type, Type*, Zone, ZoneRep>();
1935 }
1936 
1937 
TEST(HTypeFromType)1938 TEST(HTypeFromType) {
1939   CcTest::InitializeVM();
1940   ZoneTests().HTypeFromType();
1941   HeapTests().HTypeFromType();
1942 }
1943