Revision: 21494
Author:   [email protected]
Date:     Mon May 26 13:10:52 2014 UTC
Log:      Various extensions to types

[email protected]
BUG=

Review URL: https://codereview.chromium.org/296213005
http://code.google.com/p/v8/source/detail?r=21494

Modified:
 /branches/bleeding_edge/src/conversions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/types-inl.h
 /branches/bleeding_edge/src/types.cc
 /branches/bleeding_edge/src/types.h
 /branches/bleeding_edge/test/cctest/test-types.cc

=======================================
--- /branches/bleeding_edge/src/conversions.h   Tue Apr 29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/conversions.h   Mon May 26 13:10:52 2014 UTC
@@ -161,6 +161,17 @@
          value <= kMaxInt &&
          value == FastI2D(FastD2I(value));
 }
+
+
+// UInteger32 is an integer that can be represented as an unsigned 32-bit
+// integer. It has to be in the range [0, 2^32 - 1].
+// We also have to check for negative 0 as it is not a UInteger32.
+static inline bool IsUint32Double(double value) {
+  return !IsMinusZero(value) &&
+         value >= 0 &&
+         value <= kMaxUInt32 &&
+         value == FastUI2D(FastD2UI(value));
+}


 // Convert from Number object to C integer.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Mon May 26 09:04:00 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Mon May 26 13:10:52 2014 UTC
@@ -9503,7 +9503,7 @@

   if (expected_obj->Is(Type::Undefined(zone()))) {
     // This is already done by HChange.
-    *expected = Type::Union(expected_number, Type::Float(zone()), zone());
+    *expected = Type::Union(expected_number, Type::Number(zone()), zone());
     return value;
   }

=======================================
--- /branches/bleeding_edge/src/types-inl.h     Wed Apr 16 16:36:27 2014 UTC
+++ /branches/bleeding_edge/src/types-inl.h     Mon May 26 13:10:52 2014 UTC
@@ -20,7 +20,7 @@
 TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
   TypeImpl* t = static_cast<TypeImpl*>(object);
   ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() ||
-         t->IsUnion() || t->IsArray() || t->IsFunction());
+ t->IsUnion() || t->IsArray() || t->IsFunction() || t->IsContext());
   return t;
 }

=======================================
--- /branches/bleeding_edge/src/types.cc        Thu Apr 24 07:16:10 2014 UTC
+++ /branches/bleeding_edge/src/types.cc        Mon May 26 13:10:52 2014 UTC
@@ -148,6 +148,8 @@
     return kArray;
   } else if (type->IsFunction()) {
     return kFunction;
+  } else if (type->IsContext()) {
+    return kInternal & kTaggedPtr;
   } else {
     UNREACHABLE();
     return kNone;
@@ -158,16 +160,43 @@
 template<class Config>
 int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
   DisallowHeapAllocation no_allocation;
-  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;
-    return kTaggedPtr & (
- value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
-        value->ToUint32(&u) ? kUnsigned32 : kFloat);
+  if (value->IsNumber()) {
+ return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
+  }
+  return Lub(i::HeapObject::cast(value)->map());
+}
+
+
+template<class Config>
+int TypeImpl<Config>::BitsetType::Lub(double value) {
+  DisallowHeapAllocation no_allocation;
+  if (i::IsMinusZero(value)) return kMinusZero;
+  if (std::isnan(value)) return kNaN;
+  if (IsUint32Double(value)) return Lub(FastD2UI(value));
+  if (IsInt32Double(value)) return Lub(FastD2I(value));
+  return kOtherNumber;
+}
+
+
+template<class Config>
+int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
+  if (value >= 0x40000000) {
+    return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
   }
-  return Lub(map);
+  if (value >= 0) return kUnsignedSmall;
+  if (value >= -0x40000000) return kOtherSignedSmall;
+  return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall;
+}
+
+
+template<class Config>
+int TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
+  DisallowHeapAllocation no_allocation;
+  if (value >= 0x80000000u) return kOtherUnsigned32;
+  if (value >= 0x40000000u) {
+    return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
+  }
+  return kUnsignedSmall;
 }


