test-types.cc 39.5 KB
Newer Older
1
// Copyright 2013 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include <vector>
6

7
#include "src/compiler/types.h"
8
#include "src/heap/factory-inl.h"
9 10
#include "src/heap/heap.h"
#include "src/isolate.h"
11
#include "src/objects.h"
12
#include "test/cctest/cctest.h"
13
#include "test/common/types-fuzz.h"
14

15 16 17
namespace v8 {
namespace internal {
namespace compiler {
18

bmeurer's avatar
bmeurer committed
19
namespace {
20

21
// Testing auxiliaries (breaking the Type abstraction).
22 23 24 25 26 27


static bool IsInteger(double x) {
  return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
}

28 29
typedef uint32_t bitset;

30 31 32
struct Tests {
  typedef Types::TypeVector::iterator TypeIterator;
  typedef Types::ValueVector::iterator ValueIterator;
33

34 35
  Isolate* isolate;
  HandleScope scope;
36
  CanonicalHandleScope canonical;
37
  Zone zone;
38
  Types T;
39

40
  Tests()
41
      : isolate(CcTest::InitIsolateOnce()),
42
        scope(isolate),
43
        canonical(isolate),
44
        zone(isolate->allocator(), ZONE_NAME),
45 46
        T(&zone, isolate, isolate->random_number_generator()) {}

47 48 49 50
  bool IsBitset(Type type) { return type.IsBitset(); }
  bool IsUnion(Type type) { return type.IsUnionForTesting(); }
  BitsetType::bitset AsBitset(Type type) { return type.AsBitsetForTesting(); }
  const UnionType* AsUnion(Type type) { return type.AsUnionForTesting(); }
51

52
  bool Equal(Type type1, Type type2) {
53
    return type1.Equals(type2) &&
54 55
           this->IsBitset(type1) == this->IsBitset(type2) &&
           this->IsUnion(type1) == this->IsUnion(type2) &&
56
           type1.NumConstants() == type2.NumConstants() &&
57 58 59 60 61
           (!this->IsBitset(type1) ||
            this->AsBitset(type1) == this->AsBitset(type2)) &&
           (!this->IsUnion(type1) ||
            this->AsUnion(type1)->LengthForTesting() ==
                this->AsUnion(type2)->LengthForTesting());
62 63
  }

64
  void CheckEqual(Type type1, Type type2) { CHECK(Equal(type1, type2)); }
65

66
  void CheckSub(Type type1, Type type2) {
67 68
    CHECK(type1.Is(type2));
    CHECK(!type2.Is(type1));
69 70
    if (this->IsBitset(type1) && this->IsBitset(type2)) {
      CHECK(this->AsBitset(type1) != this->AsBitset(type2));
71
    }
72
  }
73

74
  void CheckSubOrEqual(Type type1, Type type2) {
75
    CHECK(type1.Is(type2));
76 77 78 79 80 81
    if (this->IsBitset(type1) && this->IsBitset(type2)) {
      CHECK((this->AsBitset(type1) | this->AsBitset(type2))
            == this->AsBitset(type2));
    }
  }

82
  void CheckUnordered(Type type1, Type type2) {
83 84
    CHECK(!type1.Is(type2));
    CHECK(!type2.Is(type1));
85 86
    if (this->IsBitset(type1) && this->IsBitset(type2)) {
      CHECK(this->AsBitset(type1) != this->AsBitset(type2));
87 88
    }
  }
89

90
  void CheckOverlap(Type type1, Type type2) {
91 92
    CHECK(type1.Maybe(type2));
    CHECK(type2.Maybe(type1));
93 94
  }

95
  void CheckDisjoint(Type type1, Type type2) {
96 97 98 99
    CHECK(!type1.Is(type2));
    CHECK(!type2.Is(type1));
    CHECK(!type1.Maybe(type2));
    CHECK(!type2.Maybe(type1));
100 101 102 103
  }

  void IsSomeType() {
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
104
      Type t = *it;
105 106
      CHECK_EQ(1, this->IsBitset(t) + t.IsHeapConstant() + t.IsRange() +
                      t.IsOtherNumberConstant() + this->IsUnion(t));
107
    }
108 109
  }

110
  void Bitset() {
111
    // None and Any are bitsets.
dslomov@chromium.org's avatar
dslomov@chromium.org committed
112 113 114
    CHECK(this->IsBitset(T.None));
    CHECK(this->IsBitset(T.Any));

115
    CHECK(bitset(0) == this->AsBitset(T.None));
116
    CHECK(bitset(0xFFFFFFFEu) == this->AsBitset(T.Any));
117

118
    // Union(T1, T2) is bitset for bitsets T1,T2
119 120
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
121 122 123
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
124
        CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
125
              this->IsBitset(union12));
126 127 128
      }
    }

129
    // Intersect(T1, T2) is bitset for bitsets T1,T2
130 131
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
132 133 134
        Type type1 = *it1;
        Type type2 = *it2;
        Type intersect12 = T.Intersect(type1, type2);
135 136 137 138 139
        CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
              this->IsBitset(intersect12));
      }
    }

140
    // Union(T1, T2) is bitset if T2 is bitset and T1.Is(T2)
141 142
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
143 144 145
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
146
        CHECK(!(this->IsBitset(type2) && type1.Is(type2)) ||
147
              this->IsBitset(union12));
148 149 150
      }
    }

151
    // Union(T1, T2) is bitwise disjunction for bitsets T1,T2
