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 "cctest.h"
29#include "types.h"
30
31using namespace v8::internal;
32
33// Testing auxiliaries (breaking the Type abstraction).
34static bool IsBitset(Type* type) { return type->IsSmi(); }
35static bool IsClass(Type* type) { return type->IsMap(); }
36static bool IsConstant(Type* type) { return type->IsBox(); }
37static bool IsUnion(Type* type) { return type->IsFixedArray(); }
38
39static int AsBitset(Type* type) { return Smi::cast(type)->value(); }
40static Map* AsClass(Type* type) { return Map::cast(type); }
41static Object* AsConstant(Type* type) { return Box::cast(type)->value(); }
42static FixedArray* AsUnion(Type* type) { return FixedArray::cast(type); }
43
44
45static void CheckEqual(Handle<Type> type1, Handle<Type> type2) {
46  CHECK_EQ(IsBitset(*type1), IsBitset(*type2));
47  CHECK_EQ(IsClass(*type1), IsClass(*type2));
48  CHECK_EQ(IsConstant(*type1), IsConstant(*type2));
49  CHECK_EQ(IsUnion(*type1), IsUnion(*type2));
50  CHECK_EQ(type1->NumClasses(), type2->NumClasses());
51  CHECK_EQ(type1->NumConstants(), type2->NumConstants());
52  if (IsBitset(*type1)) {
53    CHECK_EQ(AsBitset(*type1), AsBitset(*type2));
54  } else if (IsClass(*type1)) {
55    CHECK_EQ(AsClass(*type1), AsClass(*type2));
56  } else if (IsConstant(*type1)) {
57    CHECK_EQ(AsConstant(*type1), AsConstant(*type2));
58  } else if (IsUnion(*type1)) {
59    CHECK_EQ(AsUnion(*type1)->length(), AsUnion(*type2)->length());
60  }
61  CHECK(type1->Is(type2));
62  CHECK(type2->Is(type1));
63}
64
65
66static void CheckSub(Handle<Type> type1, Handle<Type> type2) {
67  CHECK(type1->Is(type2));
68  CHECK(!type2->Is(type1));
69  if (IsBitset(*type1) && IsBitset(*type2)) {
70    CHECK_NE(AsBitset(*type1), AsBitset(*type2));
71  }
72}
73
74
75static void CheckUnordered(Handle<Type> type1, Handle<Type> type2) {
76  CHECK(!type1->Is(type2));
77  CHECK(!type2->Is(type1));
78  if (IsBitset(*type1) && IsBitset(*type2)) {
79    CHECK_NE(AsBitset(*type1), AsBitset(*type2));
80  }
81}
82
83
84static void CheckOverlap(Handle<Type> type1, Handle<Type> type2) {
85  CHECK(type1->Maybe(type2));
86  CHECK(type2->Maybe(type1));
87  if (IsBitset(*type1) && IsBitset(*type2)) {
88    CHECK_NE(0, AsBitset(*type1) & AsBitset(*type2));
89  }
90}
91
92
93static void CheckDisjoint(Handle<Type> type1, Handle<Type> type2) {
94  CHECK(!type1->Is(type2));
95  CHECK(!type2->Is(type1));
96  CHECK(!type1->Maybe(type2));
97  CHECK(!type2->Maybe(type1));
98  if (IsBitset(*type1) && IsBitset(*type2)) {
99    CHECK_EQ(0, AsBitset(*type1) & AsBitset(*type2));
100  }
101}
102
103
104class HandlifiedTypes {
105 public:
106  explicit HandlifiedTypes(Isolate* isolate) :
107      None(Type::None(), isolate),
108      Any(Type::Any(), isolate),
109      Oddball(Type::Oddball(), isolate),
110      Boolean(Type::Boolean(), isolate),
111      Null(Type::Null(), isolate),
112      Undefined(Type::Undefined(), isolate),
113      Number(Type::Number(), isolate),
114      Smi(Type::Smi(), isolate),
115      Signed32(Type::Signed32(), isolate),
116      Double(Type::Double(), isolate),
117      Name(Type::Name(), isolate),
118      UniqueName(Type::UniqueName(), isolate),
119      String(Type::String(), isolate),
120      InternalizedString(Type::InternalizedString(), isolate),
121      Symbol(Type::Symbol(), isolate),
122      Receiver(Type::Receiver(), isolate),
123      Object(Type::Object(), isolate),
124      Array(Type::Array(), isolate),
125      Function(Type::Function(), isolate),
126      Proxy(Type::Proxy(), isolate),
127      object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)),
128      array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)),
129      isolate_(isolate) {
130    smi = handle(Smi::FromInt(666), isolate);
131    signed32 = isolate->factory()->NewHeapNumber(0x40000000);
132    object1 = isolate->factory()->NewJSObjectFromMap(object_map);
133    object2 = isolate->factory()->NewJSObjectFromMap(object_map);
134    array = isolate->factory()->NewJSArray(20);
135    ObjectClass = Class(object_map);
136    ArrayClass = Class(array_map);
137    SmiConstant = Constant(smi);
138    Signed32Constant = Constant(signed32);
139    ObjectConstant1 = Constant(object1);
140    ObjectConstant2 = Constant(object2);
141    ArrayConstant1 = Constant(array);
142    ArrayConstant2 = Constant(array);
143  }
144
145  Handle<Type> None;
146  Handle<Type> Any;
147  Handle<Type> Oddball;
148  Handle<Type> Boolean;
149  Handle<Type> Null;
150  Handle<Type> Undefined;
151  Handle<Type> Number;
152  Handle<Type> Smi;
153  Handle<Type> Signed32;
154  Handle<Type> Double;
155  Handle<Type> Name;
156  Handle<Type> UniqueName;
157  Handle<Type> String;
158  Handle<Type> InternalizedString;
159  Handle<Type> Symbol;
160  Handle<Type> Receiver;
161  Handle<Type> Object;
162  Handle<Type> Array;
163  Handle<Type> Function;
164  Handle<Type> Proxy;
165
166  Handle<Type> ObjectClass;
167  Handle<Type> ArrayClass;
168
169  Handle<Type> SmiConstant;
170  Handle<Type> Signed32Constant;
171  Handle<Type> ObjectConstant1;
172  Handle<Type> ObjectConstant2;
173  Handle<Type> ArrayConstant1;
174  Handle<Type> ArrayConstant2;
175
176  Handle<Map> object_map;
177  Handle<Map> array_map;
178
179  Handle<i::Smi> smi;
180  Handle<HeapNumber> signed32;
181  Handle<JSObject> object1;
182  Handle<JSObject> object2;
183  Handle<JSArray> array;
184
185  Handle<Type> Class(Handle<Map> map) {
186    return handle(Type::Class(map), isolate_);
187  }
188  Handle<Type> Constant(Handle<i::Object> value) {
189    return handle(Type::Constant(value, isolate_), isolate_);
190  }
191  Handle<Type> Union(Handle<Type> type1, Handle<Type> type2) {
192    return handle(Type::Union(type1, type2), isolate_);
193  }
194  Handle<Type> Intersect(Handle<Type> type1, Handle<Type> type2) {
195    return handle(Type::Intersect(type1, type2), isolate_);
196  }
197
198 private:
199  Isolate* isolate_;
200};
201
202
203TEST(Bitset) {
204  CcTest::InitializeVM();
205  Isolate* isolate = CcTest::i_isolate();
206  HandleScope scope(isolate);
207  HandlifiedTypes T(isolate);
208
209  CHECK(IsBitset(*T.None));
210  CHECK(IsBitset(*T.Any));
211  CHECK(IsBitset(*T.String));
212  CHECK(IsBitset(*T.Object));
213
214  CHECK(IsBitset(Type::Union(T.String, T.Number)));
215  CHECK(IsBitset(Type::Union(T.String, T.Receiver)));
216  CHECK(IsBitset(Type::Optional(T.Object)));
217
218  CHECK_EQ(0, AsBitset(*T.None));
219  CHECK_EQ(AsBitset(*T.Number) | AsBitset(*T.String),
220           AsBitset(Type::Union(T.String, T.Number)));
221  CHECK_EQ(AsBitset(*T.Receiver),
222           AsBitset(Type::Union(T.Receiver, T.Object)));
223  CHECK_EQ(AsBitset(*T.String) | AsBitset(*T.Undefined),
224           AsBitset(Type::Optional(T.String)));
225}
226
227
228TEST(Class) {
229  CcTest::InitializeVM();
230  Isolate* isolate = CcTest::i_isolate();
231  HandleScope scope(isolate);
232  HandlifiedTypes T(isolate);
233
234  CHECK(IsClass(*T.ObjectClass));
235  CHECK(IsClass(*T.ArrayClass));
236
237  CHECK(*T.object_map == AsClass(*T.ObjectClass));
238  CHECK(*T.array_map == AsClass(*T.ArrayClass));
239}
240
241
242TEST(Constant) {
243  CcTest::InitializeVM();
244  Isolate* isolate = CcTest::i_isolate();
245  HandleScope scope(isolate);
246  HandlifiedTypes T(isolate);
247
248  CHECK(IsConstant(*T.SmiConstant));
249  CHECK(IsConstant(*T.ObjectConstant1));
250  CHECK(IsConstant(*T.ObjectConstant2));
251  CHECK(IsConstant(*T.ArrayConstant1));
252  CHECK(IsConstant(*T.ArrayConstant2));
253
254  CHECK(*T.smi == AsConstant(*T.SmiConstant));
255  CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
256  CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
257  CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
258  CHECK(*T.array == AsConstant(*T.ArrayConstant1));
259  CHECK(*T.array == AsConstant(*T.ArrayConstant2));
260}
261
262
263TEST(Is) {
264  CcTest::InitializeVM();
265  Isolate* isolate = CcTest::i_isolate();
266  HandleScope scope(isolate);
267  HandlifiedTypes T(isolate);
268
269  // Reflexivity
270  CHECK(T.None->Is(T.None));
271  CHECK(T.Any->Is(T.Any));
272  CHECK(T.Object->Is(T.Object));
273
274  CHECK(T.ObjectClass->Is(T.ObjectClass));
275  CHECK(T.ObjectConstant1->Is(T.ObjectConstant1));
276  CHECK(T.ArrayConstant1->Is(T.ArrayConstant2));
277
278  // Symmetry and Transitivity
279  CheckSub(T.None, T.Number);
280  CheckSub(T.None, T.Any);
281
282  CheckSub(T.Oddball, T.Any);
283  CheckSub(T.Boolean, T.Oddball);
284  CheckSub(T.Null, T.Oddball);
285  CheckSub(T.Undefined, T.Oddball);
286  CheckUnordered(T.Boolean, T.Null);
287  CheckUnordered(T.Undefined, T.Null);
288  CheckUnordered(T.Boolean, T.Undefined);
289
290  CheckSub(T.Number, T.Any);
291  CheckSub(T.Smi, T.Number);
292  CheckSub(T.Signed32, T.Number);
293  CheckSub(T.Double, T.Number);
294  CheckSub(T.Smi, T.Signed32);
295  CheckUnordered(T.Smi, T.Double);
296  CheckUnordered(T.Signed32, T.Double);
297
298  CheckSub(T.Name, T.Any);
299  CheckSub(T.UniqueName, T.Any);
300  CheckSub(T.UniqueName, T.Name);
301  CheckSub(T.String, T.Name);
302  CheckSub(T.InternalizedString, T.String);
303  CheckSub(T.InternalizedString, T.UniqueName);
304  CheckSub(T.InternalizedString, T.Name);
305  CheckSub(T.Symbol, T.UniqueName);
306  CheckSub(T.Symbol, T.Name);
307  CheckUnordered(T.String, T.UniqueName);
308  CheckUnordered(T.String, T.Symbol);
309  CheckUnordered(T.InternalizedString, T.Symbol);
310
311  CheckSub(T.Receiver, T.Any);
312  CheckSub(T.Object, T.Any);
313  CheckSub(T.Object, T.Receiver);
314  CheckSub(T.Array, T.Object);
315  CheckSub(T.Function, T.Object);
316  CheckSub(T.Proxy, T.Receiver);
317  CheckUnordered(T.Object, T.Proxy);
318  CheckUnordered(T.Array, T.Function);
319
320  // Structured subtyping
321  CheckSub(T.None, T.ObjectClass);
322  CheckSub(T.None, T.ObjectConstant1);
323  CheckSub(T.ObjectClass, T.Any);
324  CheckSub(T.ObjectConstant1, T.Any);
325
326  CheckSub(T.ObjectClass, T.Object);
327  CheckSub(T.ArrayClass, T.Object);
328  CheckUnordered(T.ObjectClass, T.ArrayClass);
329
330  CheckSub(T.SmiConstant, T.Smi);
331  CheckSub(T.SmiConstant, T.Signed32);
332  CheckSub(T.SmiConstant, T.Number);
333  CheckSub(T.ObjectConstant1, T.Object);
334  CheckSub(T.ObjectConstant2, T.Object);
335  CheckSub(T.ArrayConstant1, T.Object);
336  CheckSub(T.ArrayConstant1, T.Array);
337  CheckUnordered(T.ObjectConstant1, T.ObjectConstant2);
338  CheckUnordered(T.ObjectConstant1, T.ArrayConstant1);
339
340  CheckUnordered(T.ObjectConstant1, T.ObjectClass);
341  CheckUnordered(T.ObjectConstant2, T.ObjectClass);
342  CheckUnordered(T.ObjectConstant1, T.ArrayClass);
343  CheckUnordered(T.ObjectConstant2, T.ArrayClass);
344  CheckUnordered(T.ArrayConstant1, T.ObjectClass);
345}
346
347
348TEST(Maybe) {
349  CcTest::InitializeVM();
350  Isolate* isolate = CcTest::i_isolate();
351  HandleScope scope(isolate);
352  HandlifiedTypes T(isolate);
353
354  CheckOverlap(T.Any, T.Any);
355  CheckOverlap(T.Object, T.Object);
356
357  CheckOverlap(T.Oddball, T.Any);
358  CheckOverlap(T.Boolean, T.Oddball);
359  CheckOverlap(T.Null, T.Oddball);
360  CheckOverlap(T.Undefined, T.Oddball);
361  CheckDisjoint(T.Boolean, T.Null);
362  CheckDisjoint(T.Undefined, T.Null);
363  CheckDisjoint(T.Boolean, T.Undefined);
364
365  CheckOverlap(T.Number, T.Any);
366  CheckOverlap(T.Smi, T.Number);
367  CheckOverlap(T.Double, T.Number);
368  CheckDisjoint(T.Signed32, T.Double);
369
370  CheckOverlap(T.Name, T.Any);
371  CheckOverlap(T.UniqueName, T.Any);
372  CheckOverlap(T.UniqueName, T.Name);
373  CheckOverlap(T.String, T.Name);
374  CheckOverlap(T.InternalizedString, T.String);
375  CheckOverlap(T.InternalizedString, T.UniqueName);
376  CheckOverlap(T.InternalizedString, T.Name);
377  CheckOverlap(T.Symbol, T.UniqueName);
378  CheckOverlap(T.Symbol, T.Name);
379  CheckOverlap(T.String, T.UniqueName);
380  CheckDisjoint(T.String, T.Symbol);
381  CheckDisjoint(T.InternalizedString, T.Symbol);
382
383  CheckOverlap(T.Receiver, T.Any);
384  CheckOverlap(T.Object, T.Any);
385  CheckOverlap(T.Object, T.Receiver);
386  CheckOverlap(T.Array, T.Object);
387  CheckOverlap(T.Function, T.Object);
388  CheckOverlap(T.Proxy, T.Receiver);
389  CheckDisjoint(T.Object, T.Proxy);
390  CheckDisjoint(T.Array, T.Function);
391
392  CheckOverlap(T.ObjectClass, T.Any);
393  CheckOverlap(T.ObjectConstant1, T.Any);
394
395  CheckOverlap(T.ObjectClass, T.Object);
396  CheckOverlap(T.ArrayClass, T.Object);
397  CheckOverlap(T.ObjectClass, T.ObjectClass);
398  CheckOverlap(T.ArrayClass, T.ArrayClass);
399  CheckDisjoint(T.ObjectClass, T.ArrayClass);
400
401  CheckOverlap(T.SmiConstant, T.Smi);
402  CheckOverlap(T.SmiConstant, T.Signed32);
403  CheckOverlap(T.SmiConstant, T.Number);
404  CheckDisjoint(T.SmiConstant, T.Double);
405  CheckOverlap(T.ObjectConstant1, T.Object);
406  CheckOverlap(T.ObjectConstant2, T.Object);
407  CheckOverlap(T.ArrayConstant1, T.Object);
408  CheckOverlap(T.ArrayConstant1, T.Array);
409  CheckOverlap(T.ArrayConstant1, T.ArrayConstant2);
410  CheckOverlap(T.ObjectConstant1, T.ObjectConstant1);
411  CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2);
412  CheckDisjoint(T.ObjectConstant1, T.ArrayConstant1);
413
414  CheckDisjoint(T.ObjectConstant1, T.ObjectClass);
415  CheckDisjoint(T.ObjectConstant2, T.ObjectClass);
416  CheckDisjoint(T.ObjectConstant1, T.ArrayClass);
417  CheckDisjoint(T.ObjectConstant2, T.ArrayClass);
418  CheckDisjoint(T.ArrayConstant1, T.ObjectClass);
419}
420
421
422TEST(Union) {
423  CcTest::InitializeVM();
424  Isolate* isolate = CcTest::i_isolate();
425  HandleScope scope(isolate);
426  HandlifiedTypes T(isolate);
427
428  // Bitset-bitset
429  CHECK(IsBitset(Type::Union(T.Object, T.Number)));
430  CHECK(IsBitset(Type::Union(T.Object, T.Object)));
431  CHECK(IsBitset(Type::Union(T.Any, T.None)));
432
433  CheckEqual(T.Union(T.None, T.Number), T.Number);
434  CheckEqual(T.Union(T.Object, T.Proxy), T.Receiver);
435  CheckEqual(T.Union(T.Number, T.String), T.Union(T.String, T.Number));
436  CheckSub(T.Union(T.Number, T.String), T.Any);
437
438  // Class-class
439  CHECK(IsClass(Type::Union(T.ObjectClass, T.ObjectClass)));
440  CHECK(IsUnion(Type::Union(T.ObjectClass, T.ArrayClass)));
441
442  CheckEqual(T.Union(T.ObjectClass, T.ObjectClass), T.ObjectClass);
443  CheckSub(T.None, T.Union(T.ObjectClass, T.ArrayClass));
444  CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Any);
445  CheckSub(T.ObjectClass, T.Union(T.ObjectClass, T.ArrayClass));
446  CheckSub(T.ArrayClass, T.Union(T.ObjectClass, T.ArrayClass));
447  CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object);
448  CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.Array);
449  CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array);
450  CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number);
451
452  // Constant-constant
453  CHECK(IsConstant(Type::Union(T.ObjectConstant1, T.ObjectConstant1)));
454  CHECK(IsConstant(Type::Union(T.ArrayConstant1, T.ArrayConstant1)));
455  CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectConstant2)));
456
457  CheckEqual(T.Union(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1);
458  CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant1);
459  CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant2);
460  CheckSub(T.None, T.Union(T.ObjectConstant1, T.ObjectConstant2));
461  CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Any);
462  CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2));
463  CheckSub(T.ObjectConstant2, T.Union(T.ObjectConstant1, T.ObjectConstant2));
464  CheckSub(T.ArrayConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant2));
465  CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object);
466  CheckUnordered(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass);
467  CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array);
468  CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array);
469  CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ArrayConstant2);
470  CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Number);
471  CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass);
472
473  // Bitset-class
474  CHECK(IsBitset(Type::Union(T.ObjectClass, T.Object)));
475  CHECK(IsUnion(Type::Union(T.ObjectClass, T.Number)));
476
477  CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
478  CheckSub(T.None, T.Union(T.ObjectClass, T.Number));
479  CheckSub(T.Union(T.ObjectClass, T.Number), T.Any);
480  CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number));
481  CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
482  CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
483  CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
484  CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
485
486  // Bitset-constant
487  CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number)));
488  CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
489  CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number)));
490
491  CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
492  CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
493  CheckSub(T.None, T.Union(T.ObjectConstant1, T.Number));
494  CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
495  CheckSub(T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
496  CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
497  CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array);
498  CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
499  CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number);
500  CheckEqual(T.Union(T.Signed32, T.Signed32Constant), T.Signed32);
501
502  // Class-constant
503  CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectClass)));
504  CHECK(IsUnion(Type::Union(T.ArrayClass, T.ObjectConstant2)));
505
506  CheckSub(T.None, T.Union(T.ObjectConstant1, T.ArrayClass));
507  CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Any);
508  CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object);
509  CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ArrayClass));
510  CheckSub(T.ArrayClass, T.Union(T.ObjectConstant1, T.ArrayClass));
511  CheckUnordered(T.ObjectClass, T.Union(T.ObjectConstant1, T.ArrayClass));
512  CheckSub(
513      T.Union(T.ObjectConstant1, T.ArrayClass), T.Union(T.Array, T.Object));
514  CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant1);
515  CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2);
516  CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass);
517
518  // Bitset-union
519  CHECK(IsBitset(
520      Type::Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
521  CHECK(IsUnion(
522      Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
523
524  CheckEqual(
525      T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
526      T.Object);
527  CheckEqual(
528      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number),
529      T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
530  CheckSub(
531      T.Double,
532      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
533  CheckSub(
534      T.ObjectConstant1,
535      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
536  CheckSub(
537      T.None,
538      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
539  CheckSub(
540      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double),
541      T.Any);
542  CheckSub(
543      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double),
544      T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
545
546  // Class-union
547  CHECK(IsUnion(
548      Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
549  CHECK(IsUnion(
550      Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass)));
551
552  CheckEqual(
553      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
554      T.Union(T.ObjectClass, T.ObjectConstant1));
555  CheckSub(
556      T.None,
557      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)));
558  CheckSub(
559      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
560      T.Any);
561  CheckSub(
562      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
563      T.Object);
564  CheckEqual(
565      T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass),
566      T.Union(T.ArrayClass, T.ObjectConstant2));
567
568  // Constant-union
569  CHECK(IsUnion(Type::Union(
570      T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
571  CHECK(IsUnion(Type::Union(
572      T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
573  CHECK(IsUnion(Type::Union(
574      T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1)));
575
576  CheckEqual(
577      T.Union(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
578      T.Union(T.ObjectConstant2, T.ObjectConstant1));
579  CheckEqual(
580      T.Union(T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1),
581      T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1)));
582
583  // Union-union
584  CHECK(IsBitset(Type::Union(
585      T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
586  CHECK(IsUnion(Type::Union(
587      T.Union(T.Number, T.ArrayClass), T.Union(T.ObjectClass, T.ArrayClass))));
588
589  CheckEqual(
590      T.Union(
591          T.Union(T.ObjectConstant2, T.ObjectConstant1),
592          T.Union(T.ObjectConstant1, T.ObjectConstant2)),
593      T.Union(T.ObjectConstant2, T.ObjectConstant1));
594  CheckEqual(
595      T.Union(
596          T.Union(T.ObjectConstant2, T.ArrayConstant1),
597          T.Union(T.ObjectConstant1, T.ArrayConstant2)),
598      T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant1));
599  CheckEqual(
600      T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)),
601      T.Union(T.Number, T.Array));
602}
603
604
605TEST(Intersect) {
606  CcTest::InitializeVM();
607  Isolate* isolate = CcTest::i_isolate();
608  HandleScope scope(isolate);
609  HandlifiedTypes T(isolate);
610
611  // Bitset-bitset
612  CHECK(IsBitset(Type::Intersect(T.Object, T.Number)));
613  CHECK(IsBitset(Type::Intersect(T.Object, T.Object)));
614  CHECK(IsBitset(Type::Intersect(T.Any, T.None)));
615
616  CheckEqual(T.Intersect(T.None, T.Number), T.None);
617  CheckEqual(T.Intersect(T.Object, T.Proxy), T.None);
618  CheckEqual(T.Intersect(T.Name, T.String), T.Intersect(T.String, T.Name));
619  CheckEqual(T.Intersect(T.UniqueName, T.String), T.InternalizedString);
620
621  // Class-class
622  CHECK(IsClass(Type::Intersect(T.ObjectClass, T.ObjectClass)));
623  CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.ArrayClass)));
624
625  CheckEqual(T.Intersect(T.ObjectClass, T.ObjectClass), T.ObjectClass);
626  CheckEqual(T.Intersect(T.ObjectClass, T.ArrayClass), T.None);
627
628  // Constant-constant
629  CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.ObjectConstant1)));
630  CHECK(IsConstant(Type::Intersect(T.ArrayConstant1, T.ArrayConstant2)));
631  CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectConstant2)));
632
633  CheckEqual(
634      T.Intersect(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1);
635  CheckEqual(
636      T.Intersect(T.ArrayConstant1, T.ArrayConstant2), T.ArrayConstant1);
637  CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectConstant2), T.None);
638
639  // Bitset-class
640  CHECK(IsClass(Type::Intersect(T.ObjectClass, T.Object)));
641  CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.Number)));
642
643  CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
644  CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None);
645  CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None);
646
647  // Bitset-constant
648  CHECK(IsBitset(Type::Intersect(T.Smi, T.Number)));
649  CHECK(IsConstant(Type::Intersect(T.SmiConstant, T.Number)));
650  CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.Object)));
651
652  CheckEqual(T.Intersect(T.Smi, T.Number), T.Smi);
653  CheckEqual(T.Intersect(T.SmiConstant, T.Number), T.SmiConstant);
654  CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1);
655
656  // Class-constant
657  CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectClass)));
658  CHECK(IsBitset(Type::Intersect(T.ArrayClass, T.ObjectConstant2)));
659
660  CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
661  CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
662
663  // Bitset-union
664  CHECK(IsUnion(
665      Type::Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
666  CHECK(IsBitset(
667      Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
668
669  CheckEqual(
670      T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
671      T.Union(T.ObjectConstant1, T.ObjectClass));
672  CheckEqual(
673      T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number),
674      T.None);
675
676  // Class-union
677  CHECK(IsClass(
678      Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
679  CHECK(IsClass(
680      Type::Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass)));
681  CHECK(IsBitset(
682      Type::Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass)));
683
684  CheckEqual(
685      T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
686      T.ArrayClass);
687  CheckEqual(
688      T.Intersect(T.ArrayClass, T.Union(T.Object, T.SmiConstant)),
689      T.ArrayClass);
690  CheckEqual(
691      T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass),
692      T.None);
693
694  // Constant-union
695  CHECK(IsConstant(Type::Intersect(
696      T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
697  CHECK(IsConstant(Type::Intersect(
698      T.Union(T.Number, T.ObjectClass), T.SmiConstant)));
699  CHECK(IsBitset(Type::Intersect(
700      T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
701
702  CheckEqual(
703      T.Intersect(
704          T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)),
705      T.ObjectConstant1);
706  CheckEqual(
707      T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)),
708      T.SmiConstant);
709  CheckEqual(
710      T.Intersect(T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1),
711      T.None);
712
713  // Union-union
714  CHECK(IsUnion(Type::Intersect(
715      T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
716  CHECK(IsBitset(Type::Intersect(
717      T.Union(T.Number, T.ObjectClass), T.Union(T.Signed32, T.Array))));
718
719  CheckEqual(
720      T.Intersect(
721          T.Union(T.Number, T.ArrayClass),
722          T.Union(T.Smi, T.Array)),
723      T.Union(T.Smi, T.ArrayClass));
724  CheckEqual(
725      T.Intersect(
726          T.Union(T.Number, T.ObjectClass),
727          T.Union(T.Signed32, T.Array)),
728      T.Signed32);
729  CheckEqual(
730      T.Intersect(
731          T.Union(T.ObjectConstant2, T.ObjectConstant1),
732          T.Union(T.ObjectConstant1, T.ObjectConstant2)),
733      T.Union(T.ObjectConstant2, T.ObjectConstant1));
734  CheckEqual(
735      T.Intersect(
736          T.Union(T.Union(T.ObjectConstant2, T.ObjectConstant1), T.ArrayClass),
737          T.Union(
738              T.ObjectConstant1, T.Union(T.ArrayConstant1, T.ObjectConstant2))),
739      T.Union(T.ObjectConstant2, T.ObjectConstant1));
740  CheckEqual(
741      T.Intersect(
742          T.Union(T.ObjectConstant2, T.ArrayConstant1),
743          T.Union(T.ObjectConstant1, T.ArrayConstant2)),
744      T.ArrayConstant1);
745}
746