@@ -211,7 +240,7 @@
       return kInternal & kTaggedPtr;
     }
     case HEAP_NUMBER_TYPE:
-      return kFloat & kTaggedPtr;
+      return kNumber & kTaggedPtr;
     case JS_VALUE_TYPE:
     case JS_DATE_TYPE:
     case JS_OBJECT_TYPE:
@@ -254,6 +283,7 @@
       return kDetectable;
     case DECLARED_ACCESSOR_INFO_TYPE:
     case EXECUTABLE_ACCESSOR_INFO_TYPE:
+    case SHARED_FUNCTION_INFO_TYPE:
     case ACCESSOR_PAIR_TYPE:
     case FIXED_ARRAY_TYPE:
     case FOREIGN_TYPE:
@@ -296,6 +326,10 @@
     return this->IsConstant()
         && *this->AsConstant()->Value() == *that->AsConstant()->Value();
   }
+  if (that->IsContext()) {
+    return this->IsContext()
+        && this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
+  }
   if (that->IsArray()) {
     return this->IsArray()
         && this->AsArray()->Element()->Equals(that->AsArray()->Element());
@@ -411,6 +445,9 @@
     return that->IsConstant()
         && *this->AsConstant()->Value() == *that->AsConstant()->Value();
   }
+  if (this->IsContext()) {
+    return this->Equals(that);
+  }
   if (this->IsArray()) {
     // There is no variance!
     return this->Equals(that);
@@ -463,7 +500,8 @@
   } else if (!type->IsBitset()) {
     // For all structural types, subtyping implies equivalence.
     ASSERT(type->IsClass() || type->IsConstant() ||
-           type->IsArray() || type->IsFunction());
+           type->IsArray() || type->IsFunction() ||
+           type->IsContext());
     if (!type->InUnion(result, old_size)) {
       result->Set(current_size++, type);
     }
@@ -539,7 +577,7 @@
   } else if (!type->IsBitset()) {
     // For all structural types, subtyping implies equivalence.
     ASSERT(type->IsClass() || type->IsConstant() ||
-           type->IsArray() || type->IsFunction());
+           type->IsArray() || type->IsFunction() || type->IsContext());
     if (type->Is(other) && !type->InUnion(result, old_size)) {
       result->Set(current_size++, type);
     }
@@ -608,6 +646,9 @@
     return ClassType::New(type->AsClass()->Map(), region);
   } else if (type->IsConstant()) {
     return ConstantType::New(type->AsConstant()->Value(), region);
+  } else if (type->IsContext()) {
+ TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region);
+    return ContextType::New(outer, region);
   } else if (type->IsUnion()) {
     int length = type->AsUnion()->Length();
     UnionHandle unioned = UnionType::New(length, region);
@@ -644,29 +685,21 @@
   if (type->Is(Type::Number())) return Representation::Double();
   return Representation::Tagged();
 }
-
-
-template<class Config>
-void TypeImpl<Config>::TypePrint(PrintDimension dim) {
-  TypePrint(stdout, dim);
-  PrintF(stdout, "\n");
-  Flush(stdout);
-}


 template<class Config>
 const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
   switch (bitset) {
-    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
+    case REPRESENTATION(kAny): return "Any";
+    #define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \
+    case REPRESENTATION(k##type): return #type;
+    REPRESENTATION_BITSET_TYPE_LIST(RETURN_NAMED_REPRESENTATION_TYPE)
+    #undef RETURN_NAMED_REPRESENTATION_TYPE

-    #define PRINT_COMPOSED_TYPE(type, value) \
-    case k##type & kSemantic: return #type;
-    SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
-    #undef PRINT_COMPOSED_TYPE
+    #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \
+    case SEMANTIC(k##type): return #type;
+    SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE)
+    #undef RETURN_NAMED_SEMANTIC_TYPE

     default:
       return NULL;
@@ -675,95 +708,116 @@


 template<class Config>
-void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) {
+void TypeImpl<Config>::BitsetType::PrintTo(StringStream* stream, int bitset) {
   DisallowHeapAllocation no_allocation;
   const char* name = Name(bitset);
   if (name != NULL) {
-    PrintF(out, "%s", name);
+    stream->Add("%s", name);
   } else {
     static const int named_bitsets[] = {
-      #define BITSET_CONSTANT(type, value) k##type & kRepresentation,
+      #define BITSET_CONSTANT(type, value) REPRESENTATION(k##type),
       REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
       #undef BITSET_CONSTANT

-      #define BITSET_CONSTANT(type, value) k##type & kSemantic,
+      #define BITSET_CONSTANT(type, value) SEMANTIC(k##type),
       SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT)
       #undef BITSET_CONSTANT
     };

     bool is_first = true;
-    PrintF(out, "(");
+    stream->Add("(");
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, " | ");
+        if (!is_first) stream->Add(" | ");
         is_first = false;
-        PrintF(out, "%s", Name(subset));
+        stream->Add("%s", Name(subset));
         bitset -= subset;
       }
     }
     ASSERT(bitset == 0);