152 153
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
154 155 156
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
157
        if (this->IsBitset(type1) && this->IsBitset(type2)) {
158 159
          CHECK(
              (this->AsBitset(type1) | this->AsBitset(type2)) ==
160
              this->AsBitset(union12));
161 162 163 164
        }
      }
    }

165
    // Intersect(T1, T2) is bitwise conjunction for bitsets T1,T2 (modulo None)
166 167
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
168 169
        Type type1 = *it1;
        Type type2 = *it2;
170
        if (this->IsBitset(type1) && this->IsBitset(type2)) {
171
          Type intersect12 = T.Intersect(type1, type2);
172
          bitset bits = this->AsBitset(type1) & this->AsBitset(type2);
173
          CHECK(bits == this->AsBitset(intersect12));
174 175 176
        }
      }
    }
177 178
  }

179
  void Constant() {
180 181 182
    // Constructor
    for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
      Handle<i::Object> value = *vt;
183
      Type type = T.NewConstant(value);
184 185
      CHECK(type.IsHeapConstant() || type.IsOtherNumberConstant() ||
            type.IsRange());
186
    }
dslomov@chromium.org's avatar
dslomov@chromium.org committed
187

188 189 190
    // Value attribute
    for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
      Handle<i::Object> value = *vt;
191
      Type type = T.NewConstant(value);
192 193 194
      if (type.IsHeapConstant()) {
        CHECK(value.address() == type.AsHeapConstant()->Value().address());
      } else if (type.IsOtherNumberConstant()) {
195
        CHECK(value->IsHeapNumber());
196
        CHECK(value->Number() == type.AsOtherNumberConstant()->Value());
197
      } else {
198
        CHECK(type.IsRange());
199
        double v = value->Number();
200
        CHECK(v == type.AsRange()->Min() && v == type.AsRange()->Max());
201
      }
202 203
    }

204
    // Functionality & Injectivity: Constant(V1) = Constant(V2) iff V1 = V2
205 206
    for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
      for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
207 208
        Handle<i::Object> value1 = *vt1;
        Handle<i::Object> value2 = *vt2;
209 210
        Type type1 = T.NewConstant(value1);
        Type type2 = T.NewConstant(value2);
211
        if (type1.IsOtherNumberConstant() && type2.IsOtherNumberConstant()) {
212
          CHECK(Equal(type1, type2) ==
213 214 215
                (type1.AsOtherNumberConstant()->Value() ==
                 type2.AsOtherNumberConstant()->Value()));
        } else if (type1.IsRange() && type2.IsRange()) {
216
          CHECK(Equal(type1, type2) ==
217 218
                ((type1.AsRange()->Min() == type2.AsRange()->Min()) &&
                 (type1.AsRange()->Max() == type2.AsRange()->Max())));
219 220 221
        } else {
          CHECK(Equal(type1, type2) == (*value1 == *value2));
        }
222 223
      }
    }
224 225 226

    // Typing of numbers
    Factory* fac = isolate->factory();
227 228 229 230 231 232 233 234 235 236 237 238 239 240
    CHECK(T.NewConstant(fac->NewNumber(0)).Is(T.UnsignedSmall));
    CHECK(T.NewConstant(fac->NewNumber(1)).Is(T.UnsignedSmall));
    CHECK(T.NewConstant(fac->NewNumber(0x3FFFFFFF)).Is(T.UnsignedSmall));
    CHECK(T.NewConstant(fac->NewNumber(-1)).Is(T.Negative31));
    CHECK(T.NewConstant(fac->NewNumber(-0x3FFFFFFF)).Is(T.Negative31));
    CHECK(T.NewConstant(fac->NewNumber(-0x40000000)).Is(T.Negative31));
    CHECK(T.NewConstant(fac->NewNumber(0x40000000)).Is(T.Unsigned31));
    CHECK(!T.NewConstant(fac->NewNumber(0x40000000)).Is(T.Unsigned30));
    CHECK(T.NewConstant(fac->NewNumber(0x7FFFFFFF)).Is(T.Unsigned31));
    CHECK(!T.NewConstant(fac->NewNumber(0x7FFFFFFF)).Is(T.Unsigned30));
    CHECK(T.NewConstant(fac->NewNumber(-0x40000001)).Is(T.Negative32));
    CHECK(!T.NewConstant(fac->NewNumber(-0x40000001)).Is(T.Negative31));
    CHECK(T.NewConstant(fac->NewNumber(-0x7FFFFFFF)).Is(T.Negative32));
    CHECK(!T.NewConstant(fac->NewNumber(-0x7FFFFFFF - 1)).Is(T.Negative31));
241
    if (SmiValuesAre31Bits()) {
242 243 244 245
      CHECK(!T.NewConstant(fac->NewNumber(0x40000000)).Is(T.UnsignedSmall));
      CHECK(!T.NewConstant(fac->NewNumber(0x7FFFFFFF)).Is(T.UnsignedSmall));
      CHECK(!T.NewConstant(fac->NewNumber(-0x40000001)).Is(T.SignedSmall));
      CHECK(!T.NewConstant(fac->NewNumber(-0x7FFFFFFF - 1)).Is(T.SignedSmall));
246 247
    } else {
      CHECK(SmiValuesAre32Bits());
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      CHECK(T.NewConstant(fac->NewNumber(0x40000000)).Is(T.UnsignedSmall));
      CHECK(T.NewConstant(fac->NewNumber(0x7FFFFFFF)).Is(T.UnsignedSmall));
      CHECK(T.NewConstant(fac->NewNumber(-0x40000001)).Is(T.SignedSmall));
      CHECK(T.NewConstant(fac->NewNumber(-0x7FFFFFFF - 1)).Is(T.SignedSmall));
    }
    CHECK(T.NewConstant(fac->NewNumber(0x80000000u)).Is(T.Unsigned32));
    CHECK(!T.NewConstant(fac->NewNumber(0x80000000u)).Is(T.Unsigned31));
    CHECK(T.NewConstant(fac->NewNumber(0xFFFFFFFFu)).Is(T.Unsigned32));
    CHECK(!T.NewConstant(fac->NewNumber(0xFFFFFFFFu)).Is(T.Unsigned31));
    CHECK(T.NewConstant(fac->NewNumber(0xFFFFFFFFu + 1.0)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(0xFFFFFFFFu + 1.0)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(-0x7FFFFFFF - 2.0)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(-0x7FFFFFFF - 2.0)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(0.1)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(0.1)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(-10.1)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(-10.1)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(10e60)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(10e60)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(-1.0 * 0.0)).Is(T.MinusZero));
