Introduce representation types
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Mar 2014 11:50:18 +0000 (11:50 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Mar 2014 11:50:18 +0000 (11:50 +0000)
Also:
- improve type pretty-printing,
- update doc comments,
- some renamings for consistency.

R=mstarzinger@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20025 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/code-stubs-hydrogen.cc
src/hydrogen.cc
src/ic.cc
src/types.cc
src/types.h
src/typing.cc
test/cctest/test-types.cc

index e38efca..3f4997f 100644 (file)
@@ -941,7 +941,7 @@ HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
   // If we encounter a generic argument, the number conversion is
   // observable, thus we cannot afford to bail out after the fact.
   if (!state.HasSideEffects()) {
-    if (result_type->Is(Type::Smi())) {
+    if (result_type->Is(Type::SignedSmall())) {
       if (state.op() == Token::SHR) {
         // TODO(olivf) Replace this by a SmiTagU Instruction.
         // 0x40000000: this number would convert to negative when interpreting
index 8237cbb..cbd53ee 100644 (file)
@@ -1674,7 +1674,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
   }
   if_objectissmi.Else();
   {
-    if (type->Is(Type::Smi())) {
+    if (type->Is(Type::SignedSmall())) {
       if_objectissmi.Deopt("Expected smi");
     } else {
       // Check if the object is a heap number.
@@ -8980,7 +8980,7 @@ bool CanBeZero(HValue* right) {
 
 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
                                          Type* expected) {
-  if (expected->Is(Type::Smi())) {
+  if (expected->Is(Type::SignedSmall())) {
     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   }
   if (expected->Is(Type::Signed32())) {
@@ -9023,7 +9023,7 @@ HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
 
   if (expected_obj->Is(Type::Undefined(zone()))) {
     // This is already done by HChange.
-    *expected = Type::Union(expected_number, Type::Double(zone()), zone());
+    *expected = Type::Union(expected_number, Type::Float(zone()), zone());
     return value;
   }
 
index 5392fbc..f7d668f 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -2372,7 +2372,7 @@ const char* BinaryOpIC::State::KindToString(Kind kind) {
 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) {
   switch (kind) {
     case NONE: return Type::None(zone);
-    case SMI: return Type::Smi(zone);
+    case SMI: return Type::SignedSmall(zone);
     case INT32: return Type::Signed32(zone);
     case NUMBER: return Type::Number(zone);
     case STRING: return Type::String(zone);
@@ -2518,7 +2518,7 @@ Type* CompareIC::StateToType(
     Handle<Map> map) {
   switch (state) {
     case CompareIC::UNINITIALIZED: return Type::None(zone);
-    case CompareIC::SMI: return Type::Smi(zone);
+    case CompareIC::SMI: return Type::SignedSmall(zone);
     case CompareIC::NUMBER: return Type::Number(zone);
     case CompareIC::STRING: return Type::String(zone);
     case CompareIC::INTERNALIZED_STRING: return Type::InternalizedString(zone);
index cf41bb5..e269582 100644 (file)
@@ -152,14 +152,14 @@ int TypeImpl<Config>::LubBitset() {
 
 template<class Config>
 int TypeImpl<Config>::LubBitset(i::Object* value) {
-  if (value->IsSmi()) return kSmi;
+  if (value->IsSmi()) return kSignedSmall & kTaggedInt;
   i::Map* map = i::HeapObject::cast(value)->map();
   if (map->instance_type() == HEAP_NUMBER_TYPE) {
     int32_t i;
     uint32_t u;
-    if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32;
-    if (value->ToUint32(&u)) return kUnsigned32;
-    return kDouble;
+    return kTaggedPtr & (
+        value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
+        value->ToUint32(&u) ? kUnsigned32 : kFloat);
   }
   if (map->instance_type() == ODDBALL_TYPE) {
     if (value->IsUndefined()) return kUndefined;
@@ -204,7 +204,7 @@ int TypeImpl<Config>::LubBitset(i::Map* map) {
     case ODDBALL_TYPE:
       return kOddball;
     case HEAP_NUMBER_TYPE:
-      return kDouble;
+      return kFloat & kTaggedPtr;
     case JS_VALUE_TYPE:
     case JS_DATE_TYPE:
     case JS_OBJECT_TYPE:
@@ -247,7 +247,7 @@ int TypeImpl<Config>::LubBitset(i::Map* map) {
     case EXECUTABLE_ACCESSOR_INFO_TYPE:
     case ACCESSOR_PAIR_TYPE:
     case FIXED_ARRAY_TYPE:
-      return kInternal;
+      return kInternal & kTaggedPtr;
     default:
       UNREACHABLE();
       return kNone;
@@ -273,13 +273,12 @@ int TypeImpl<Config>::GlbBitset() {
 template<class Config>
 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently(
     i::Handle<i::Object> value, Region* region) {
-  if (value->IsSmi()) return Smi(region);
-  i::Map* map = i::HeapObject::cast(*value)->map();
-  if (map->instance_type() == HEAP_NUMBER_TYPE ||
-      map->instance_type() == ODDBALL_TYPE) {
+  if (value->IsSmi() ||
+      i::HeapObject::cast(*value)->map()->instance_type() == HEAP_NUMBER_TYPE ||
+      i::HeapObject::cast(*value)->map()->instance_type() == ODDBALL_TYPE) {
     return Of(value, region);
   }
-  return Class(i::handle(map), region);
+  return Class(i::handle(i::HeapObject::cast(*value)->map()), region);
 }
 
 
@@ -340,10 +339,10 @@ template<class Config>
 bool TypeImpl<Config>::Maybe(TypeImpl* that) {
   // Fast path for bitsets.
   if (this->IsBitset()) {
-    return (this->AsBitset() & that->LubBitset()) != 0;
+    return IsInhabited(this->AsBitset() & that->LubBitset());
   }
   if (that->IsBitset()) {
-    return (this->LubBitset() & that->AsBitset()) != 0;
+    return IsInhabited(this->LubBitset() & that->AsBitset());
   }
 
   // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
@@ -570,7 +569,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
 // TODO(rossberg): this does not belong here.
 Representation Representation::FromType(Type* type) {
   if (type->Is(Type::None())) return Representation::None();
-  if (type->Is(Type::Smi())) return Representation::Smi();
+  if (type->Is(Type::SignedSmall())) return Representation::Smi();
   if (type->Is(Type::Signed32())) return Representation::Integer32();
   if (type->Is(Type::Number())) return Representation::Double();
   return Representation::Tagged();
@@ -579,8 +578,8 @@ Representation Representation::FromType(Type* type) {
 
 #ifdef OBJECT_PRINT
 template<class Config>
-void TypeImpl<Config>::TypePrint() {
-  TypePrint(stdout);
+void TypeImpl<Config>::TypePrint(PrintDimension dim) {
+  TypePrint(stdout, dim);
   PrintF(stdout, "\n");
   Flush(stdout);
 }
@@ -589,9 +588,17 @@ void TypeImpl<Config>::TypePrint() {
 template<class Config>
 const char* TypeImpl<Config>::bitset_name(int bitset) {
   switch (bitset) {
-    #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
-    BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
+    case kAny & kRepresentation: return "Any";
+    #define PRINT_COMPOSED_TYPE(type, value) \
+    case k##type & kRepresentation: return #type;
+    REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
     #undef PRINT_COMPOSED_TYPE
+
+    #define PRINT_COMPOSED_TYPE(type, value) \
+    case k##type & kSemantic: return #type;
+    SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
+    #undef PRINT_COMPOSED_TYPE
+
     default:
       return NULL;
   }
@@ -599,23 +606,54 @@ const char* TypeImpl<Config>::bitset_name(int bitset) {
 
 
 template<class Config>
-void TypeImpl<Config>::TypePrint(FILE* out) {
+void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) {
+  const char* name = bitset_name(bitset);
+  if (name != NULL) {
+    PrintF(out, "%s", name);
+  } else {
+    static const int named_bitsets[] = {
+      #define BITSET_CONSTANT(type, value) k##type & kRepresentation,
+      REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
+      #undef BITSET_CONSTANT
+
+      #define BITSET_CONSTANT(type, value) k##type & kSemantic,
+      SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT)
+      #undef BITSET_CONSTANT
+    };
+
+    bool is_first = true;
+    PrintF(out, "(");
+    for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) {
+      int subset = named_bitsets[i];
+      if ((bitset & subset) == subset) {
+        if (!is_first) PrintF(out, " | ");
+        is_first = false;
+        PrintF(out, "%s", bitset_name(subset));
+        bitset -= subset;
+      }
+    }
+    ASSERT(bitset == 0);
+    PrintF(out, ")");
+  }
+}
+
+
+template<class Config>
+void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
   if (this->IsBitset()) {
     int bitset = this->AsBitset();
-    const char* name = bitset_name(bitset);
-    if (name != NULL) {
-      PrintF(out, "%s", name);
-    } else {
-      bool is_first = true;
-      PrintF(out, "(");
-      for (int mask = 1; mask != 0; mask = mask << 1) {
-        if ((bitset & mask) != 0) {
-          if (!is_first) PrintF(out, " | ");
-          is_first = false;
-          PrintF(out, "%s", bitset_name(mask));
-        }
-      }
-      PrintF(out, ")");
+    switch (dim) {
+      case BOTH_DIMS:
+        BitsetTypePrint(out, bitset & kSemantic);
+        PrintF("/");
+        BitsetTypePrint(out, bitset & kRepresentation);
+        break;
+      case SEMANTIC_DIM:
+        BitsetTypePrint(out, bitset & kSemantic);
+        break;
+      case REPRESENTATION_DIM:
+        BitsetTypePrint(out, bitset & kRepresentation);
+        break;
     }
   } else if (this->IsConstant()) {
     PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
index 20371a9..4569d13 100644 (file)
@@ -42,7 +42,10 @@ namespace internal {
 // can express class types (a.k.a. specific maps) and singleton types (i.e.,
 // concrete constants).
 //
-// The following equations and inequations hold:
+// Types consist of two dimensions: semantic (value range) and representation.
+// Both are related through subtyping.
+//
+// The following equations and inequations hold for the semantic axis:
 //
 //   None <= T
 //   T <= Any
@@ -54,13 +57,12 @@ namespace internal {
 //   UniqueName = InternalizedString \/ Symbol
 //   InternalizedString < String
 //
-//   Allocated = Receiver \/ Number \/ Name
-//   Detectable = Allocated - Undetectable
-//   Undetectable < Object
 //   Receiver = Object \/ Proxy
 //   Array < Object
 //   Function < Object
 //   RegExp < Object
+//   Undetectable < Object
+//   Detectable = Receiver \/ Number \/ Name - Undetectable
 //
 //   Class(map) < T   iff instance_type(map) < T
 //   Constant(x) < T  iff instance_type(map(x)) < T
@@ -70,20 +72,43 @@ namespace internal {
 // TODO(rossberg): the latter is not currently true for proxies, because of fix,
 // but will hold once we implement direct proxies.
 //
+// For the representation axis, the following holds:
+//
+//   None <= R
+//   R <= Any
+//
+//   UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32)
+//   UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64
+//   UntaggedNumber <= UntaggedInt \/ UntaggedFloat
+//   Untagged <= UntaggedNumber \/ UntaggedPtr
+//   Tagged <= TaggedInt \/ TaggedPtr
+//
+// Subtyping relates the two dimensions, for example:
+//
+//   Number <= Tagged \/ UntaggedNumber
+//   Object <= TaggedPtr \/ UntaggedPtr
+//
+// That holds because the semantic type constructors defined by the API create
+// types that allow for all possible representations, and dually, the ones for
+// representation types initially include all semantic ranges. Representations
+// can then e.g. be narrowed for a given semantic type using intersection:
+//
+//   SignedSmall /\ TaggedInt       (a 'smi')
+//   Number /\ TaggedPtr            (a heap number)
+//
 // There are two main functions for testing types:
 //
 //   T1->Is(T2)     -- tests whether T1 is included in T2 (i.e., T1 <= T2)
 //   T1->Maybe(T2)  -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
 //
 // Typically, the former is to be used to select representations (e.g., via
-// T->Is(Integer31())), and the to check whether a specific case needs handling
-// (e.g., via T->Maybe(Number())).
+// T->Is(SignedSmall())), and the latter to check whether a specific case needs
+// handling (e.g., via T->Maybe(Number())).
 //
 // There is no functionality to discover whether a type is a leaf in the
 // lattice. That is intentional. It should always be possible to refine the
 // lattice (e.g., splitting up number types further) without invalidating any
 // existing assumptions or tests.
-//
 // Consequently, do not use pointer equality for type tests, always use Is!
 //
 // Internally, all 'primitive' types, and their unions, are represented as
@@ -100,40 +125,68 @@ namespace internal {
 // them. For zone types, no query method touches the heap, only constructors do.
 
 
-#define BITSET_TYPE_LIST(V)              \
-  V(None,                0)              \
-  V(Null,                1 << 0)         \
-  V(Undefined,           1 << 1)         \
-  V(Boolean,             1 << 2)         \
-  V(Smi,                 1 << 3)         \
-  V(OtherSigned32,       1 << 4)         \
-  V(Unsigned32,          1 << 5)         \
-  V(Double,              1 << 6)         \
-  V(Symbol,              1 << 7)         \
-  V(InternalizedString,  1 << 8)         \
-  V(OtherString,         1 << 9)         \
-  V(Undetectable,        1 << 10)        \
-  V(Array,               1 << 11)        \
-  V(Function,            1 << 12)        \
-  V(RegExp,              1 << 13)        \
-  V(OtherObject,         1 << 14)        \
-  V(Proxy,               1 << 15)        \
-  V(Internal,            1 << 16)        \
+#define MASK_BITSET_TYPE_LIST(V) \
+  V(Representation, static_cast<int>(0xff800000)) \
+  V(Semantic,       static_cast<int>(0x007fffff))
+
+#define REPRESENTATION(k) ((k) & kRepresentation)
+#define SEMANTIC(k)       ((k) & kSemantic)
+
+#define REPRESENTATION_BITSET_TYPE_LIST(V) \
+  V(None,             0)                   \
+  V(UntaggedInt8,     1 << 23 | kSemantic) \
+  V(UntaggedInt16,    1 << 24 | kSemantic) \
+  V(UntaggedInt32,    1 << 25 | kSemantic) \
+  V(UntaggedFloat32,  1 << 26 | kSemantic) \
+  V(UntaggedFloat64,  1 << 27 | kSemantic) \
+  V(UntaggedPtr,      1 << 28 | kSemantic) \
+  V(TaggedInt,        1 << 29 | kSemantic) \
+  V(TaggedPtr,        -1 << 30 | kSemantic)  /* MSB has to be sign-extended */ \
+  \
+  V(UntaggedInt,      kUntaggedInt8 | kUntaggedInt16 | kUntaggedInt32) \
+  V(UntaggedFloat,    kUntaggedFloat32 | kUntaggedFloat64)             \
+  V(UntaggedNumber,   kUntaggedInt | kUntaggedFloat)                   \
+  V(Untagged,         kUntaggedNumber | kUntaggedPtr)                  \
+  V(Tagged,           kTaggedInt | kTaggedPtr)
+
+#define SEMANTIC_BITSET_TYPE_LIST(V) \
+  V(Null,                1 << 0  | REPRESENTATION(kTaggedPtr)) \
+  V(Undefined,           1 << 1  | REPRESENTATION(kTaggedPtr)) \
+  V(Boolean,             1 << 2  | REPRESENTATION(kTaggedPtr)) \
+  V(SignedSmall,         1 << 3  | REPRESENTATION(kTagged | kUntaggedNumber)) \
+  V(OtherSigned32,       1 << 4  | REPRESENTATION(kTagged | kUntaggedNumber)) \
+  V(Unsigned32,          1 << 5  | REPRESENTATION(kTagged | kUntaggedNumber)) \
+  V(Float,               1 << 6  | REPRESENTATION(kTagged | kUntaggedNumber)) \
+  V(Symbol,              1 << 7  | REPRESENTATION(kTaggedPtr)) \
+  V(InternalizedString,  1 << 8  | REPRESENTATION(kTaggedPtr)) \
+  V(OtherString,         1 << 9  | REPRESENTATION(kTaggedPtr)) \
+  V(Undetectable,        1 << 10 | REPRESENTATION(kTaggedPtr)) \
+  V(Array,               1 << 11 | REPRESENTATION(kTaggedPtr)) \
+  V(Function,            1 << 12 | REPRESENTATION(kTaggedPtr)) \
+  V(RegExp,              1 << 13 | REPRESENTATION(kTaggedPtr)) \
+  V(OtherObject,         1 << 14 | REPRESENTATION(kTaggedPtr)) \
+  V(Proxy,               1 << 15 | REPRESENTATION(kTaggedPtr)) \
+  V(Internal,            1 << 16 | REPRESENTATION(kTagged | kUntagged)) \
   \
-  V(Oddball,         kBoolean | kNull | kUndefined)                 \
-  V(Signed32,        kSmi | kOtherSigned32)                         \
-  V(Number,          kSigned32 | kUnsigned32 | kDouble)             \
-  V(String,          kInternalizedString | kOtherString)            \
-  V(UniqueName,      kSymbol | kInternalizedString)                 \
-  V(Name,            kSymbol | kString)                             \
-  V(NumberOrString,  kNumber | kString)                             \
-  V(Object,          kUndetectable | kArray | kFunction |           \
-                     kRegExp | kOtherObject)                        \
-  V(Receiver,        kObject | kProxy)                              \
-  V(Allocated,       kDouble | kName | kReceiver)                   \
-  V(Any,             kOddball | kNumber | kAllocated | kInternal)   \
-  V(NonNumber,       kAny - kNumber)                                \
-  V(Detectable,      kAllocated - kUndetectable)
+  V(Oddball,             kBoolean | kNull | kUndefined)                 \
+  V(Signed32,            kSignedSmall | kOtherSigned32)                 \
+  V(Number,              kSigned32 | kUnsigned32 | kFloat)              \
+  V(String,              kInternalizedString | kOtherString)            \
+  V(UniqueName,          kSymbol | kInternalizedString)                 \
+  V(Name,                kSymbol | kString)                             \
+  V(NumberOrString,      kNumber | kString)                             \
+  V(DetectableObject,    kArray | kFunction | kRegExp | kOtherObject)   \
+  V(DetectableReceiver,  kDetectableObject | kProxy)                    \
+  V(Detectable,          kDetectableReceiver | kNumber | kName)         \
+  V(Object,              kDetectableObject | kUndetectable)             \
+  V(Receiver,            kObject | kProxy)                              \
+  V(NonNumber,           kOddball | kName | kReceiver | kInternal)      \
+  V(Any,                 kNumber | kNonNumber)
+
+#define BITSET_TYPE_LIST(V) \
+  MASK_BITSET_TYPE_LIST(V) \
+  REPRESENTATION_BITSET_TYPE_LIST(V) \
+  SEMANTIC_BITSET_TYPE_LIST(V)
 
 
 // struct Config {
@@ -254,8 +307,9 @@ class TypeImpl : public Config::Base {
       typename OtherTypeImpl::TypeHandle type, Region* region);
 
 #ifdef OBJECT_PRINT
-  void TypePrint();
-  void TypePrint(FILE* out);
+  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
+  void TypePrint(PrintDimension = BOTH_DIMS);
+  void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
 #endif
 
  private:
@@ -292,6 +346,10 @@ class TypeImpl : public Config::Base {
 
   bool SlowIs(TypeImpl* that);
 
+  static bool IsInhabited(int bitset) {
+    return (bitset & kRepresentation) && (bitset & kSemantic);
+  }
+
   int LubBitset();  // least upper bound that's a bitset
   int GlbBitset();  // greatest lower bound that's a bitset
 
@@ -306,6 +364,7 @@ class TypeImpl : public Config::Base {
 
 #ifdef OBJECT_PRINT
   static const char* bitset_name(int bitset);
+  static void BitsetTypePrint(FILE* out, int bitset);
 #endif
 };
 
index a88ca8c..2a581e2 100644 (file)
@@ -612,7 +612,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
 
   RECURSE(Visit(expr->expression()));
 
-  NarrowType(expr, Bounds(Type::Smi(zone()), Type::Number(zone())));
+  NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
 
   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   if (proxy != NULL && proxy->var()->IsStackAllocated()) {
@@ -668,7 +668,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
       Type* upper = Type::Union(
           expr->left()->bounds().upper, expr->right()->bounds().upper, zone());
       if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
-      Type* lower = Type::Intersect(Type::Smi(zone()), upper, zone());
+      Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
       NarrowType(expr, Bounds(lower, upper));
       break;
     }
@@ -677,7 +677,8 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
     case Token::SAR:
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      NarrowType(expr, Bounds(Type::Smi(zone()), Type::Signed32(zone())));
+      NarrowType(expr,
+          Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())));
       break;
     case Token::SHR:
       RECURSE(Visit(expr->left()));
@@ -685,7 +686,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
       // TODO(rossberg): The upper bound would be Unsigned32, but since there
       // is no 'positive Smi' type for the lower bound, we use the smallest
       // union of Smi and Unsigned32 as upper bound instead.
-      NarrowType(expr, Bounds(Type::Smi(zone()), Type::Number(zone())));
+      NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
       break;
     case Token::ADD: {
       RECURSE(Visit(expr->left()));
@@ -698,7 +699,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
           l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
               Type::String(zone()) :
           l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
-              Type::Smi(zone()) : Type::None(zone());
+              Type::SignedSmall(zone()) : Type::None(zone());
       Type* upper =
           l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
               Type::String(zone()) :
@@ -713,7 +714,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
     case Token::MOD:
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      NarrowType(expr, Bounds(Type::Smi(zone()), Type::Number(zone())));
+      NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
       break;
     default:
       UNREACHABLE();
index 57f0b27..326bd1b 100644 (file)
@@ -34,6 +34,8 @@ template<class Type, class TypeHandle, class Region>
 class Types {
  public:
   Types(Region* region, Isolate* isolate) :
+      Representation(Type::Representation(region)),
+      Semantic(Type::Semantic(region)),
       None(Type::None(region)),
       Any(Type::Any(region)),
       Oddball(Type::Oddball(region)),
@@ -41,9 +43,9 @@ class Types {
       Null(Type::Null(region)),
       Undefined(Type::Undefined(region)),
       Number(Type::Number(region)),
-      Smi(Type::Smi(region)),
+      SignedSmall(Type::SignedSmall(region)),
       Signed32(Type::Signed32(region)),
-      Double(Type::Double(region)),
+      Float(Type::Float(region)),
       Name(Type::Name(region)),
       UniqueName(Type::UniqueName(region)),
       String(Type::String(region)),
@@ -72,6 +74,8 @@ class Types {
     ArrayConstant2 = Type::Constant(array, region);
   }
 
+  TypeHandle Representation;
+  TypeHandle Semantic;
   TypeHandle None;
   TypeHandle Any;
   TypeHandle Oddball;
@@ -79,9 +83,9 @@ class Types {
   TypeHandle Null;
   TypeHandle Undefined;
   TypeHandle Number;
-  TypeHandle Smi;
+  TypeHandle SignedSmall;
   TypeHandle Signed32;
-  TypeHandle Double;
+  TypeHandle Float;
   TypeHandle Name;
   TypeHandle UniqueName;
   TypeHandle String;
@@ -236,7 +240,7 @@ struct Tests : Rep {
       T(Rep::ToRegion(&zone, isolate), isolate) {
   }
 
-  static void CheckEqual(TypeHandle type1, TypeHandle type2) {
+  void CheckEqual(TypeHandle type1, TypeHandle type2) {
     CHECK_EQ(Rep::IsBitset(type1), Rep::IsBitset(type2));
     CHECK_EQ(Rep::IsClass(type1), Rep::IsClass(type2));
     CHECK_EQ(Rep::IsConstant(type1), Rep::IsConstant(type2));
@@ -256,7 +260,7 @@ struct Tests : Rep {
     CHECK(type2->Is(type1));
   }
 
-  static void CheckSub(TypeHandle type1, TypeHandle type2) {
+  void CheckSub(TypeHandle type1, TypeHandle type2) {
     CHECK(type1->Is(type2));
     CHECK(!type2->Is(type1));
     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
@@ -264,7 +268,7 @@ struct Tests : Rep {
     }
   }
 
-  static void CheckUnordered(TypeHandle type1, TypeHandle type2) {
+  void CheckUnordered(TypeHandle type1, TypeHandle type2) {
     CHECK(!type1->Is(type2));
     CHECK(!type2->Is(type1));
     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
@@ -272,21 +276,23 @@ struct Tests : Rep {
     }
   }
 
-  static void CheckOverlap(TypeHandle type1, TypeHandle type2) {
+  void CheckOverlap(TypeHandle type1, TypeHandle type2, TypeHandle mask) {
     CHECK(type1->Maybe(type2));
     CHECK(type2->Maybe(type1));
     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
-      CHECK_NE(0, Rep::AsBitset(type1) & Rep::AsBitset(type2));
+      CHECK_NE(0,
+          Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
     }
   }
 
-  static void CheckDisjoint(TypeHandle type1, TypeHandle type2) {
+  void CheckDisjoint(TypeHandle type1, TypeHandle type2, TypeHandle mask) {
     CHECK(!type1->Is(type2));
     CHECK(!type2->Is(type1));
     CHECK(!type1->Maybe(type2));
     CHECK(!type2->Maybe(type1));
     if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
-      CHECK_EQ(0, Rep::AsBitset(type1) & Rep::AsBitset(type2));
+      CHECK_EQ(0,
+          Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
     }
   }
 
@@ -300,10 +306,12 @@ struct Tests : Rep {
     CHECK(this->IsBitset(T.Union(T.String, T.Receiver)));
 
     CHECK_EQ(0, this->AsBitset(T.None));
-    CHECK_EQ(this->AsBitset(T.Number) | this->AsBitset(T.String),
-             this->AsBitset(T.Union(T.String, T.Number)));
-    CHECK_EQ(this->AsBitset(T.Receiver),
-             this->AsBitset(T.Union(T.Receiver, T.Object)));
+    CHECK_EQ(
+        this->AsBitset(T.Number) | this->AsBitset(T.String),
+        this->AsBitset(T.Union(T.String, T.Number)));
+    CHECK_EQ(
+        this->AsBitset(T.Receiver),
+        this->AsBitset(T.Union(T.Receiver, T.Object)));
   }
 
   void Class() {
@@ -352,12 +360,12 @@ struct Tests : Rep {
     CheckUnordered(T.Boolean, T.Undefined);
 
     CheckSub(T.Number, T.Any);
-    CheckSub(T.Smi, T.Number);
+    CheckSub(T.SignedSmall, T.Number);
     CheckSub(T.Signed32, T.Number);
-    CheckSub(T.Double, T.Number);
-    CheckSub(T.Smi, T.Signed32);
-    CheckUnordered(T.Smi, T.Double);
-    CheckUnordered(T.Signed32, T.Double);
+    CheckSub(T.Float, T.Number);
+    CheckSub(T.SignedSmall, T.Signed32);
+    CheckUnordered(T.SignedSmall, T.Float);
+    CheckUnordered(T.Signed32, T.Float);
 
     CheckSub(T.Name, T.Any);
     CheckSub(T.UniqueName, T.Any);
@@ -391,7 +399,7 @@ struct Tests : Rep {
     CheckSub(T.ArrayClass, T.Object);
     CheckUnordered(T.ObjectClass, T.ArrayClass);
 
-    CheckSub(T.SmiConstant, T.Smi);
+    CheckSub(T.SmiConstant, T.SignedSmall);
     CheckSub(T.SmiConstant, T.Signed32);
     CheckSub(T.SmiConstant, T.Number);
     CheckSub(T.ObjectConstant1, T.Object);
@@ -409,71 +417,71 @@ struct Tests : Rep {
   }
 
   void Maybe() {
-    CheckOverlap(T.Any, T.Any);
-    CheckOverlap(T.Object, T.Object);
-
-    CheckOverlap(T.Oddball, T.Any);
-    CheckOverlap(T.Boolean, T.Oddball);
-    CheckOverlap(T.Null, T.Oddball);
-    CheckOverlap(T.Undefined, T.Oddball);
-    CheckDisjoint(T.Boolean, T.Null);
-    CheckDisjoint(T.Undefined, T.Null);
-    CheckDisjoint(T.Boolean, T.Undefined);
-
-    CheckOverlap(T.Number, T.Any);
-    CheckOverlap(T.Smi, T.Number);
-    CheckOverlap(T.Double, T.Number);
-    CheckDisjoint(T.Signed32, T.Double);
-
-    CheckOverlap(T.Name, T.Any);
-    CheckOverlap(T.UniqueName, T.Any);
-    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.Receiver, T.Any);
-    CheckOverlap(T.Object, T.Any);
-    CheckOverlap(T.Object, T.Receiver);
-    CheckOverlap(T.Array, T.Object);
-    CheckOverlap(T.Function, T.Object);
-    CheckOverlap(T.Proxy, T.Receiver);
-    CheckDisjoint(T.Object, T.Proxy);
-    CheckDisjoint(T.Array, T.Function);
-
-    CheckOverlap(T.ObjectClass, T.Any);
-    CheckOverlap(T.ObjectConstant1, T.Any);
-
-    CheckOverlap(T.ObjectClass, T.Object);
-    CheckOverlap(T.ArrayClass, T.Object);
-    CheckOverlap(T.ObjectClass, T.ObjectClass);
-    CheckOverlap(T.ArrayClass, T.ArrayClass);
-    CheckDisjoint(T.ObjectClass, T.ArrayClass);
-
-    CheckOverlap(T.SmiConstant, T.Smi);
-    CheckOverlap(T.SmiConstant, T.Signed32);
-    CheckOverlap(T.SmiConstant, T.Number);
-    CheckDisjoint(T.SmiConstant, T.Double);
-    CheckOverlap(T.ObjectConstant1, T.Object);
-    CheckOverlap(T.ObjectConstant2, T.Object);
-    CheckOverlap(T.ArrayConstant1, T.Object);
-    CheckOverlap(T.ArrayConstant1, T.Array);
-    CheckOverlap(T.ArrayConstant1, T.ArrayConstant2);
-    CheckOverlap(T.ObjectConstant1, T.ObjectConstant1);
-    CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2);
-    CheckDisjoint(T.ObjectConstant1, T.ArrayConstant1);
-
-    CheckDisjoint(T.ObjectConstant1, T.ObjectClass);
-    CheckDisjoint(T.ObjectConstant2, T.ObjectClass);
-    CheckDisjoint(T.ObjectConstant1, T.ArrayClass);
-    CheckDisjoint(T.ObjectConstant2, T.ArrayClass);
-    CheckDisjoint(T.ArrayConstant1, T.ObjectClass);
+    CheckOverlap(T.Any, T.Any, T.Semantic);
+    CheckOverlap(T.Object, T.Object, T.Semantic);
+
+    CheckOverlap(T.Oddball, T.Any, T.Semantic);
+    CheckOverlap(T.Boolean, T.Oddball, T.Semantic);
+    CheckOverlap(T.Null, T.Oddball, T.Semantic);
+    CheckOverlap(T.Undefined, T.Oddball, T.Semantic);
+    CheckDisjoint(T.Boolean, T.Null, T.Semantic);
+    CheckDisjoint(T.Undefined, T.Null, T.Semantic);
+    CheckDisjoint(T.Boolean, T.Undefined, T.Semantic);
+
+    CheckOverlap(T.Number, T.Any, T.Semantic);
+    CheckOverlap(T.SignedSmall, T.Number, T.Semantic);
+    CheckOverlap(T.Float, T.Number, T.Semantic);
+    CheckDisjoint(T.Signed32, T.Float, T.Semantic);
+
+    CheckOverlap(T.Name, T.Any, T.Semantic);
+    CheckOverlap(T.UniqueName, T.Any, T.Semantic);
+    CheckOverlap(T.UniqueName, T.Name, T.Semantic);
+    CheckOverlap(T.String, T.Name, T.Semantic);
+    CheckOverlap(T.InternalizedString, T.String, T.Semantic);
+    CheckOverlap(T.InternalizedString, T.UniqueName, T.Semantic);
+    CheckOverlap(T.InternalizedString, T.Name, T.Semantic);
+    CheckOverlap(T.Symbol, T.UniqueName, T.Semantic);
+    CheckOverlap(T.Symbol, T.Name, T.Semantic);
+    CheckOverlap(T.String, T.UniqueName, T.Semantic);
+    CheckDisjoint(T.String, T.Symbol, T.Semantic);
+    CheckDisjoint(T.InternalizedString, T.Symbol, T.Semantic);
+
+    CheckOverlap(T.Receiver, T.Any, T.Semantic);
+    CheckOverlap(T.Object, T.Any, T.Semantic);
+    CheckOverlap(T.Object, T.Receiver, T.Semantic);
+    CheckOverlap(T.Array, T.Object, T.Semantic);
+    CheckOverlap(T.Function, T.Object, T.Semantic);
+    CheckOverlap(T.Proxy, T.Receiver, T.Semantic);
+    CheckDisjoint(T.Object, T.Proxy, T.Semantic);
+    CheckDisjoint(T.Array, T.Function, T.Semantic);
+
+    CheckOverlap(T.ObjectClass, T.Any, T.Semantic);
+    CheckOverlap(T.ObjectConstant1, T.Any, T.Semantic);
+
+    CheckOverlap(T.ObjectClass, T.Object, T.Semantic);
+    CheckOverlap(T.ArrayClass, T.Object, T.Semantic);
+    CheckOverlap(T.ObjectClass, T.ObjectClass, T.Semantic);
+    CheckOverlap(T.ArrayClass, T.ArrayClass, T.Semantic);
+    CheckDisjoint(T.ObjectClass, T.ArrayClass, T.Semantic);
+
+    CheckOverlap(T.SmiConstant, T.SignedSmall, T.Semantic);
+    CheckOverlap(T.SmiConstant, T.Signed32, T.Semantic);
+    CheckOverlap(T.SmiConstant, T.Number, T.Semantic);
+    CheckDisjoint(T.SmiConstant, T.Float, T.Semantic);
+    CheckOverlap(T.ObjectConstant1, T.Object, T.Semantic);
+    CheckOverlap(T.ObjectConstant2, T.Object, T.Semantic);
+    CheckOverlap(T.ArrayConstant1, T.Object, T.Semantic);
+    CheckOverlap(T.ArrayConstant1, T.Array, T.Semantic);
+    CheckOverlap(T.ArrayConstant1, T.ArrayConstant2, T.Semantic);
+    CheckOverlap(T.ObjectConstant1, T.ObjectConstant1, T.Semantic);
+    CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2, T.Semantic);
+    CheckDisjoint(T.ObjectConstant1, T.ArrayConstant1, T.Semantic);
+
+    CheckDisjoint(T.ObjectConstant1, T.ObjectClass, T.Semantic);
+    CheckDisjoint(T.ObjectConstant2, T.ObjectClass, T.Semantic);
+    CheckDisjoint(T.ObjectConstant1, T.ArrayClass, T.Semantic);
+    CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
+    CheckDisjoint(T.ArrayConstant1, T.ObjectClass, T.Semantic);
   }
 
   void Union() {
@@ -498,8 +506,8 @@ struct Tests : Rep {
     CheckSub(T.ArrayClass, T.Union(T.ObjectClass, T.ArrayClass));
     CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object);
     CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.Array);
-    CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array);
-    CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number);
+    CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array, T.Semantic);
+    CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number, T.Semantic);
 
     // Constant-constant
     CHECK(this->IsConstant(T.Union(T.ObjectConstant1, T.ObjectConstant1)));
@@ -520,11 +528,16 @@ struct Tests : Rep {
     CheckUnordered(
         T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass);
     CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array);
-    CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array);
     CheckOverlap(
-        T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ArrayConstant2);
-    CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Number);
-    CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass);
+        T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array, T.Semantic);
+    CheckOverlap(
+        T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ArrayConstant2,
+        T.Semantic);
+    CheckDisjoint(
+        T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Number, T.Semantic);
+    CheckDisjoint(
+        T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass,
+        T.Semantic);
 
     // Bitset-class
     CHECK(this->IsBitset(T.Union(T.ObjectClass, T.Object)));
@@ -533,11 +546,12 @@ struct Tests : Rep {
     CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
     CheckSub(T.None, T.Union(T.ObjectClass, T.Number));
     CheckSub(T.Union(T.ObjectClass, T.Number), T.Any);
-    CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number));
+    CheckSub(
+        T.Union(T.ObjectClass, T.SignedSmall), T.Union(T.Object, T.Number));
     CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
     CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
-    CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
-    CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
+    CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object, T.Semantic);
+    CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number, T.Semantic);
 
     // Bitset-constant
     CHECK(this->IsBitset(T.Union(T.SmiConstant, T.Number)));
@@ -552,8 +566,8 @@ struct Tests : Rep {
         T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
     CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
     CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array);
-    CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
-    CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number);
+    CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object, T.Semantic);
+    CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number, T.Semantic);
     CheckEqual(T.Union(T.Signed32, T.Signed32Constant), T.Signed32);
 
     // Class-constant
@@ -569,8 +583,11 @@ struct Tests : Rep {
     CheckSub(
         T.Union(T.ObjectConstant1, T.ArrayClass), T.Union(T.Array, T.Object));
     CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant1);
-    CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2);
-    CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass);
+    CheckDisjoint(
+        T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2,
+        T.Semantic);
+    CheckDisjoint(
+        T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass, T.Semantic);
 
     // Bitset-union
     CHECK(this->IsBitset(
@@ -585,19 +602,19 @@ struct Tests : Rep {
         T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number),
         T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
     CheckSub(
-        T.Double,
+        T.Float,
         T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
     CheckSub(
         T.ObjectConstant1,
-        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
+        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float));
     CheckSub(
         T.None,
-        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
+        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float));
     CheckSub(
-        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double),
+        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float),
         T.Any);
     CheckSub(
-        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double),
+        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float),
         T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));
 
     // Class-union
@@ -661,7 +678,9 @@ struct Tests : Rep {
             T.Union(T.ObjectConstant1, T.ObjectConstant2),
             T.ArrayConstant1));
     CheckEqual(
-        T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)),
+        T.Union(
+            T.Union(T.Number, T.ArrayClass),
+            T.Union(T.SignedSmall, T.Array)),
         T.Union(T.Number, T.Array));
   }
 
@@ -672,7 +691,7 @@ struct Tests : Rep {
     CHECK(this->IsBitset(T.Intersect(T.Any, T.None)));
 
     CheckEqual(T.Intersect(T.None, T.Number), T.None);
-    CheckEqual(T.Intersect(T.Object, T.Proxy), T.None);
+    CheckSub(T.Intersect(T.Object, T.Proxy), T.Representation);
     CheckEqual(T.Intersect(T.Name, T.String), T.Intersect(T.String, T.Name));
     CheckEqual(T.Intersect(T.UniqueName, T.String), T.InternalizedString);
 
@@ -699,15 +718,15 @@ struct Tests : Rep {
     CHECK(this->IsBitset(T.Intersect(T.ObjectClass, T.Number)));
 
     CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
-    CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None);
-    CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None);
+    CheckSub(T.Intersect(T.ObjectClass, T.Array), T.Representation);
+    CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
 
     // Bitset-constant
-    CHECK(this->IsBitset(T.Intersect(T.Smi, T.Number)));
+    CHECK(this->IsBitset(T.Intersect(T.SignedSmall, T.Number)));
     CHECK(this->IsConstant(T.Intersect(T.SmiConstant, T.Number)));
     CHECK(this->IsConstant(T.Intersect(T.ObjectConstant1, T.Object)));
 
-    CheckEqual(T.Intersect(T.Smi, T.Number), T.Smi);
+    CheckEqual(T.Intersect(T.SignedSmall, T.Number), T.SignedSmall);
     CheckEqual(T.Intersect(T.SmiConstant, T.Number), T.SmiConstant);
     CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1);
 
@@ -778,8 +797,8 @@ struct Tests : Rep {
     CheckEqual(
         T.Intersect(
             T.Union(T.Number, T.ArrayClass),
-            T.Union(T.Smi, T.Array)),
-        T.Union(T.Smi, T.ArrayClass));
+            T.Union(T.SignedSmall, T.Array)),
+        T.Union(T.SignedSmall, T.ArrayClass));
     CheckEqual(
         T.Intersect(
             T.Union(T.Number, T.ObjectClass),