-    PrintF(out, ")");
+    stream->Add(")");
   }
 }


 template<class Config>
-void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
+void TypeImpl<Config>::PrintTo(StringStream* stream, PrintDimension dim) {
   DisallowHeapAllocation no_allocation;
   if (this->IsBitset()) {
     int bitset = this->AsBitset();
     switch (dim) {
       case BOTH_DIMS:
-        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
-        PrintF(out, "/");
- BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
+        BitsetType::PrintTo(stream, SEMANTIC(bitset));
+        stream->Add("/");
+        BitsetType::PrintTo(stream, REPRESENTATION(bitset));
         break;
       case SEMANTIC_DIM:
-        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
+        BitsetType::PrintTo(stream, SEMANTIC(bitset));
         break;
       case REPRESENTATION_DIM:
- BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
+        BitsetType::PrintTo(stream, REPRESENTATION(bitset));
         break;
     }
   } else if (this->IsConstant()) {
-    PrintF(out, "Constant(%p : ",
+    stream->Add("Constant(%p : ",
         static_cast<void*>(*this->AsConstant()->Value()));
-    BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
-    PrintF(out, ")");
+    BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
+    stream->Add(")");
   } else if (this->IsClass()) {
- PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
-    BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
-    PrintF(out, ")");
+ stream->Add("Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
+    BitsetType::New(BitsetType::Lub(this))->PrintTo(stream, dim);
+    stream->Add(")");
+  } else if (this->IsContext()) {
+    stream->Add("Context(");
+    this->AsContext()->Outer()->PrintTo(stream, dim);
+    stream->Add(")");
   } else if (this->IsUnion()) {
-    PrintF(out, "(");
+    stream->Add("(");
     UnionHandle unioned = handle(this->AsUnion());
     for (int i = 0; i < unioned->Length(); ++i) {
       TypeHandle type_i = unioned->Get(i);
-      if (i > 0) PrintF(out, " | ");
-      type_i->TypePrint(out, dim);
+      if (i > 0) stream->Add(" | ");
+      type_i->PrintTo(stream, dim);
     }
-    PrintF(out, ")");
+    stream->Add(")");
   } else if (this->IsArray()) {
-    PrintF(out, "[");
-    AsArray()->Element()->TypePrint(out, dim);
-    PrintF(out, "]");
+    stream->Add("[");
+    AsArray()->Element()->PrintTo(stream, dim);
+    stream->Add("]");
   } else if (this->IsFunction()) {
     if (!this->AsFunction()->Receiver()->IsAny()) {
-      this->AsFunction()->Receiver()->TypePrint(out, dim);
-      PrintF(out, ".");
+      this->AsFunction()->Receiver()->PrintTo(stream, dim);
+      stream->Add(".");
     }
-    PrintF(out, "(");
+    stream->Add("(");
     for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
-      if (i > 0) PrintF(out, ", ");
-      this->AsFunction()->Parameter(i)->TypePrint(out, dim);
+      if (i > 0) stream->Add(", ");
+      this->AsFunction()->Parameter(i)->PrintTo(stream, dim);
     }
-    PrintF(out, ")->");
-    this->AsFunction()->Result()->TypePrint(out, dim);
+    stream->Add(")->");
+    this->AsFunction()->Result()->PrintTo(stream, dim);
   } else {
     UNREACHABLE();
   }
 }
+
+
+template<class Config>
+void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
+  HeapStringAllocator allocator;
+  StringStream stream(&allocator);
+  PrintTo(&stream, dim);
+  stream.OutputToFile(out);
+}
+
+
+template<class Config>
+void TypeImpl<Config>::TypePrint(PrintDimension dim) {
+  TypePrint(stdout, dim);
+  PrintF(stdout, "\n");
+  Flush(stdout);
+}


 template class TypeImpl<ZoneTypeConfig>;