268 269
    CHECK(
        T.NewConstant(fac->NewNumber(std::numeric_limits<double>::quiet_NaN()))
270 271 272 273 274
            .Is(T.NaN));
    CHECK(T.NewConstant(fac->NewNumber(V8_INFINITY)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(V8_INFINITY)).Is(T.Integral32));
    CHECK(T.NewConstant(fac->NewNumber(-V8_INFINITY)).Is(T.PlainNumber));
    CHECK(!T.NewConstant(fac->NewNumber(-V8_INFINITY)).Is(T.Integral32));
275 276 277

    // Typing of Strings
    Handle<String> s1 = fac->NewStringFromAsciiChecked("a");
278
    CHECK(T.NewConstant(s1).Is(T.InternalizedString));
279 280 281
    const uc16 two_byte[1] = {0x2603};
    Handle<String> s2 =
        fac->NewTwoByteInternalizedString(Vector<const uc16>(two_byte, 1), 1);
282
    CHECK(T.NewConstant(s2).Is(T.InternalizedString));
283 284
  }

285 286
  void Range() {
    // Constructor
287 288
    for (ValueIterator i = T.integers.begin(); i != T.integers.end(); ++i) {
      for (ValueIterator j = T.integers.begin(); j != T.integers.end(); ++j) {
289 290 291
        double min = (*i)->Number();
        double max = (*j)->Number();
        if (min > max) std::swap(min, max);
292
        Type type = T.Range(min, max);
293
        CHECK(type.IsRange());
294 295 296 297
      }
    }

    // Range attributes
298 299
    for (ValueIterator i = T.integers.begin(); i != T.integers.end(); ++i) {
      for (ValueIterator j = T.integers.begin(); j != T.integers.end(); ++j) {
300 301 302
        double min = (*i)->Number();
        double max = (*j)->Number();
        if (min > max) std::swap(min, max);
303
        Type type = T.Range(min, max);
304 305
        CHECK(min == type.AsRange()->Min());
        CHECK(max == type.AsRange()->Max());
306 307 308 309 310 311 312
      }
    }

    // Functionality & Injectivity:
    // Range(min1, max1) = Range(min2, max2) <=> min1 = min2 /\ max1 = max2
    for (ValueIterator i1 = T.integers.begin();
        i1 != T.integers.end(); ++i1) {
313
      for (ValueIterator j1 = i1;
314 315 316
          j1 != T.integers.end(); ++j1) {
        for (ValueIterator i2 = T.integers.begin();
            i2 != T.integers.end(); ++i2) {
317
          for (ValueIterator j2 = i2;
318
              j2 != T.integers.end(); ++j2) {
319 320 321 322 323 324
            double min1 = (*i1)->Number();
            double max1 = (*j1)->Number();
            double min2 = (*i2)->Number();
            double max2 = (*j2)->Number();
            if (min1 > max1) std::swap(min1, max1);
            if (min2 > max2) std::swap(min2, max2);
325 326
            Type type1 = T.Range(min1, max1);
            Type type2 = T.Range(min2, max2);
327
            CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2));
328 329 330 331
          }
        }
      }
    }
332 333
  }

334
  void MinMax() {
335
    // If b is regular numeric bitset, then Range(b.Min(), b.Max()).Is(b).
336 337 338
    // TODO(neis): Need to ignore representation for this to be true.
    /*
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
339
      Type type = *it;
340 341
      if (this->IsBitset(type) && type.Is(T.Number) &&
          !type.Is(T.None) && !type.Is(T.NaN)) {
342
        Type range = T.Range(
343 344 345
            isolate->factory()->NewNumber(type.Min()),
            isolate->factory()->NewNumber(type.Max()));
        CHECK(range.Is(type));
346 347 348 349
      }
    }
    */

350
    // If b is regular numeric bitset, then b.Min() and b.Max() are integers.
351
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
352
      Type type = *it;
353 354
      if (this->IsBitset(type) && type.Is(T.Number) && !type.Is(T.NaN)) {
        CHECK(IsInteger(type.Min()) && IsInteger(type.Max()));
355 356 357
      }
    }

358 359
    // If b1 and b2 are regular numeric bitsets with b1.Is(b2), then
    // b1.Min() >= b2.Min() and b1.Max() <= b2.Max().
360 361
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
362 363
        Type type1 = *it1;
        Type type2 = *it2;
364 365 366 367
        if (this->IsBitset(type1) && type1.Is(type2) && type2.Is(T.Number) &&
            !type1.Is(T.NaN) && !type2.Is(T.NaN)) {
          CHECK(type1.Min() >= type2.Min());
          CHECK(type1.Max() <= type2.Max());
368 369 370 371
        }
      }
    }

