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