1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_TYPES_H_
6 #define V8_TYPES_H_
7 
8 #include "src/conversions.h"
9 #include "src/factory.h"
10 #include "src/handles.h"
11 #include "src/ostreams.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // SUMMARY
17 //
18 // A simple type system for compiler-internal use. It is based entirely on
19 // union types, and all subtyping hence amounts to set inclusion. Besides the
20 // obvious primitive types and some predefined unions, the type language also
21 // can express class types (a.k.a. specific maps) and singleton types (i.e.,
22 // concrete constants).
23 //
24 // Types consist of two dimensions: semantic (value range) and representation.
25 // Both are related through subtyping.
26 //
27 //
28 // SEMANTIC DIMENSION
29 //
30 // The following equations and inequations hold for the semantic axis:
31 //
32 //   None <= T
33 //   T <= Any
34 //
35 //   Number = Signed32 \/ Unsigned32 \/ Double
36 //   Smi <= Signed32
37 //   Name = String \/ Symbol
38 //   UniqueName = InternalizedString \/ Symbol
39 //   InternalizedString < String
40 //
41 //   Receiver = Object \/ Proxy
42 //   Array < Object
43 //   Function < Object
44 //   RegExp < Object
45 //   Undetectable < Object
46 //   Detectable = Receiver \/ Number \/ Name - Undetectable
47 //
48 //   Class(map) < T   iff instance_type(map) < T
49 //   Constant(x) < T  iff instance_type(map(x)) < T
50 //   Array(T) < Array
51 //   Function(R, S, T0, T1, ...) < Function
52 //   Context(T) < Internal
53 //
54 // Both structural Array and Function types are invariant in all parameters;
55 // relaxing this would make Union and Intersect operations more involved.
56 // There is no subtyping relation between Array, Function, or Context types
57 // and respective Constant types, since these types cannot be reconstructed
58 // for arbitrary heap values.
59 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
60 // change! (Its instance type cannot, however.)
61 // TODO(rossberg): the latter is not currently true for proxies, because of fix,
62 // but will hold once we implement direct proxies.
63 // However, we also define a 'temporal' variant of the subtyping relation that
64 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)).
65 //
66 //
67 // REPRESENTATIONAL DIMENSION
68 //
69 // For the representation axis, the following holds:
70 //
71 //   None <= R
72 //   R <= Any
73 //
74 //   UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/
75 //                 UntaggedInt16 \/ UntaggedInt32
76 //   UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64
77 //   UntaggedNumber = UntaggedInt \/ UntaggedFloat
78 //   Untagged = UntaggedNumber \/ UntaggedPtr
79 //   Tagged = TaggedInt \/ TaggedPtr
80 //
81 // Subtyping relates the two dimensions, for example:
82 //
83 //   Number <= Tagged \/ UntaggedNumber
84 //   Object <= TaggedPtr \/ UntaggedPtr
85 //
86 // That holds because the semantic type constructors defined by the API create
87 // types that allow for all possible representations, and dually, the ones for
88 // representation types initially include all semantic ranges. Representations
89 // can then e.g. be narrowed for a given semantic type using intersection:
90 //
91 //   SignedSmall /\ TaggedInt       (a 'smi')
92 //   Number /\ TaggedPtr            (a heap number)
93 //
94 //
95 // RANGE TYPES
96 //
97 // A range type represents a continuous integer interval by its minimum and
98 // maximum value.  Either value might be an infinity.
99 //
100 // Constant(v) is considered a subtype of Range(x..y) if v happens to be an
101 // integer between x and y.
102 //
103 //
104 // PREDICATES
105 //
106 // There are two main functions for testing types:
107 //
108 //   T1->Is(T2)     -- tests whether T1 is included in T2 (i.e., T1 <= T2)
109 //   T1->Maybe(T2)  -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
110 //
111 // Typically, the former is to be used to select representations (e.g., via
112 // T->Is(SignedSmall())), and the latter to check whether a specific case needs
113 // handling (e.g., via T->Maybe(Number())).
114 //
115 // There is no functionality to discover whether a type is a leaf in the
116 // lattice. That is intentional. It should always be possible to refine the
117 // lattice (e.g., splitting up number types further) without invalidating any
118 // existing assumptions or tests.
119 // Consequently, do not normally use Equals for type tests, always use Is!
120 //
121 // The NowIs operator implements state-sensitive subtying, as described above.
122 // Any compilation decision based on such temporary properties requires runtime
123 // guarding!
124 //
125 //
126 // PROPERTIES
127 //
128 // Various formal properties hold for constructors, operators, and predicates
129 // over types. For example, constructors are injective and subtyping is a
130 // complete partial order.
131 //
132 // See test/cctest/test-types.cc for a comprehensive executable specification,
133 // especially with respect to the properties of the more exotic 'temporal'
134 // constructors and predicates (those prefixed 'Now').
135 //
136 //
137 // IMPLEMENTATION
138 //
139 // Internally, all 'primitive' types, and their unions, are represented as
140 // bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the
141 // respective map. Only structured types require allocation.
142 // Note that the bitset representation is closed under both Union and Intersect.
143 //
144 // There are two type representations, using different allocation:
145 //
146 // - class Type (zone-allocated, for compiler and concurrent compilation)
147 // - class HeapType (heap-allocated, for persistent types)
148 //
149 // Both provide the same API, and the Convert method can be used to interconvert
150 // them. For zone types, no query method touches the heap, only constructors do.
151 
152 
153 // -----------------------------------------------------------------------------
154 // Values for bitset types
155 
156 #define MASK_BITSET_TYPE_LIST(V) \
157   V(Representation, 0xff800000u) \
158   V(Semantic,       0x007ffffeu)
159 
160 #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
161 #define SEMANTIC(k)       ((k) & BitsetType::kSemantic)
162 
163 #define REPRESENTATION_BITSET_TYPE_LIST(V) \
164   V(None,             0)                   \
165   V(UntaggedInt1,     1u << 23 | kSemantic) \
166   V(UntaggedInt8,     1u << 24 | kSemantic) \
167   V(UntaggedInt16,    1u << 25 | kSemantic) \
168   V(UntaggedInt32,    1u << 26 | kSemantic) \
169   V(UntaggedFloat32,  1u << 27 | kSemantic) \
170   V(UntaggedFloat64,  1u << 28 | kSemantic) \
171   V(UntaggedPtr,      1u << 29 | kSemantic) \
172   V(TaggedInt,        1u << 30 | kSemantic) \
173   V(TaggedPtr,        1u << 31 | kSemantic) \
174   \
175   V(UntaggedInt,      kUntaggedInt1 | kUntaggedInt8 |      \
176                       kUntaggedInt16 | kUntaggedInt32)     \
177   V(UntaggedFloat,    kUntaggedFloat32 | kUntaggedFloat64) \
178   V(UntaggedNumber,   kUntaggedInt | kUntaggedFloat)       \
179   V(Untagged,         kUntaggedNumber | kUntaggedPtr)      \
180   V(Tagged,           kTaggedInt | kTaggedPtr)
181 
182 #define SEMANTIC_BITSET_TYPE_LIST(V) \
183   V(Null,                1u << 1  | REPRESENTATION(kTaggedPtr)) \
184   V(Undefined,           1u << 2  | REPRESENTATION(kTaggedPtr)) \
185   V(Boolean,             1u << 3  | REPRESENTATION(kTaggedPtr)) \
186   V(UnsignedSmall,       1u << 4  | REPRESENTATION(kTagged | kUntaggedNumber)) \
187   V(OtherSignedSmall,    1u << 5  | REPRESENTATION(kTagged | kUntaggedNumber)) \
188   V(OtherUnsigned31,     1u << 6  | REPRESENTATION(kTagged | kUntaggedNumber)) \
189   V(OtherUnsigned32,     1u << 7  | REPRESENTATION(kTagged | kUntaggedNumber)) \
190   V(OtherSigned32,       1u << 8  | REPRESENTATION(kTagged | kUntaggedNumber)) \
191   V(MinusZero,           1u << 9  | REPRESENTATION(kTagged | kUntaggedNumber)) \
192   V(NaN,                 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
193   V(OtherNumber,         1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \
194   V(Symbol,              1u << 12 | REPRESENTATION(kTaggedPtr)) \
195   V(InternalizedString,  1u << 13 | REPRESENTATION(kTaggedPtr)) \
196   V(OtherString,         1u << 14 | REPRESENTATION(kTaggedPtr)) \
197   V(Undetectable,        1u << 15 | REPRESENTATION(kTaggedPtr)) \
198   V(Array,               1u << 16 | REPRESENTATION(kTaggedPtr)) \
199   V(Buffer,              1u << 17 | REPRESENTATION(kTaggedPtr)) \
200   V(Function,            1u << 18 | REPRESENTATION(kTaggedPtr)) \
201   V(RegExp,              1u << 19 | REPRESENTATION(kTaggedPtr)) \
202   V(OtherObject,         1u << 20 | REPRESENTATION(kTaggedPtr)) \
203   V(Proxy,               1u << 21 | REPRESENTATION(kTaggedPtr)) \
204   V(Internal,            1u << 22 | REPRESENTATION(kTagged | kUntagged)) \
205   \
206   V(SignedSmall,         kUnsignedSmall | kOtherSignedSmall) \
207   V(Signed32,            kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \
208   V(Unsigned32,          kUnsignedSmall | kOtherUnsigned31 | kOtherUnsigned32) \
209   V(Integral32,          kSigned32 | kUnsigned32) \
210   V(OrderedNumber,       kIntegral32 | kMinusZero | kOtherNumber) \
211   V(Number,              kOrderedNumber | kNaN) \
212   V(String,              kInternalizedString | kOtherString) \
213   V(UniqueName,          kSymbol | kInternalizedString) \
214   V(Name,                kSymbol | kString) \
215   V(NumberOrString,      kNumber | kString) \
216   V(Primitive,           kNumber | kName | kBoolean | kNull | kUndefined) \
217   V(DetectableObject,    kArray | kFunction | kRegExp | kOtherObject) \
218   V(DetectableReceiver,  kDetectableObject | kProxy) \
219   V(Detectable,          kDetectableReceiver | kNumber | kName) \
220   V(Object,              kDetectableObject | kUndetectable) \
221   V(Receiver,            kObject | kProxy) \
222   V(NonNumber,           kBoolean | kName | kNull | kReceiver | \
223                          kUndefined | kInternal) \
224   V(Any,                 0xfffffffeu)
225 
226 /*
227  * The following diagrams show how integers (in the mathematical sense) are
228  * divided among the different atomic numerical types.
229  *
230  * If SmiValuesAre31Bits():
231  *
232  *   ON    OS32     OSS     US     OU31    OU32     ON
233  * ______[_______[_______[_______[_______[_______[_______
234  *     -2^31   -2^30     0      2^30    2^31    2^32
235  *
236  * Otherwise:
237  *
238  *   ON         OSS             US         OU32     ON
239  * ______[_______________[_______________[_______[_______
240  *     -2^31             0              2^31    2^32
241  *
242  *
243  * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
244  *
245  */
246 
247 #define PROPER_BITSET_TYPE_LIST(V) \
248   REPRESENTATION_BITSET_TYPE_LIST(V) \
249   SEMANTIC_BITSET_TYPE_LIST(V)
250 
251 #define BITSET_TYPE_LIST(V) \
252   MASK_BITSET_TYPE_LIST(V) \
253   PROPER_BITSET_TYPE_LIST(V)
254 
255 
256 // -----------------------------------------------------------------------------
257 // The abstract Type class, parameterized over the low-level representation.
258 
259 // struct Config {
260 //   typedef TypeImpl<Config> Type;
261 //   typedef Base;
262 //   typedef Struct;
263 //   typedef Region;
264 //   template<class> struct Handle { typedef type; }  // No template typedefs...
265 //   template<class T> static Handle<T>::type handle(T* t);  // !is_bitset(t)
266 //   template<class T> static Handle<T>::type cast(Handle<Type>::type);
267 //   static bool is_bitset(Type*);
268 //   static bool is_class(Type*);
269 //   static bool is_struct(Type*, int tag);
270 //   static bitset as_bitset(Type*);
271 //   static i::Handle<i::Map> as_class(Type*);
272 //   static Handle<Struct>::type as_struct(Type*);
273 //   static Type* from_bitset(bitset);
274 //   static Handle<Type>::type from_bitset(bitset, Region*);
275 //   static Handle<Type>::type from_class(i::Handle<Map>, Region*);
276 //   static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
277 //   static Handle<Struct>::type struct_create(int tag, int length, Region*);
278 //   static void struct_shrink(Handle<Struct>::type, int length);
279 //   static int struct_tag(Handle<Struct>::type);
280 //   static int struct_length(Handle<Struct>::type);
281 //   static Handle<Type>::type struct_get(Handle<Struct>::type, int);
282 //   static void struct_set(Handle<Struct>::type, int, Handle<Type>::type);
283 //   template<class V>
284 //   static i::Handle<V> struct_get_value(Handle<Struct>::type, int);
285 //   template<class V>
286 //   static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>);
287 // }
288 template<class Config>
289 class TypeImpl : public Config::Base {
290  public:
291   // Auxiliary types.
292 
293   typedef uint32_t bitset;  // Internal
294   class BitsetType;         // Internal
295   class StructuralType;     // Internal
296   class UnionType;          // Internal
297 
298   class ClassType;
299   class ConstantType;
300   class RangeType;
301   class ContextType;
302   class ArrayType;
303   class FunctionType;
304 
305   typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
306   typedef typename Config::template Handle<ClassType>::type ClassHandle;
307   typedef typename Config::template Handle<ConstantType>::type ConstantHandle;
308   typedef typename Config::template Handle<RangeType>::type RangeHandle;
309   typedef typename Config::template Handle<ContextType>::type ContextHandle;
310   typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
311   typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
312   typedef typename Config::template Handle<UnionType>::type UnionHandle;
313   typedef typename Config::Region Region;
314 
315   // Constructors.
316 
317   #define DEFINE_TYPE_CONSTRUCTOR(type, value)                                \
318     static TypeImpl* type() {                                                 \
319       return BitsetType::New(BitsetType::k##type);                            \
320     }                                                                         \
321     static TypeHandle type(Region* region) {                                  \
322       return BitsetType::New(BitsetType::k##type, region);                    \
323     }
PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)324   PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
325   #undef DEFINE_TYPE_CONSTRUCTOR
326 
327   static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
328     return ClassType::New(map, region);
329   }
Constant(i::Handle<i::Object> value,Region * region)330   static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
331     return ConstantType::New(value, region);
332   }
Range(i::Handle<i::Object> min,i::Handle<i::Object> max,Region * region)333   static TypeHandle Range(
334       i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
335     return RangeType::New(min, max, region);
336   }
Context(TypeHandle outer,Region * region)337   static TypeHandle Context(TypeHandle outer, Region* region) {
338     return ContextType::New(outer, region);
339   }
Array(TypeHandle element,Region * region)340   static TypeHandle Array(TypeHandle element, Region* region) {
341     return ArrayType::New(element, region);
342   }
Function(TypeHandle result,TypeHandle receiver,int arity,Region * region)343   static FunctionHandle Function(
344       TypeHandle result, TypeHandle receiver, int arity, Region* region) {
345     return FunctionType::New(result, receiver, arity, region);
346   }
Function(TypeHandle result,Region * region)347   static TypeHandle Function(TypeHandle result, Region* region) {
348     return Function(result, Any(region), 0, region);
349   }
Function(TypeHandle result,TypeHandle param0,Region * region)350   static TypeHandle Function(
351       TypeHandle result, TypeHandle param0, Region* region) {
352     FunctionHandle function = Function(result, Any(region), 1, region);
353     function->InitParameter(0, param0);
354     return function;
355   }
Function(TypeHandle result,TypeHandle param0,TypeHandle param1,Region * region)356   static TypeHandle Function(
357       TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) {
358     FunctionHandle function = Function(result, Any(region), 2, region);
359     function->InitParameter(0, param0);
360     function->InitParameter(1, param1);
361     return function;
362   }
Function(TypeHandle result,TypeHandle param0,TypeHandle param1,TypeHandle param2,Region * region)363   static TypeHandle Function(
364       TypeHandle result, TypeHandle param0, TypeHandle param1,
365       TypeHandle param2, Region* region) {
366     FunctionHandle function = Function(result, Any(region), 3, region);
367     function->InitParameter(0, param0);
368     function->InitParameter(1, param1);
369     function->InitParameter(2, param2);
370     return function;
371   }
372 
373   static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
374   static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
375 
Of(double value,Region * region)376   static TypeHandle Of(double value, Region* region) {
377     return Config::from_bitset(BitsetType::Lub(value), region);
378   }
Of(i::Object * value,Region * region)379   static TypeHandle Of(i::Object* value, Region* region) {
380     return Config::from_bitset(BitsetType::Lub(value), region);
381   }
Of(i::Handle<i::Object> value,Region * region)382   static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
383     return Of(*value, region);
384   }
385 
386   // Predicates.
387 
IsInhabited()388   bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
389 
Is(TypeImpl * that)390   bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
391   template<class TypeHandle>
Is(TypeHandle that)392   bool Is(TypeHandle that) { return this->Is(*that); }
393 
394   bool Maybe(TypeImpl* that);
395   template<class TypeHandle>
Maybe(TypeHandle that)396   bool Maybe(TypeHandle that) { return this->Maybe(*that); }
397 
Equals(TypeImpl * that)398   bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); }
399   template<class TypeHandle>
Equals(TypeHandle that)400   bool Equals(TypeHandle that) { return this->Equals(*that); }
401 
402   // Equivalent to Constant(val)->Is(this), but avoiding allocation.
403   bool Contains(i::Object* val);
Contains(i::Handle<i::Object> val)404   bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
405 
406   // State-dependent versions of the above that consider subtyping between
407   // a constant and its map class.
408   inline static TypeHandle NowOf(i::Object* value, Region* region);
NowOf(i::Handle<i::Object> value,Region * region)409   static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) {
410     return NowOf(*value, region);
411   }
412   bool NowIs(TypeImpl* that);
413   template<class TypeHandle>
NowIs(TypeHandle that)414   bool NowIs(TypeHandle that)  { return this->NowIs(*that); }
415   inline bool NowContains(i::Object* val);
NowContains(i::Handle<i::Object> val)416   bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
417 
418   bool NowStable();
419 
420   // Inspection.
421 
IsClass()422   bool IsClass() {
423     return Config::is_class(this)
424         || Config::is_struct(this, StructuralType::kClassTag);
425   }
IsConstant()426   bool IsConstant() {
427     return Config::is_struct(this, StructuralType::kConstantTag);
428   }
IsRange()429   bool IsRange() {
430     return Config::is_struct(this, StructuralType::kRangeTag);
431   }
IsContext()432   bool IsContext() {
433     return Config::is_struct(this, StructuralType::kContextTag);
434   }
IsArray()435   bool IsArray() {
436     return Config::is_struct(this, StructuralType::kArrayTag);
437   }
IsFunction()438   bool IsFunction() {
439     return Config::is_struct(this, StructuralType::kFunctionTag);
440   }
441 
AsClass()442   ClassType* AsClass() { return ClassType::cast(this); }
AsConstant()443   ConstantType* AsConstant() { return ConstantType::cast(this); }
AsRange()444   RangeType* AsRange() { return RangeType::cast(this); }
AsContext()445   ContextType* AsContext() { return ContextType::cast(this); }
AsArray()446   ArrayType* AsArray() { return ArrayType::cast(this); }
AsFunction()447   FunctionType* AsFunction() { return FunctionType::cast(this); }
448 
449   // Minimum and maximum of a numeric type.
450   // These functions do not distinguish between -0 and +0.  If the type equals
451   // kNaN, they return NaN; otherwise kNaN is ignored.  Only call these
452   // functions on subtypes of Number.
453   double Min();
454   double Max();
455 
456   int NumClasses();
457   int NumConstants();
458 
459   template<class T> class Iterator;
Classes()460   Iterator<i::Map> Classes() {
461     if (this->IsBitset()) return Iterator<i::Map>();
462     return Iterator<i::Map>(Config::handle(this));
463   }
Constants()464   Iterator<i::Object> Constants() {
465     if (this->IsBitset()) return Iterator<i::Object>();
466     return Iterator<i::Object>(Config::handle(this));
467   }
468 
469   // Casting and conversion.
470 
471   static inline TypeImpl* cast(typename Config::Base* object);
472 
473   template<class OtherTypeImpl>
474   static TypeHandle Convert(
475       typename OtherTypeImpl::TypeHandle type, Region* region);
476 
477   // Printing.
478 
479   enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
480 
481   void PrintTo(OStream& os, PrintDimension dim = BOTH_DIMS);  // NOLINT
482 
483 #ifdef DEBUG
484   void Print();
485 #endif
486 
487  protected:
488   // Friends.
489 
490   template<class> friend class Iterator;
491   template<class> friend class TypeImpl;
492 
493   // Handle conversion.
494 
495   template<class T>
handle(T * type)496   static typename Config::template Handle<T>::type handle(T* type) {
497     return Config::handle(type);
498   }
unhandle()499   TypeImpl* unhandle() { return this; }
500 
501   // Internal inspection.
502 
IsNone()503   bool IsNone() { return this == None(); }
IsAny()504   bool IsAny() { return this == Any(); }
IsBitset()505   bool IsBitset() { return Config::is_bitset(this); }
IsUnion()506   bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
507 
AsBitset()508   bitset AsBitset() {
509     DCHECK(this->IsBitset());
510     return static_cast<BitsetType*>(this)->Bitset();
511   }
AsUnion()512   UnionType* AsUnion() { return UnionType::cast(this); }
513 
514   // Auxiliary functions.
515 
BitsetGlb()516   bitset BitsetGlb() { return BitsetType::Glb(this); }
BitsetLub()517   bitset BitsetLub() { return BitsetType::Lub(this); }
518 
519   bool SlowIs(TypeImpl* that);
520 
IsInteger(double x)521   static bool IsInteger(double x) {
522     return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
523   }
IsInteger(i::Object * x)524   static bool IsInteger(i::Object* x) {
525     return x->IsNumber() && IsInteger(x->Number());
526   }
527 
528   struct Limits {
529     i::Handle<i::Object> min;
530     i::Handle<i::Object> max;
LimitsLimits531     Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) :
532       min(min), max(max) {}
LimitsLimits533     explicit Limits(RangeType* range) :
534       min(range->Min()), max(range->Max()) {}
535   };
536 
537   static Limits Intersect(Limits lhs, Limits rhs);
538   static Limits Union(Limits lhs, Limits rhs);
539   static bool Overlap(RangeType* lhs, RangeType* rhs);
540   static bool Contains(RangeType* lhs, RangeType* rhs);
541   static bool Contains(RangeType* range, i::Object* val);
542 
543   RangeType* GetRange();
544   static int UpdateRange(
545       RangeHandle type, UnionHandle result, int size, Region* region);
546 
547   bool SimplyEquals(TypeImpl* that);
548   template<class TypeHandle>
SimplyEquals(TypeHandle that)549   bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); }
550 
551   static int AddToUnion(
552       TypeHandle type, UnionHandle result, int size, Region* region);
553   static int IntersectAux(
554       TypeHandle type, TypeHandle other,
555       UnionHandle result, int size, Region* region);
556   static TypeHandle NormalizeUnion(UnionHandle unioned, int size);
557 };
558 
559 
560 // -----------------------------------------------------------------------------
561 // Bitset types (internal).
562 
563 template<class Config>
564 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
565  protected:
566   friend class TypeImpl<Config>;
567 
568   enum {
569     #define DECLARE_TYPE(type, value) k##type = (value),
570     BITSET_TYPE_LIST(DECLARE_TYPE)
571     #undef DECLARE_TYPE
572     kUnusedEOL = 0
573   };
574 
Bitset()575   bitset Bitset() { return Config::as_bitset(this); }
576 
New(bitset bits)577   static TypeImpl* New(bitset bits) {
578     DCHECK(bits == kNone || IsInhabited(bits));
579     return Config::from_bitset(bits);
580   }
New(bitset bits,Region * region)581   static TypeHandle New(bitset bits, Region* region) {
582     DCHECK(bits == kNone || IsInhabited(bits));
583     return Config::from_bitset(bits, region);
584   }
585   // TODO(neis): Eventually allow again for types with empty semantics
586   // part and modify intersection and possibly subtyping accordingly.
587 
IsInhabited(bitset bits)588   static bool IsInhabited(bitset bits) {
589     return bits & kSemantic;
590   }
591 
Is(bitset bits1,bitset bits2)592   static bool Is(bitset bits1, bitset bits2) {
593     return (bits1 | bits2) == bits2;
594   }
595 
596   static double Min(bitset);
597   static double Max(bitset);
598 
599   static bitset Glb(TypeImpl* type);  // greatest lower bound that's a bitset
600   static bitset Lub(TypeImpl* type);  // least upper bound that's a bitset
601   static bitset Lub(i::Object* value);
602   static bitset Lub(double value);
603   static bitset Lub(int32_t value);
604   static bitset Lub(uint32_t value);
605   static bitset Lub(i::Map* map);
606   static bitset Lub(Limits lim);
607 
608   static const char* Name(bitset);
609   static void Print(OStream& os, bitset);  // NOLINT
610 #ifdef DEBUG
611   static void Print(bitset);
612 #endif
613 
614  private:
615   struct BitsetMin{
616     bitset bits;
617     double min;
618   };
619   static const BitsetMin BitsetMins31[];
620   static const BitsetMin BitsetMins32[];
BitsetMins()621   static const BitsetMin* BitsetMins() {
622     return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32;
623   }
BitsetMinsSize()624   static size_t BitsetMinsSize() {
625     return i::SmiValuesAre31Bits() ? 7 : 5;
626     /* arraysize(BitsetMins31) : arraysize(BitsetMins32); */
627     // Using arraysize here doesn't compile on Windows.
628   }
629 };
630 
631 
632 // -----------------------------------------------------------------------------
633 // Superclass for non-bitset types (internal).
634 // Contains a tag and a variable number of type or value fields.
635 
636 template<class Config>
637 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
638  protected:
639   template<class> friend class TypeImpl;
640   friend struct ZoneTypeConfig;  // For tags.
641   friend struct HeapTypeConfig;
642 
643   enum Tag {
644     kClassTag,
645     kConstantTag,
646     kRangeTag,
647     kContextTag,
648     kArrayTag,
649     kFunctionTag,
650     kUnionTag
651   };
652 
Length()653   int Length() {
654     return Config::struct_length(Config::as_struct(this));
655   }
Get(int i)656   TypeHandle Get(int i) {
657     DCHECK(0 <= i && i < this->Length());
658     return Config::struct_get(Config::as_struct(this), i);
659   }
Set(int i,TypeHandle type)660   void Set(int i, TypeHandle type) {
661     DCHECK(0 <= i && i < this->Length());
662     Config::struct_set(Config::as_struct(this), i, type);
663   }
Shrink(int length)664   void Shrink(int length) {
665     DCHECK(2 <= length && length <= this->Length());
666     Config::struct_shrink(Config::as_struct(this), length);
667   }
GetValue(int i)668   template<class V> i::Handle<V> GetValue(int i) {
669     DCHECK(0 <= i && i < this->Length());
670     return Config::template struct_get_value<V>(Config::as_struct(this), i);
671   }
SetValue(int i,i::Handle<V> x)672   template<class V> void SetValue(int i, i::Handle<V> x) {
673     DCHECK(0 <= i && i < this->Length());
674     Config::struct_set_value(Config::as_struct(this), i, x);
675   }
676 
New(Tag tag,int length,Region * region)677   static TypeHandle New(Tag tag, int length, Region* region) {
678     DCHECK(1 <= length);
679     return Config::from_struct(Config::struct_create(tag, length, region));
680   }
681 };
682 
683 
684 // -----------------------------------------------------------------------------
685 // Union types (internal).
686 // A union is a structured type with the following invariants:
687 // - its length is at least 2
688 // - at most one field is a bitset, and it must go into index 0
689 // - no field is a union
690 // - no field is a subtype of any other field
691 template<class Config>
692 class TypeImpl<Config>::UnionType : public StructuralType {
693  public:
New(int length,Region * region)694   static UnionHandle New(int length, Region* region) {
695     return Config::template cast<UnionType>(
696         StructuralType::New(StructuralType::kUnionTag, length, region));
697   }
698 
cast(TypeImpl * type)699   static UnionType* cast(TypeImpl* type) {
700     DCHECK(type->IsUnion());
701     return static_cast<UnionType*>(type);
702   }
703 
704   bool Wellformed();
705 };
706 
707 
708 // -----------------------------------------------------------------------------
709 // Class types.
710 
711 template<class Config>
712 class TypeImpl<Config>::ClassType : public StructuralType {
713  public:
Bound(Region * region)714   TypeHandle Bound(Region* region) {
715     return Config::is_class(this) ?
716         BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) :
717         this->Get(0);
718   }
Map()719   i::Handle<i::Map> Map() {
720     return Config::is_class(this) ? Config::as_class(this) :
721         this->template GetValue<i::Map>(1);
722   }
723 
New(i::Handle<i::Map> map,Region * region)724   static ClassHandle New(i::Handle<i::Map> map, Region* region) {
725     ClassHandle type =
726         Config::template cast<ClassType>(Config::from_class(map, region));
727     if (!type->IsClass()) {
728       type = Config::template cast<ClassType>(
729           StructuralType::New(StructuralType::kClassTag, 2, region));
730       type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
731       type->SetValue(1, map);
732     }
733     return type;
734   }
735 
cast(TypeImpl * type)736   static ClassType* cast(TypeImpl* type) {
737     DCHECK(type->IsClass());
738     return static_cast<ClassType*>(type);
739   }
740 };
741 
742 
743 // -----------------------------------------------------------------------------
744 // Constant types.
745 
746 template<class Config>
747 class TypeImpl<Config>::ConstantType : public StructuralType {
748  public:
Bound()749   TypeHandle Bound() { return this->Get(0); }
Value()750   i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
751 
New(i::Handle<i::Object> value,Region * region)752   static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
753     ConstantHandle type = Config::template cast<ConstantType>(
754         StructuralType::New(StructuralType::kConstantTag, 2, region));
755     type->Set(0, BitsetType::New(BitsetType::Lub(*value), region));
756     type->SetValue(1, value);
757     return type;
758   }
759 
cast(TypeImpl * type)760   static ConstantType* cast(TypeImpl* type) {
761     DCHECK(type->IsConstant());
762     return static_cast<ConstantType*>(type);
763   }
764 };
765 // TODO(neis): Also cache value if numerical.
766 // TODO(neis): Allow restricting the representation.
767 
768 
769 // -----------------------------------------------------------------------------
770 // Range types.
771 
772 template<class Config>
773 class TypeImpl<Config>::RangeType : public StructuralType {
774  public:
BitsetLub()775   int BitsetLub() { return this->Get(0)->AsBitset(); }
Min()776   i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); }
Max()777   i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); }
778 
New(i::Handle<i::Object> min,i::Handle<i::Object> max,Region * region)779   static RangeHandle New(
780       i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
781     DCHECK(min->Number() <= max->Number());
782     RangeHandle type = Config::template cast<RangeType>(
783         StructuralType::New(StructuralType::kRangeTag, 3, region));
784     type->Set(0, BitsetType::New(BitsetType::Lub(Limits(min, max)), region));
785     type->SetValue(1, min);
786     type->SetValue(2, max);
787     return type;
788   }
789 
New(Limits lim,Region * region)790   static RangeHandle New(Limits lim, Region* region) {
791     return New(lim.min, lim.max, region);
792   }
793 
cast(TypeImpl * type)794   static RangeType* cast(TypeImpl* type) {
795     DCHECK(type->IsRange());
796     return static_cast<RangeType*>(type);
797   }
798 };
799 // TODO(neis): Also cache min and max values.
800 // TODO(neis): Allow restricting the representation.
801 
802 
803 // -----------------------------------------------------------------------------
804 // Context types.
805 
806 template<class Config>
807 class TypeImpl<Config>::ContextType : public StructuralType {
808  public:
Outer()809   TypeHandle Outer() { return this->Get(0); }
810 
New(TypeHandle outer,Region * region)811   static ContextHandle New(TypeHandle outer, Region* region) {
812     ContextHandle type = Config::template cast<ContextType>(
813         StructuralType::New(StructuralType::kContextTag, 1, region));
814     type->Set(0, outer);
815     return type;
816   }
817 
cast(TypeImpl * type)818   static ContextType* cast(TypeImpl* type) {
819     DCHECK(type->IsContext());
820     return static_cast<ContextType*>(type);
821   }
822 };
823 
824 
825 // -----------------------------------------------------------------------------
826 // Array types.
827 
828 template<class Config>
829 class TypeImpl<Config>::ArrayType : public StructuralType {
830  public:
Element()831   TypeHandle Element() { return this->Get(0); }
832 
New(TypeHandle element,Region * region)833   static ArrayHandle New(TypeHandle element, Region* region) {
834     ArrayHandle type = Config::template cast<ArrayType>(
835         StructuralType::New(StructuralType::kArrayTag, 1, region));
836     type->Set(0, element);
837     return type;
838   }
839 
cast(TypeImpl * type)840   static ArrayType* cast(TypeImpl* type) {
841     DCHECK(type->IsArray());
842     return static_cast<ArrayType*>(type);
843   }
844 };
845 
846 
847 // -----------------------------------------------------------------------------
848 // Function types.
849 
850 template<class Config>
851 class TypeImpl<Config>::FunctionType : public StructuralType {
852  public:
Arity()853   int Arity() { return this->Length() - 2; }
Result()854   TypeHandle Result() { return this->Get(0); }
Receiver()855   TypeHandle Receiver() { return this->Get(1); }
Parameter(int i)856   TypeHandle Parameter(int i) { return this->Get(2 + i); }
857 
InitParameter(int i,TypeHandle type)858   void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
859 
New(TypeHandle result,TypeHandle receiver,int arity,Region * region)860   static FunctionHandle New(
861       TypeHandle result, TypeHandle receiver, int arity, Region* region) {
862     FunctionHandle type = Config::template cast<FunctionType>(
863         StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
864     type->Set(0, result);
865     type->Set(1, receiver);
866     return type;
867   }
868 
cast(TypeImpl * type)869   static FunctionType* cast(TypeImpl* type) {
870     DCHECK(type->IsFunction());
871     return static_cast<FunctionType*>(type);
872   }
873 };
874 
875 
876 // -----------------------------------------------------------------------------
877 // Type iterators.
878 
879 template<class Config> template<class T>
880 class TypeImpl<Config>::Iterator {
881  public:
Done()882   bool Done() const { return index_ < 0; }
883   i::Handle<T> Current();
884   void Advance();
885 
886  private:
887   template<class> friend class TypeImpl;
888 
Iterator()889   Iterator() : index_(-1) {}
Iterator(TypeHandle type)890   explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
891     Advance();
892   }
893 
894   inline bool matches(TypeHandle type);
895   inline TypeHandle get_type();
896 
897   TypeHandle type_;
898   int index_;
899 };
900 
901 
902 // -----------------------------------------------------------------------------
903 // Zone-allocated types; they are either (odd) integers to represent bitsets, or
904 // (even) pointers to structures for everything else.
905 
906 struct ZoneTypeConfig {
907   typedef TypeImpl<ZoneTypeConfig> Type;
908   class Base {};
909   typedef void* Struct;
910   typedef i::Zone Region;
911   template<class T> struct Handle { typedef T* type; };
912 
913   template<class T> static inline T* handle(T* type);
914   template<class T> static inline T* cast(Type* type);
915 
916   static inline bool is_bitset(Type* type);
917   static inline bool is_class(Type* type);
918   static inline bool is_struct(Type* type, int tag);
919 
920   static inline Type::bitset as_bitset(Type* type);
921   static inline i::Handle<i::Map> as_class(Type* type);
922   static inline Struct* as_struct(Type* type);
923 
924   static inline Type* from_bitset(Type::bitset);
925   static inline Type* from_bitset(Type::bitset, Zone* zone);
926   static inline Type* from_class(i::Handle<i::Map> map, Zone* zone);
927   static inline Type* from_struct(Struct* structured);
928 
929   static inline Struct* struct_create(int tag, int length, Zone* zone);
930   static inline void struct_shrink(Struct* structure, int length);
931   static inline int struct_tag(Struct* structure);
932   static inline int struct_length(Struct* structure);
933   static inline Type* struct_get(Struct* structure, int i);
934   static inline void struct_set(Struct* structure, int i, Type* type);
935   template<class V>
936   static inline i::Handle<V> struct_get_value(Struct* structure, int i);
937   template<class V> static inline void struct_set_value(
938       Struct* structure, int i, i::Handle<V> x);
939 };
940 
941 typedef TypeImpl<ZoneTypeConfig> Type;
942 
943 
944 // -----------------------------------------------------------------------------
945 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for
946 // constants, or fixed arrays for unions.
947 
948 struct HeapTypeConfig {
949   typedef TypeImpl<HeapTypeConfig> Type;
950   typedef i::Object Base;
951   typedef i::FixedArray Struct;
952   typedef i::Isolate Region;
953   template<class T> struct Handle { typedef i::Handle<T> type; };
954 
955   template<class T> static inline i::Handle<T> handle(T* type);
956   template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
957 
958   static inline bool is_bitset(Type* type);
959   static inline bool is_class(Type* type);
960   static inline bool is_struct(Type* type, int tag);
961 
962   static inline Type::bitset as_bitset(Type* type);
963   static inline i::Handle<i::Map> as_class(Type* type);
964   static inline i::Handle<Struct> as_struct(Type* type);
965 
966   static inline Type* from_bitset(Type::bitset);
967   static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate);
968   static inline i::Handle<Type> from_class(
969       i::Handle<i::Map> map, Isolate* isolate);
970   static inline i::Handle<Type> from_struct(i::Handle<Struct> structure);
971 
972   static inline i::Handle<Struct> struct_create(
973       int tag, int length, Isolate* isolate);
974   static inline void struct_shrink(i::Handle<Struct> structure, int length);
975   static inline int struct_tag(i::Handle<Struct> structure);
976   static inline int struct_length(i::Handle<Struct> structure);
977   static inline i::Handle<Type> struct_get(i::Handle<Struct> structure, int i);
978   static inline void struct_set(
979       i::Handle<Struct> structure, int i, i::Handle<Type> type);
980   template<class V>
981   static inline i::Handle<V> struct_get_value(
982       i::Handle<Struct> structure, int i);
983   template<class V>
984   static inline void struct_set_value(
985       i::Handle<Struct> structure, int i, i::Handle<V> x);
986 };
987 
988 typedef TypeImpl<HeapTypeConfig> HeapType;
989 
990 
991 // -----------------------------------------------------------------------------
992 // Type bounds. A simple struct to represent a pair of lower/upper types.
993 
994 template<class Config>
995 struct BoundsImpl {
996   typedef TypeImpl<Config> Type;
997   typedef typename Type::TypeHandle TypeHandle;
998   typedef typename Type::Region Region;
999 
1000   TypeHandle lower;
1001   TypeHandle upper;
1002 
BoundsImplBoundsImpl1003   BoundsImpl() {}
BoundsImplBoundsImpl1004   explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
BoundsImplBoundsImpl1005   BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
1006     DCHECK(lower->Is(upper));
1007   }
1008 
1009   // Unrestricted bounds.
UnboundedBoundsImpl1010   static BoundsImpl Unbounded(Region* region) {
1011     return BoundsImpl(Type::None(region), Type::Any(region));
1012   }
1013 
1014   // Meet: both b1 and b2 are known to hold.
BothBoundsImpl1015   static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
1016     TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
1017     TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
1018     // Lower bounds are considered approximate, correct as necessary.
1019     lower = Type::Intersect(lower, upper, region);
1020     return BoundsImpl(lower, upper);
1021   }
1022 
1023   // Join: either b1 or b2 is known to hold.
EitherBoundsImpl1024   static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
1025     TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
1026     TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
1027     return BoundsImpl(lower, upper);
1028   }
1029 
NarrowLowerBoundsImpl1030   static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
1031     // Lower bounds are considered approximate, correct as necessary.
1032     t = Type::Intersect(t, b.upper, region);
1033     TypeHandle lower = Type::Union(b.lower, t, region);
1034     return BoundsImpl(lower, b.upper);
1035   }
NarrowUpperBoundsImpl1036   static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) {
1037     TypeHandle lower = Type::Intersect(b.lower, t, region);
1038     TypeHandle upper = Type::Intersect(b.upper, t, region);
1039     return BoundsImpl(lower, upper);
1040   }
1041 
NarrowsBoundsImpl1042   bool Narrows(BoundsImpl that) {
1043     return that.lower->Is(this->lower) && this->upper->Is(that.upper);
1044   }
1045 };
1046 
1047 typedef BoundsImpl<ZoneTypeConfig> Bounds;
1048 
1049 } }  // namespace v8::internal
1050 
1051 #endif  // V8_TYPES_H_
1052