372
    // Lub(Range(x,y)).Min() <= x and y <= Lub(Range(x,y)).Max()
373
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
374
      Type type = *it;
375 376 377
      if (type.IsRange()) {
        Type lub = type.BitsetLubForTesting();
        CHECK(lub.Min() <= type.Min() && type.Max() <= lub.Max());
378 379
      }
    }
380

381 382
    // Rangification: If T.Is(Range(-inf,+inf)) and T is inhabited, then
    // T.Is(Range(T.Min(), T.Max())).
383
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
384
      Type type = *it;
385 386
      CHECK(!type.Is(T.Integer) || type.IsNone() ||
            type.Is(T.Range(type.Min(), type.Max())));
387
    }
388 389
  }

390
  void BitsetGlb() {
391
    // Lower: (T->BitsetGlb()).Is(T)
392
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
393
      Type type = *it;
394 395
      Type glb = type.BitsetGlbForTesting();
      CHECK(glb.Is(type));
396 397
    }

398
    // Greatest: If T1.IsBitset() and T1.Is(T2), then T1.Is(T2->BitsetGlb())
399 400
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
401 402
        Type type1 = *it1;
        Type type2 = *it2;
403 404
        Type glb2 = type2.BitsetGlbForTesting();
        CHECK(!this->IsBitset(type1) || !type1.Is(type2) || type1.Is(glb2));
405 406 407
      }
    }

408
    // Monotonicity: T1.Is(T2) implies (T1->BitsetGlb()).Is(T2->BitsetGlb())
409 410
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
411 412
        Type type1 = *it1;
        Type type2 = *it2;
413 414 415
        Type glb1 = type1.BitsetGlbForTesting();
        Type glb2 = type2.BitsetGlbForTesting();
        CHECK(!type1.Is(type2) || glb1.Is(glb2));
416
      }
417
    }
418
  }
419

420
  void BitsetLub() {
421
    // Upper: T.Is(T->BitsetLub())
422
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
423
      Type type = *it;
424 425
      Type lub = type.BitsetLubForTesting();
      CHECK(type.Is(lub));
426 427
    }

428
    // Least: If T2.IsBitset() and T1.Is(T2), then (T1->BitsetLub()).Is(T2)
429 430
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
431 432
        Type type1 = *it1;
        Type type2 = *it2;
433 434
        Type lub1 = type1.BitsetLubForTesting();
        CHECK(!this->IsBitset(type2) || !type1.Is(type2) || lub1.Is(type2));
435 436 437
      }
    }

438
    // Monotonicity: T1.Is(T2) implies (T1->BitsetLub()).Is(T2->BitsetLub())
439 440
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
441 442
        Type type1 = *it1;
        Type type2 = *it2;
443 444 445
        Type lub1 = type1.BitsetLubForTesting();
        Type lub2 = type2.BitsetLubForTesting();
        CHECK(!type1.Is(type2) || lub1.Is(lub2));
446
      }
447 448 449
    }
  }

450
  void Is1() {
451
    // Least Element (Bottom): None.Is(T)
452
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
453
      Type type = *it;
454
      CHECK(T.None.Is(type));
455 456
    }

457
    // Greatest Element (Top): T.Is(Any)
458
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
459
      Type type = *it;
460
      CHECK(type.Is(T.Any));
461 462
    }

463
    // Bottom Uniqueness: T.Is(None) implies T = None
464
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
465
      Type type = *it;
466
      if (type.Is(T.None)) CheckEqual(type, T.None);
467 468
    }

469
    // Top Uniqueness: Any.Is(T) implies T = Any
470
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
471
      Type type = *it;
472
      if (T.Any.Is(type)) CheckEqual(type, T.Any);
473 474
    }

475
    // Reflexivity: T.Is(T)
476
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
477
      Type type = *it;
478
      CHECK(type.Is(type));
479
    }
480

481
    // Transitivity: T1.Is(T2) and T2.Is(T3) implies T1.Is(T3)
482 483 484
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
485 486 487
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
488
          CHECK(!(type1.Is(type2) && type2.Is(type3)) || type1.Is(type3));
489 490 491
        }
      }
    }
492

493
    // Antisymmetry: T1.Is(T2) and T2.Is(T1) iff T1 = T2
494 495
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
496 497
        Type type1 = *it1;
        Type type2 = *it2;
498
        CHECK((type1.Is(type2) && type2.Is(type1)) == Equal(type1, type2));
499 500 501
      }
    }

502 503 504
    // (In-)Compatibilities.
    for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
      for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
505 506
        Type type1 = *i;
        Type type2 = *j;
507 508 509 510 511 512 513 514
        CHECK(
            !type1.Is(type2) || this->IsBitset(type2) || this->IsUnion(type2) ||
            this->IsUnion(type1) ||
            (type1.IsHeapConstant() && type2.IsHeapConstant()) ||
            (this->IsBitset(type1) && type2.IsRange()) ||
            (type1.IsRange() && type2.IsRange()) ||
            (type1.IsOtherNumberConstant() && type2.IsOtherNumberConstant()) ||
            type1.IsNone());