=======================================
--- /branches/bleeding_edge/src/types.h Thu Apr 17 08:22:22 2014 UTC
+++ /branches/bleeding_edge/src/types.h Mon May 26 13:10:52 2014 UTC
@@ -45,10 +45,14 @@
 //   Constant(x) < T  iff instance_type(map(x)) < T
 //   Array(T) < Array
 //   Function(R, S, T0, T1, ...) < Function
+//   Context(T) < Internal
 //
-// Both structural Array and Function types are invariant in all parameters.
-// Relaxing this would make Union and Intersect operations more involved.
-// Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
+// Both structural Array and Function types are invariant in all parameters;
+// relaxing this would make Union and Intersect operations more involved.
+// There is no subtyping relation between Array, Function, or Context types
+// and respective Constant types, since these types cannot be reconstructed
+// for arbitrary heap values.
+// Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
 // change! (Its instance type cannot, however.)
// TODO(rossberg): the latter is not currently true for proxies, because of fix,
 // but will hold once we implement direct proxies.
@@ -129,14 +133,15 @@


 #define MASK_BITSET_TYPE_LIST(V) \
-  V(Representation, static_cast<int>(0xff800000)) \
-  V(Semantic,       static_cast<int>(0x007fffff))
+  V(Representation, static_cast<int>(0xffc00000)) \
+  V(Semantic,       static_cast<int>(0x003fffff))

-#define REPRESENTATION(k) ((k) & kRepresentation)
-#define SEMANTIC(k)       ((k) & kSemantic)
+#define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
+#define SEMANTIC(k)       ((k) & BitsetType::kSemantic)

 #define REPRESENTATION_BITSET_TYPE_LIST(V) \
   V(None,             0)                   \
+  V(UntaggedInt1,     1 << 22 | kSemantic) \
   V(UntaggedInt8,     1 << 23 | kSemantic) \
   V(UntaggedInt16,    1 << 24 | kSemantic) \
   V(UntaggedInt32,    1 << 25 | kSemantic) \
