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