515 516 517 518 519
      }
    }
  }

  void Is2() {
520
    // Range(X1, Y1).Is(Range(X2, Y2)) iff X1 >= X2 /\ Y1 <= Y2
521 522
    for (ValueIterator i1 = T.integers.begin();
        i1 != T.integers.end(); ++i1) {
523
      for (ValueIterator j1 = i1;
524 525 526
          j1 != T.integers.end(); ++j1) {
        for (ValueIterator i2 = T.integers.begin();
             i2 != T.integers.end(); ++i2) {
527
          for (ValueIterator j2 = i2;
528
               j2 != T.integers.end(); ++j2) {
529 530 531 532 533 534
            double min1 = (*i1)->Number();
            double max1 = (*j1)->Number();
            double min2 = (*i2)->Number();
            double max2 = (*j2)->Number();
            if (min1 > max1) std::swap(min1, max1);
            if (min2 > max2) std::swap(min2, max2);
535 536
            Type type1 = T.Range(min1, max1);
            Type type2 = T.Range(min2, max2);
537
            CHECK(type1.Is(type2) == (min1 >= min2 && max1 <= max2));
538 539
          }
        }
540 541 542
      }
    }

543
    // Constant(V1).Is(Constant(V2)) iff V1 = V2
544 545 546 547
    for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
      for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
        Handle<i::Object> value1 = *vt1;
        Handle<i::Object> value2 = *vt2;
548 549
        Type const_type1 = T.NewConstant(value1);
        Type const_type2 = T.NewConstant(value2);
550 551 552 553 554 555 556 557 558 559
        if (const_type1.IsOtherNumberConstant() &&
            const_type2.IsOtherNumberConstant()) {
          CHECK(const_type1.Is(const_type2) ==
                (const_type1.AsOtherNumberConstant()->Value() ==
                 const_type2.AsOtherNumberConstant()->Value()));
        } else if (const_type1.IsRange() && const_type2.IsRange()) {
          CHECK(
              Equal(const_type1, const_type2) ==
              ((const_type1.AsRange()->Min() == const_type2.AsRange()->Min()) &&
               (const_type1.AsRange()->Max() == const_type2.AsRange()->Max())));
560
        } else {
561
          CHECK(const_type1.Is(const_type2) == (*value1 == *value2));
562
        }
563 564 565 566 567
      }
    }

    // Range-specific subtyping

568
    // Lub(Range(x,y)).Is(T.Union(T.Integral32, T.OtherNumber))
569
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
570
      Type type = *it;
571 572 573
      if (type.IsRange()) {
        Type lub = type.BitsetLubForTesting();
        CHECK(lub.Is(T.PlainNumber));
574 575 576 577 578 579
      }
    }


    // Subtyping between concrete basic types

580 581 582 583
    CheckUnordered(T.Boolean, T.Null);
    CheckUnordered(T.Undefined, T.Null);
    CheckUnordered(T.Boolean, T.Undefined);

584
    CheckSub(T.SignedSmall, T.Number);
585
    CheckSub(T.Signed32, T.Number);
586
    CheckSubOrEqual(T.SignedSmall, T.Signed32);
587 588
    CheckUnordered(T.SignedSmall, T.MinusZero);
    CheckUnordered(T.Signed32, T.Unsigned32);
589 590 591 592 593 594 595 596 597 598 599 600 601 602

    CheckSub(T.UniqueName, T.Name);
    CheckSub(T.String, T.Name);
    CheckSub(T.InternalizedString, T.String);
    CheckSub(T.InternalizedString, T.UniqueName);
    CheckSub(T.InternalizedString, T.Name);
    CheckSub(T.Symbol, T.UniqueName);
    CheckSub(T.Symbol, T.Name);
    CheckUnordered(T.String, T.UniqueName);
    CheckUnordered(T.String, T.Symbol);
    CheckUnordered(T.InternalizedString, T.Symbol);

    CheckSub(T.Object, T.Receiver);
    CheckSub(T.Proxy, T.Receiver);
603
    CheckSub(T.Array, T.Object);
604
    CheckSub(T.OtherObject, T.Object);
605
    CheckSub(T.OtherUndetectable, T.Object);
606

607
    CheckUnordered(T.Object, T.Proxy);
608
    CheckUnordered(T.Array, T.Undetectable);
609
    CheckUnordered(T.OtherObject, T.Undetectable);
610 611 612

    // Subtyping between concrete structural types

613
    CheckSub(T.SmiConstant, T.SignedSmall);
614 615 616 617
    CheckSub(T.SmiConstant, T.Signed32);
    CheckSub(T.SmiConstant, T.Number);
    CheckSub(T.ObjectConstant1, T.Object);
    CheckSub(T.ObjectConstant2, T.Object);
618
    CheckSub(T.ArrayConstant, T.Object);
619
    CheckSub(T.ArrayConstant, T.Array);
620
    CheckSub(T.ArrayConstant, T.Receiver);
621
    CheckSub(T.UninitializedConstant, T.Internal);
622
    CheckUnordered(T.ObjectConstant1, T.ObjectConstant2);
623
    CheckUnordered(T.ObjectConstant1, T.ArrayConstant);
624 625
    CheckUnordered(T.UninitializedConstant, T.Null);
    CheckUnordered(T.UninitializedConstant, T.Undefined);
626
  }
627

628
  void Maybe() {
629
    // T.Maybe(Any) iff T inhabited
630
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
631
      Type type = *it;
632
      CHECK(type.Maybe(T.Any) == !type.IsNone());
633 634
    }

635
    // T.Maybe(None) never
636
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
637
      Type type = *it;
638
      CHECK(!type.Maybe(T.None));
639 640
    }

641
    // Reflexivity upto Inhabitation: T.Maybe(T) iff T inhabited
642
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
643
      Type type = *it;
644
      CHECK(type.Maybe(type) == !type.IsNone());