@@ -146,44 +151,54 @@
   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(UntaggedInt,      kUntaggedInt1 | 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(UnsignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(OtherSignedSmall, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(OtherUnsigned31, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(OtherUnsigned32, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(OtherSigned32, 1 << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(MinusZero, 1 << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(NaN, 1 << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \ + V(OtherNumber, 1 << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
+  V(Symbol,              1 << 11 | REPRESENTATION(kTaggedPtr)) \
+  V(InternalizedString,  1 << 12 | REPRESENTATION(kTaggedPtr)) \
+  V(OtherString,         1 << 13 | REPRESENTATION(kTaggedPtr)) \
+  V(Undetectable,        1 << 14 | REPRESENTATION(kTaggedPtr)) \
+  V(Array,               1 << 15 | REPRESENTATION(kTaggedPtr)) \
+  V(Buffer,              1 << 16 | REPRESENTATION(kTaggedPtr)) \
+  V(Function,            1 << 17 | REPRESENTATION(kTaggedPtr)) \
+  V(RegExp,              1 << 18 | REPRESENTATION(kTaggedPtr)) \
+  V(OtherObject,         1 << 19 | REPRESENTATION(kTaggedPtr)) \
+  V(Proxy,               1 << 20 | REPRESENTATION(kTaggedPtr)) \
+  V(Internal,            1 << 21 | REPRESENTATION(kTagged | kUntagged)) \
   \
-  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,           kBoolean | kName | kNull | kReceiver |         \
-                         kUndefined | kInternal)                        \
+  V(SignedSmall,         kUnsignedSmall | kOtherSignedSmall) \
+ V(Signed32, kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \ + V(Unsigned32, kUnsignedSmall | kOtherUnsigned31 | kOtherUnsigned32) \
+  V(Integral32,          kSigned32 | kUnsigned32) \
+  V(Number,              kIntegral32 | kMinusZero | kNaN | kOtherNumber) \
+  V(String,              kInternalizedString | kOtherString) \
+  V(UniqueName,          kSymbol | kInternalizedString) \
+  V(Name,                kSymbol | kString) \
+  V(NumberOrString,      kNumber | kString) \
+  V(Primitive,           kNumber | kName | kBoolean | kNull | kUndefined) \
+  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,           kBoolean | kName | kNull | kReceiver | \
+                         kUndefined | kInternal) \
   V(Any,                 -1)

 #define BITSET_TYPE_LIST(V) \
@@ -230,12 +245,14 @@

   class ClassType;
   class ConstantType;
+  class ContextType;
   class ArrayType;
   class FunctionType;

   typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
   typedef typename Config::template Handle<ClassType>::type ClassHandle;
typedef typename Config::template Handle<ConstantType>::type ConstantHandle; + typedef typename Config::template Handle<ContextType>::type ContextHandle;
   typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
   typedef typename Config::template Handle<UnionType>::type UnionHandle;
@@ -255,6 +272,9 @@
   static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
     return ConstantType::New(value, region);
   }
+  static TypeHandle Context(TypeHandle outer, Region* region) {
+    return ContextType::New(outer, region);
+  }
   static TypeHandle Array(TypeHandle element, Region* region) {
     return ArrayType::New(element, region);
   }
@@ -276,12 +296,24 @@
     FunctionHandle function = Function(result, Any(region), 2, region);
     function->InitParameter(0, param0);
     function->InitParameter(1, param1);
+    return function;
+  }
+  static TypeHandle Function(
+      TypeHandle result, TypeHandle param0, TypeHandle param1,
+      TypeHandle param2, Region* region) {
+    FunctionHandle function = Function(result, Any(region), 3, region);
+    function->InitParameter(0, param0);
+    function->InitParameter(1, param1);
+    function->InitParameter(2, param2);
     return function;
   }

   static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);

+  static TypeHandle Of(double value, Region* region) {
+    return Config::from_bitset(BitsetType::Lub(value), region);
+  }
   static TypeHandle Of(i::Object* value, Region* region) {
     return Config::from_bitset(BitsetType::Lub(value), region);
   }
@@ -325,6 +357,9 @@

   bool IsClass() { return Config::is_class(this); }
   bool IsConstant() { return Config::is_constant(this); }
+  bool IsContext() {
+    return Config::is_struct(this, StructuralType::kContextTag);
+  }
bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); }
   bool IsFunction() {
     return Config::is_struct(this, StructuralType::kFunctionTag);
@@ -332,6 +367,7 @@

   ClassType* AsClass() { return ClassType::cast(this); }
   ConstantType* AsConstant() { return ConstantType::cast(this); }
+  ContextType* AsContext() { return ContextType::cast(this); }
   ArrayType* AsArray() { return ArrayType::cast(this); }
   FunctionType* AsFunction() { return FunctionType::cast(this); }

@@ -355,6 +391,7 @@
       typename OtherTypeImpl::TypeHandle type, Region* region);

   enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
+  void PrintTo(StringStream* stream, PrintDimension = BOTH_DIMS);
   void TypePrint(PrintDimension = BOTH_DIMS);
   void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);

@@ -419,10 +456,14 @@
   static int Glb(TypeImpl* type);  // greatest lower bound that's a bitset
   static int Lub(TypeImpl* type);  // least upper bound that's a bitset
   static int Lub(i::Object* value);
+  static int Lub(double value);
+  static int Lub(int32_t value);
+  static int Lub(uint32_t value);
   static int Lub(i::Map* map);

   static const char* Name(int bitset);
-  static void BitsetTypePrint(FILE* out, int bitset);
+  static void PrintTo(StringStream* stream, int bitset);
+  using TypeImpl::PrintTo;
 };


@@ -438,6 +479,7 @@
   enum Tag {
     kClassTag,
     kConstantTag,
+    kContextTag,
     kArrayTag,
     kFunctionTag,
     kUnionTag
@@ -496,6 +538,25 @@
 };


+template<class Config>
+class TypeImpl<Config>::ContextType : public StructuralType {
+ public:
+  TypeHandle Outer() { return this->Get(0); }
+
+  static ContextHandle New(TypeHandle outer, Region* region) {
+    ContextHandle type = Config::template cast<ContextType>(
+        StructuralType::New(StructuralType::kContextTag, 1, region));
+    type->Set(0, outer);
+    return type;
+  }
+
+  static ContextType* cast(TypeImpl* type) {
+    ASSERT(type->IsContext());
+    return static_cast<ContextType*>(type);
+  }
+};
+
+
 // Internal
 // A union is a structured type with the following invariants:
 // - its length is at least 2
=======================================
--- /branches/bleeding_edge/test/cctest/test-types.cc Thu Apr 17 09:30:41 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-types.cc Mon May 26 13:10:52 2014 UTC
@@ -43,9 +43,10 @@
static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
   static bool IsClass(Type* t) { return IsStruct(t, 0); }
   static bool IsConstant(Type* t) { return IsStruct(t, 1); }
-  static bool IsArray(Type* t) { return IsStruct(t, 2); }
-  static bool IsFunction(Type* t) { return IsStruct(t, 3); }
-  static bool IsUnion(Type* t) { return IsStruct(t, 4); }
+  static bool IsContext(Type* t) { return IsStruct(t, 2); }
+  static bool IsArray(Type* t) { return IsStruct(t, 3); }
+  static bool IsFunction(Type* t) { return IsStruct(t, 4); }
+  static bool IsUnion(Type* t) { return IsStruct(t, 5); }

   static Struct* AsStruct(Type* t) {
     return reinterpret_cast<Struct*>(t);
@@ -59,6 +60,9 @@
   static Object* AsConstant(Type* t) {
     return *static_cast<Object**>(AsStruct(t)[3]);
   }
+  static Type* AsContext(Type* t) {
+    return *static_cast<Type**>(AsStruct(t)[2]);
+  }
   static Struct* AsUnion(Type* t) {
     return AsStruct(t);
   }
@@ -79,9 +83,10 @@
   static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
   static bool IsClass(Handle<HeapType> t) { return t->IsMap(); }
   static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); }