645 646
    }

647
    // Symmetry: T1.Maybe(T2) iff T2.Maybe(T1)
648 649
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
650 651
        Type type1 = *it1;
        Type type2 = *it2;
652
        CHECK(type1.Maybe(type2) == type2.Maybe(type1));
653 654 655
      }
    }

656
    // T1.Maybe(T2) implies T1, T2 inhabited
657 658
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
659 660
        Type type1 = *it1;
        Type type2 = *it2;
661
        CHECK(!type1.Maybe(type2) || (!type1.IsNone() && !type2.IsNone()));
662 663 664
      }
    }

665
    // T1.Maybe(T2) implies Intersect(T1, T2) inhabited
666 667
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
668 669 670
        Type type1 = *it1;
        Type type2 = *it2;
        Type intersect12 = T.Intersect(type1, type2);
671
        CHECK(!type1.Maybe(type2) || !intersect12.IsNone());
672 673 674
      }
    }

675
    // T1.Is(T2) and T1 inhabited implies T1.Maybe(T2)
676 677
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
678 679
        Type type1 = *it1;
        Type type2 = *it2;
680
        CHECK(!(type1.Is(type2) && !type1.IsNone()) || type1.Maybe(type2));
681 682 683
      }
    }

684
    // Constant(V1).Maybe(Constant(V2)) iff V1 = V2
685 686
    for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
      for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
687 688
        Handle<i::Object> value1 = *vt1;
        Handle<i::Object> value2 = *vt2;
689 690
        Type const_type1 = T.NewConstant(value1);
        Type const_type2 = T.NewConstant(value2);
691 692 693 694 695 696 697 698 699 700
        if (const_type1.IsOtherNumberConstant() &&
            const_type2.IsOtherNumberConstant()) {
          CHECK(const_type1.Maybe(const_type2) ==
                (const_type1.AsOtherNumberConstant()->Value() ==
                 const_type2.AsOtherNumberConstant()->Value()));
        } else if (const_type1.IsRange() && const_type2.IsRange()) {
          CHECK(
              Equal(const_type1, const_type2) ==
              ((const_type1.AsRange()->Min() == const_type2.AsRange()->Min()) &&
               (const_type1.AsRange()->Max() == const_type2.AsRange()->Max())));
701
        } else {
702
          CHECK(const_type1.Maybe(const_type2) == (*value1 == *value2));
703
        }
704 705
      }
    }
706

707
    // Basic types
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
    CheckDisjoint(T.Boolean, T.Null);
    CheckDisjoint(T.Undefined, T.Null);
    CheckDisjoint(T.Boolean, T.Undefined);
    CheckOverlap(T.SignedSmall, T.Number);
    CheckOverlap(T.NaN, T.Number);
    CheckDisjoint(T.Signed32, T.NaN);
    CheckOverlap(T.UniqueName, T.Name);
    CheckOverlap(T.String, T.Name);
    CheckOverlap(T.InternalizedString, T.String);
    CheckOverlap(T.InternalizedString, T.UniqueName);
    CheckOverlap(T.InternalizedString, T.Name);
    CheckOverlap(T.Symbol, T.UniqueName);
    CheckOverlap(T.Symbol, T.Name);
    CheckOverlap(T.String, T.UniqueName);
    CheckDisjoint(T.String, T.Symbol);
    CheckDisjoint(T.InternalizedString, T.Symbol);
    CheckOverlap(T.Object, T.Receiver);
725
    CheckOverlap(T.OtherObject, T.Object);
726 727
    CheckOverlap(T.Proxy, T.Receiver);
    CheckDisjoint(T.Object, T.Proxy);
728

729
    // Structural types
730 731 732 733 734 735
    CheckOverlap(T.SmiConstant, T.SignedSmall);
    CheckOverlap(T.SmiConstant, T.Signed32);
    CheckOverlap(T.SmiConstant, T.Number);
    CheckOverlap(T.ObjectConstant1, T.Object);
    CheckOverlap(T.ObjectConstant2, T.Object);
    CheckOverlap(T.ArrayConstant, T.Object);
736
    CheckOverlap(T.ArrayConstant, T.Receiver);
737 738 739
    CheckOverlap(T.ObjectConstant1, T.ObjectConstant1);
    CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2);
    CheckDisjoint(T.ObjectConstant1, T.ArrayConstant);
740
  }
741

742
  void Union1() {
743 744
    // Identity: Union(T, None) = T
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
745 746
      Type type = *it;
      Type union_type = T.Union(type, T.None);
747 748 749 750 751
      CheckEqual(union_type, type);
    }

    // Domination: Union(T, Any) = Any
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
752 753
      Type type = *it;
      Type union_type = T.Union(type, T.Any);
754 755 756 757 758
      CheckEqual(union_type, T.Any);
    }

    // Idempotence: Union(T, T) = T
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
759 760
      Type type = *it;
      Type union_type = T.Union(type, type);
761 762
      CheckEqual(union_type, type);
    }
763

764 765 766
    // Commutativity: Union(T1, T2) = Union(T2, T1)
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
767 768 769 770
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
        Type union21 = T.Union(type2, type1);
771 772 773 774 775
        CheckEqual(union12, union21);
      }
    }

    // Associativity: Union(T1, Union(T2, T3)) = Union(Union(T1, T2), T3)
776 777 778
    // This does NOT hold!  For example:
    // (Unsigned32 \/ Range(0,5)) \/ Range(-5,0) = Unsigned32 \/ Range(-5,0)
    // Unsigned32 \/ (Range(0,5) \/ Range(-5,0)) = Unsigned32 \/ Range(-5,5)
779
    /*
780 781 782
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
783 784 785 786 787 788 789
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type union12 = T.Union(type1, type2);
          Type union23 = T.Union(type2, type3);
          Type union1_23 = T.Union(type1, union23);
          Type union12_3 = T.Union(union12, type3);
790 791 792 793
          CheckEqual(union1_23, union12_3);
        }
      }
    }
794
    */
795

796
    // Meet: T1.Is(Union(T1, T2)) and T2.Is(Union(T1, T2))
797 798
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
799 800 801
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
802 803
        CHECK(type1.Is(union12));
        CHECK(type2.Is(union12));
804 805 806
      }
    }

807
    // Upper Boundedness: T1.Is(T2) implies Union(T1, T2) = T2
808 809
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
810 811 812
        Type type1 = *it1;
        Type type2 = *it2;
        Type union12 = T.Union(type1, type2);
813
        if (type1.Is(type2)) CheckEqual(union12, type2);
814 815 816
      }
    }

817
    // Monotonicity: T1.Is(T2) implies Union(T1, T3).Is(Union(T2, T3))
818 819 820
    // This does NOT hold.  For example:
    // Range(-5,-1) <= Signed32
    // Range(-5,-1) \/ Range(1,5) = Range(-5,5) </= Signed32 \/ Range(1,5)
821
    /*
822 823 824
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
825 826 827 828 829
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type union13 = T.Union(type1, type3);
          Type union23 = T.Union(type2, type3);
830
          CHECK(!type1.Is(type2) || union13.Is(union23));
831 832 833
        }
      }
    }
834 835
    */
  }
836

837
  void Union2() {
838
    // Monotonicity: T1.Is(T3) and T2.Is(T3) implies Union(T1, T2).Is(T3)
839 840 841 842
    // This does NOT hold.  For example:
    // Range(-2^33, -2^33) <= OtherNumber
    // Range(2^33, 2^33) <= OtherNumber
    // Range(-2^33, 2^33) </= OtherNumber
843
    /*
844 845 846
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
847 848 849 850
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type union12 = T.Union(type1, type2);
851
          CHECK(!(type1.Is(type3) && type2.Is(type3)) || union12.Is(type3));
852 853 854
        }
      }
    }
855 856
    */
  }
857

858
  void Union3() {
859
    // Monotonicity: T1.Is(T2) or T1.Is(T3) implies T1.Is(Union(T2, T3))
860
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
861
      HandleScope scope(isolate);
862
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
863
        for (TypeIterator it3 = it2; it3 != T.types.end(); ++it3) {
864 865 866 867
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type union23 = T.Union(type2, type3);
868
          CHECK(!(type1.Is(type2) || type1.Is(type3)) || type1.Is(union23));
869 870 871
        }
      }
    }
872
  }
873

874
  void Union4() {
875 876
    // Constant-constant
    CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object);
877 878
    CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant), T.OtherObject);
    CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant), T.OtherObject);
879
    CheckDisjoint(
880
        T.Union(T.ObjectConstant1, T.ArrayConstant), T.Number);
881 882 883 884

    // Bitset-constant
    CheckSub(
        T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
885 886
    CheckSub(T.Union(T.ObjectConstant1, T.OtherObject), T.Object);
    CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.OtherObject);
887 888
    CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
    CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number);
889 890 891 892 893 894 895 896

    // Constant-union
    CheckEqual(
        T.Union(
            T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
        T.Union(T.ObjectConstant2, T.ObjectConstant1));
    CheckEqual(
        T.Union(
897
            T.Union(T.ArrayConstant, T.ObjectConstant2), T.ObjectConstant1),
898
        T.Union(
899
            T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
900 901 902 903 904 905 906

    // Union-union
    CheckEqual(
        T.Union(
            T.Union(T.ObjectConstant2, T.ObjectConstant1),
            T.Union(T.ObjectConstant1, T.ObjectConstant2)),
        T.Union(T.ObjectConstant2, T.ObjectConstant1));
907
  }
908

909
  void Intersect() {
910 911
    // Identity: Intersect(T, Any) = T
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
912 913
      Type type = *it;
      Type intersect_type = T.Intersect(type, T.Any);
914 915
      CheckEqual(intersect_type, type);
    }
916

917 918
    // Domination: Intersect(T, None) = None
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
919 920
      Type type = *it;
      Type intersect_type = T.Intersect(type, T.None);
921 922
      CheckEqual(intersect_type, T.None);
    }
923

924 925
    // Idempotence: Intersect(T, T) = T
    for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
926 927
      Type type = *it;
      Type intersect_type = T.Intersect(type, type);
928 929
      CheckEqual(intersect_type, type);
    }
930

931 932 933
    // Commutativity: Intersect(T1, T2) = Intersect(T2, T1)
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
934 935 936 937
        Type type1 = *it1;
        Type type2 = *it2;
        Type intersect12 = T.Intersect(type1, type2);
        Type intersect21 = T.Intersect(type2, type1);
938 939 940
        CheckEqual(intersect12, intersect21);
      }
    }
941

942
    // Lower Boundedness: T1.Is(T2) implies Intersect(T1, T2) = T1
943 944
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
945 946 947
        Type type1 = *it1;
        Type type2 = *it2;
        Type intersect12 = T.Intersect(type1, type2);
948
        if (type1.Is(type2)) CheckEqual(intersect12, type1);
949 950 951
      }
    }