-  static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 2); }
-  static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 3); }
-  static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 4); }
+  static bool IsContext(Handle<HeapType> t) { return IsStruct(t, 2); }
+  static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 3); }
+  static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 4); }
+  static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 5); }

static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); } static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
@@ -89,6 +94,9 @@
   static Object* AsConstant(Handle<HeapType> t) {
     return Box::cast(*t)->value();
   }
+  static HeapType* AsContext(Handle<HeapType> t) {
+    return HeapType::cast(AsStruct(t)->get(1));
+  }
   static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
static int Length(Struct* structured) { return structured->length() - 1; }

@@ -143,7 +151,7 @@
       types.push_back(Type::Constant(*it, region));
     }

-    FloatArray = Type::Array(Float, region);
+    NumberArray = Type::Array(Number, region);
     StringArray = Type::Array(String, region);
     AnyArray = Type::Array(Any, region);

@@ -183,7 +191,7 @@
   TypeHandle ArrayConstant;
   TypeHandle UninitializedConstant;

-  TypeHandle FloatArray;
+  TypeHandle NumberArray;
   TypeHandle StringArray;
   TypeHandle AnyArray;

@@ -272,13 +280,19 @@
         int i = rng_.NextInt(static_cast<int>(values.size()));
         return Type::Constant(values[i], region_);
       }