952
    // Monotonicity: T1.Is(T2) and T1.Is(T3) implies T1.Is(Intersect(T2, T3))
953
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
954
      HandleScope scope(isolate);
955 956
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
957 958 959 960
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type intersect23 = T.Intersect(type2, type3);
961
          CHECK(!(type1.Is(type2) && type1.Is(type3)) || type1.Is(intersect23));
962 963 964 965
        }
      }
    }

966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
    // Constant-union
    CheckEqual(
        T.Intersect(
            T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
        T.ObjectConstant1);
    CheckEqual(
        T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)),
        T.SmiConstant);

    // Union-union
    CheckEqual(
        T.Intersect(
            T.Union(T.ObjectConstant2, T.ObjectConstant1),
            T.Union(T.ObjectConstant1, T.ObjectConstant2)),
        T.Union(T.ObjectConstant2, T.ObjectConstant1));
  }
982

983
  void Distributivity() {
984
    // Union(T1, Intersect(T2, T3)) = Intersect(Union(T1, T2), Union(T1, T3))
985 986 987 988 989
    // This does NOT hold.  For example:
    // Untagged \/ (Untagged /\ Class(../Tagged)) = Untagged \/ Class(../Tagged)
    // (Untagged \/ Untagged) /\ (Untagged \/ Class(../Tagged)) =
    // Untagged /\ (Untagged \/ Class(../Tagged)) = Untagged
    // because Untagged <= Untagged \/ Class(../Tagged)
990
    /*
991 992 993
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
994 995 996 997 998 999 1000 1001
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type union12 = T.Union(type1, type2);
          Type union13 = T.Union(type1, type3);
          Type intersect23 = T.Intersect(type2, type3);
          Type union1_23 = T.Union(type1, intersect23);
          Type intersect12_13 = T.Intersect(union12, union13);
1002 1003 1004 1005
          CHECK(Equal(union1_23, intersect12_13));
        }
      }
    }
1006
    */
1007 1008

    // Intersect(T1, Union(T2, T3)) = Union(Intersect(T1, T2), Intersect(T1,T3))
1009 1010 1011 1012
    // This does NOT hold.  For example:
    // Untagged /\ (Untagged \/ Class(../Tagged)) = Untagged
    // (Untagged /\ Untagged) \/ (Untagged /\ Class(../Tagged)) =
    // Untagged \/ Class(../Tagged)
1013
    /*
1014 1015 1016
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
      for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
        for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
1017 1018 1019 1020 1021 1022 1023 1024
          Type type1 = *it1;
          Type type2 = *it2;
          Type type3 = *it3;
          Type intersect12 = T.Intersect(type1, type2);
          Type intersect13 = T.Intersect(type1, type3);
          Type union23 = T.Union(type2, type3);
          Type intersect1_23 = T.Intersect(type1, union23);
          Type union12_13 = T.Union(intersect12, intersect13);
1025 1026 1027 1028
          CHECK(Equal(intersect1_23, union12_13));
        }
      }
    }
1029
    */
1030 1031
  }

1032 1033 1034
  void GetRange() {
    // GetRange(Range(a, b)) = Range(a, b).
    for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
1035
      Type type1 = *it1;
1036 1037 1038 1039
      if (type1.IsRange()) {
        const RangeType* range = type1.GetRange().AsRange();
        CHECK(type1.Min() == range->Min());
        CHECK(type1.Max() == range->Max());
1040 1041 1042
      }
    }
  }
1043 1044
};

bmeurer's avatar
bmeurer committed
1045
}  // namespace
1046

bmeurer's avatar
bmeurer committed
1047
TEST(IsSomeType) { Tests().IsSomeType(); }
1048

bmeurer's avatar
bmeurer committed
1049
TEST(BitsetType) { Tests().Bitset(); }
1050

bmeurer's avatar
bmeurer committed
1051
TEST(ConstantType) { Tests().Constant(); }
1052

bmeurer's avatar
bmeurer committed
1053
TEST(RangeType) { Tests().Range(); }
1054

bmeurer's avatar
bmeurer committed
1055
TEST(MinMax) { Tests().MinMax(); }
1056

bmeurer's avatar
bmeurer committed
1057
TEST(BitsetGlb) { Tests().BitsetGlb(); }
1058

bmeurer's avatar
bmeurer committed
1059
TEST(BitsetLub) { Tests().BitsetLub(); }
1060

bmeurer's avatar
bmeurer committed
1061
TEST(Is1) { Tests().Is1(); }
1062

bmeurer's avatar
bmeurer committed
1063
TEST(Is2) { Tests().Is2(); }
1064

bmeurer's avatar
bmeurer committed
1065
TEST(Maybe) { Tests().Maybe(); }
1066

bmeurer's avatar
bmeurer committed
1067
TEST(Union1) { Tests().Union1(); }
1068

bmeurer's avatar
bmeurer committed
1069
TEST(Union2) { Tests().Union2(); }
1070

bmeurer's avatar
bmeurer committed
1071
TEST(Union3) { Tests().Union3(); }
1072

bmeurer's avatar
bmeurer committed
1073
TEST(Union4) { Tests().Union4(); }
1074

bmeurer's avatar
bmeurer committed
1075
TEST(Intersect) { Tests().Intersect(); }
1076

bmeurer's avatar
bmeurer committed
1077
TEST(Distributivity) { Tests().Distributivity(); }
1078

bmeurer's avatar
bmeurer committed
1079
TEST(GetRange) { Tests().GetRange(); }
1080 1081 1082 1083

}  // namespace compiler
}  // namespace internal
}  // namespace v8