-      case 3: {  // array
+      case 3: {  // context
+        int depth = rng_.NextInt(3);
+        TypeHandle type = Type::Internal(region_);
+ for (int i = 0; i < depth; ++i) type = Type::Context(type, region_);
+        return type;
+      }
+      case 4: {  // array
         TypeHandle element = Fuzz(depth / 2);
         return Type::Array(element, region_);
       }
-      case 4:
       case 5:
-      case 6: {  // function
+      case 6:
+      case 7: {  // function
         TypeHandle result = Fuzz(depth / 2);
         TypeHandle receiver = Fuzz(depth / 2);
         int arity = rng_.NextInt(3);
@@ -332,6 +346,7 @@
         Rep::IsBitset(type1) == Rep::IsBitset(type2) &&
         Rep::IsClass(type1) == Rep::IsClass(type2) &&
         Rep::IsConstant(type1) == Rep::IsConstant(type2) &&
+        Rep::IsContext(type1) == Rep::IsContext(type2) &&
         Rep::IsUnion(type1) == Rep::IsUnion(type2) &&
         type1->NumClasses() == type2->NumClasses() &&
         type1->NumConstants() == type2->NumConstants() &&
@@ -507,6 +522,45 @@
         CHECK(Equal(type1, type2) == (*value1 == *value2));
       }
     }
+
+    // Typing of numbers
+    Factory* fac = isolate->factory();
+    CHECK(T.Constant(fac->NewNumber(0))->Is(T.UnsignedSmall));
+    CHECK(T.Constant(fac->NewNumber(1))->Is(T.UnsignedSmall));
+    CHECK(T.Constant(fac->NewNumber(0x3fffffff))->Is(T.UnsignedSmall));
+    CHECK(T.Constant(fac->NewNumber(-1))->Is(T.OtherSignedSmall));
+    CHECK(T.Constant(fac->NewNumber(-0x3fffffff))->Is(T.OtherSignedSmall));
+    CHECK(T.Constant(fac->NewNumber(-0x40000000))->Is(T.OtherSignedSmall));
+    if (SmiValuesAre31Bits()) {
+      CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31));
+      CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31));
+      CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
+      CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
+ CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
+    } else {
+      CHECK(SmiValuesAre32Bits());
+      CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
+      CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
+ CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.OtherUnsigned31)); + CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.OtherUnsigned31)); + CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSignedSmall)); + CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSignedSmall)); + CHECK(T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSignedSmall));
+      CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.OtherSigned32));
+      CHECK(!T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.OtherSigned32));
+ CHECK(!T.Constant(fac->NewNumber(-0x7fffffff-1))->Is(T.OtherSigned32));
+    }
+    CHECK(T.Constant(fac->NewNumber(0x80000000u))->Is(T.OtherUnsigned32));
+    CHECK(T.Constant(fac->NewNumber(0xffffffffu))->Is(T.OtherUnsigned32));
+    CHECK(T.Constant(fac->NewNumber(0xffffffffu+1.0))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(-0x7fffffff-2.0))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(0.1))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(-10.1))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(10e60))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(-1.0*0.0))->Is(T.MinusZero));
+    CHECK(T.Constant(fac->NewNumber(0.0/0.0))->Is(T.NaN));
+    CHECK(T.Constant(fac->NewNumber(1.0/0.0))->Is(T.OtherNumber));
+    CHECK(T.Constant(fac->NewNumber(-1.0/0.0))->Is(T.OtherNumber));
   }

   void Array() {
@@ -772,10 +826,9 @@

     CheckSub(T.SignedSmall, T.Number);
     CheckSub(T.Signed32, T.Number);
-    CheckSub(T.Float, T.Number);
     CheckSub(T.SignedSmall, T.Signed32);
-    CheckUnordered(T.SignedSmall, T.Float);
-    CheckUnordered(T.Signed32, T.Float);
+    CheckUnordered(T.SignedSmall, T.MinusZero);
+    CheckUnordered(T.Signed32, T.Unsigned32);

     CheckSub(T.UniqueName, T.Name);
     CheckSub(T.String, T.Name);
@@ -823,8 +876,8 @@
     CheckUnordered(T.ObjectConstant2, T.ArrayClass);
     CheckUnordered(T.ArrayConstant, T.ObjectClass);

-    CheckSub(T.FloatArray, T.Array);
-    CheckSub(T.FloatArray, T.Object);
+    CheckSub(T.NumberArray, T.Array);
+    CheckSub(T.NumberArray, T.Object);
     CheckUnordered(T.StringArray, T.AnyArray);

     CheckSub(T.MethodFunction, T.Function);
@@ -1114,8 +1167,8 @@
     CheckDisjoint(T.Boolean, T.Undefined, 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.NaN, T.Number, T.Semantic);
+    CheckDisjoint(T.Signed32, T.NaN, T.Semantic);

     CheckOverlap(T.UniqueName, T.Name, T.Semantic);
     CheckOverlap(T.String, T.Name, T.Semantic);
@@ -1145,7 +1198,6 @@
     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.ArrayConstant, T.Object, T.Semantic);
@@ -1160,9 +1212,9 @@
     CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
     CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);

-    CheckOverlap(T.FloatArray, T.Array, T.Semantic);
-    CheckDisjoint(T.FloatArray, T.AnyArray, T.Semantic);
-    CheckDisjoint(T.FloatArray, T.StringArray, T.Semantic);
+    CheckOverlap(T.NumberArray, T.Array, T.Semantic);
+    CheckDisjoint(T.NumberArray, T.AnyArray, T.Semantic);
+    CheckDisjoint(T.NumberArray, T.StringArray, T.Semantic);

     CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
     CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
@@ -1303,22 +1355,18 @@

     // Bitset-array
     CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array)));
-    CHECK(this->IsUnion(T.Union(T.FloatArray, T.Number)));
+    CHECK(this->IsUnion(T.Union(T.NumberArray, T.Number)));

     CheckEqual(T.Union(T.AnyArray, T.Array), T.Array);
-    CheckSub(T.None, T.Union(T.FloatArray, T.Number));
-    CheckSub(T.Union(T.FloatArray, T.Number), T.Any);
     CheckUnordered(T.Union(T.AnyArray, T.String), T.Array);
-    CheckOverlap(T.Union(T.FloatArray, T.String), T.Object, T.Semantic);
-    CheckDisjoint(T.Union(T.FloatArray, T.String), T.Number, T.Semantic);
+    CheckOverlap(T.Union(T.NumberArray, T.String), T.Object, T.Semantic);
+    CheckDisjoint(T.Union(T.NumberArray, T.String), T.Number, T.Semantic);

     // Bitset-function
     CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
     CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));

     CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function);
-    CheckSub(T.None, T.Union(T.MethodFunction, T.Number));
-    CheckSub(T.Union(T.MethodFunction, T.Number), T.Any);
     CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function);
CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic); CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
@@ -1353,10 +1401,10 @@

     // Bitset-union
     CheckSub(
-        T.Float,
+        T.NaN,
         T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number));
     CheckSub(
-        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Float),
+        T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Signed32),
         T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass)));

     // Class-union
@@ -1380,9 +1428,9 @@

     // Array-union
     CheckEqual(
-        T.Union(T.AnyArray, T.Union(T.FloatArray, T.AnyArray)),
-        T.Union(T.AnyArray, T.FloatArray));
-    CheckSub(T.Union(T.AnyArray, T.FloatArray), T.Array);
+        T.Union(T.AnyArray, T.Union(T.NumberArray, T.AnyArray)),
+        T.Union(T.AnyArray, T.NumberArray));
+    CheckSub(T.Union(T.AnyArray, T.NumberArray), T.Array);

     // Function-union
     CheckEqual(
@@ -1524,7 +1572,7 @@
     CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);

     // Bitset-array
-    CheckEqual(T.Intersect(T.FloatArray, T.Object), T.FloatArray);
+    CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
     CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation);

     // Bitset-function
@@ -1545,13 +1593,13 @@

     // Array-union
     CheckEqual(
-        T.Intersect(T.FloatArray, T.Union(T.FloatArray, T.ArrayClass)),
-        T.FloatArray);
+        T.Intersect(T.NumberArray, T.Union(T.NumberArray, T.ArrayClass)),
+        T.NumberArray);
     CheckEqual(
         T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
         T.AnyArray);
     CheckEqual(
-        T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.FloatArray),
+        T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.NumberArray),
         T.None);

     // Function-union

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to