V8 Project
types.h
Go to the documentation of this file.
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  }
325  #undef DEFINE_TYPE_CONSTRUCTOR
326 
328  return ClassType::New(map, region);
329  }
331  return ConstantType::New(value, region);
332  }
335  return RangeType::New(min, max, region);
336  }
337  static TypeHandle Context(TypeHandle outer, Region* region) {
338  return ContextType::New(outer, region);
339  }
340  static TypeHandle Array(TypeHandle element, Region* region) {
341  return ArrayType::New(element, region);
342  }
344  TypeHandle result, TypeHandle receiver, int arity, Region* region) {
345  return FunctionType::New(result, receiver, arity, region);
346  }
347  static TypeHandle Function(TypeHandle result, Region* region) {
348  return Function(result, Any(region), 0, region);
349  }
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  }
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  }
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 
376  static TypeHandle Of(double value, Region* region) {
377  return Config::from_bitset(BitsetType::Lub(value), region);
378  }
379  static TypeHandle Of(i::Object* value, Region* region) {
380  return Config::from_bitset(BitsetType::Lub(value), region);
381  }
382  static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
383  return Of(*value, region);
384  }
385 
386  // Predicates.
387 
388  bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
389 
390  bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
391  template<class TypeHandle>
392  bool Is(TypeHandle that) { return this->Is(*that); }
393 
394  bool Maybe(TypeImpl* that);
395  template<class TypeHandle>
396  bool Maybe(TypeHandle that) { return this->Maybe(*that); }
397 
398  bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); }
399  template<class TypeHandle>
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);
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);
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>
414  bool NowIs(TypeHandle that) { return this->NowIs(*that); }
415  inline bool NowContains(i::Object* val);
416  bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
417 
418  bool NowStable();
419 
420  // Inspection.
421 
422  bool IsClass() {
423  return Config::is_class(this)
424  || Config::is_struct(this, StructuralType::kClassTag);
425  }
426  bool IsConstant() {
427  return Config::is_struct(this, StructuralType::kConstantTag);
428  }
429  bool IsRange() {
430  return Config::is_struct(this, StructuralType::kRangeTag);
431  }
432  bool IsContext() {
433  return Config::is_struct(this, StructuralType::kContextTag);
434  }
435  bool IsArray() {
436  return Config::is_struct(this, StructuralType::kArrayTag);
437  }
438  bool IsFunction() {
439  return Config::is_struct(this, StructuralType::kFunctionTag);
440  }
441 
442  ClassType* AsClass() { return ClassType::cast(this); }
444  RangeType* AsRange() { return RangeType::cast(this); }
446  ArrayType* AsArray() { return ArrayType::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;
461  if (this->IsBitset()) return Iterator<i::Map>();
462  return Iterator<i::Map>(Config::handle(this));
463  }
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>
475  typename OtherTypeImpl::TypeHandle type, Region* region);
476 
477  // Printing.
478 
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>
496  static typename Config::template Handle<T>::type handle(T* type) {
497  return Config::handle(type);
498  }
499  TypeImpl* unhandle() { return this; }
500 
501  // Internal inspection.
502 
503  bool IsNone() { return this == None(); }
504  bool IsAny() { return this == Any(); }
505  bool IsBitset() { return Config::is_bitset(this); }
506  bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
507 
509  DCHECK(this->IsBitset());
510  return static_cast<BitsetType*>(this)->Bitset();
511  }
512  UnionType* AsUnion() { return UnionType::cast(this); }
513 
514  // Auxiliary functions.
515 
516  bitset BitsetGlb() { return BitsetType::Glb(this); }
517  bitset BitsetLub() { return BitsetType::Lub(this); }
518 
519  bool SlowIs(TypeImpl* that);
520 
521  static bool IsInteger(double x) {
522  return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
523  }
524  static bool IsInteger(i::Object* x) {
525  return x->IsNumber() && IsInteger(x->Number());
526  }
527 
528  struct Limits {
532  min(min), max(max) {}
533  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>
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),
571  #undef DECLARE_TYPE
572  kUnusedEOL = 0
573  };
574 
575  bitset Bitset() { return Config::as_bitset(this); }
576 
577  static TypeImpl* New(bitset bits) {
578  DCHECK(bits == kNone || IsInhabited(bits));
579  return Config::from_bitset(bits);
580  }
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 
588  static bool IsInhabited(bitset bits) {
589  return bits & kSemantic;
590  }
591 
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{
617  double min;
618  };
619  static const BitsetMin BitsetMins31[];
620  static const BitsetMin BitsetMins32[];
621  static const BitsetMin* BitsetMins() {
622  return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32;
623  }
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 {
650  kUnionTag
651  };
652 
653  int Length() {
654  return Config::struct_length(Config::as_struct(this));
655  }
656  TypeHandle Get(int i) {
657  DCHECK(0 <= i && i < this->Length());
658  return Config::struct_get(Config::as_struct(this), i);
659  }
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  }
664  void Shrink(int length) {
665  DCHECK(2 <= length && length <= this->Length());
666  Config::struct_shrink(Config::as_struct(this), length);
667  }
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  }
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 
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:
694  static UnionHandle New(int length, Region* region) {
695  return Config::template cast<UnionType>(
697  }
698 
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:
715  return Config::is_class(this) ?
716  BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) :
717  this->Get(0);
718  }
720  return Config::is_class(this) ? Config::as_class(this) :
721  this->template GetValue<i::Map>(1);
722  }
723 
725  ClassHandle type =
726  Config::template cast<ClassType>(Config::from_class(map, region));
727  if (!type->IsClass()) {
728  type = Config::template cast<ClassType>(
730  type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
731  type->SetValue(1, map);
732  }
733  return type;
734  }
735 
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>
748  public:
749  TypeHandle Bound() { return this->Get(0); }
750  i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
751 
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 
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>
774  public:
775  int BitsetLub() { return this->Get(0)->AsBitset(); }
776  i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); }
777  i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); }
778 
779  static RangeHandle New(
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 
790  static RangeHandle New(Limits lim, Region* region) {
791  return New(lim.min, lim.max, region);
792  }
793 
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>
808  public:
809  TypeHandle Outer() { return this->Get(0); }
810 
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 
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>
830  public:
831  TypeHandle Element() { return this->Get(0); }
832 
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 
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>
852  public:
853  int Arity() { return this->Length() - 2; }
854  TypeHandle Result() { return this->Get(0); }
855  TypeHandle Receiver() { return this->Get(1); }
856  TypeHandle Parameter(int i) { return this->Get(2 + i); }
857 
858  void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
859 
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 
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>
881  public:
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 
889  Iterator() : index_(-1) {}
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 
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 
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 
942 
943 
944 // -----------------------------------------------------------------------------
945 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for
946 // constants, or fixed arrays for unions.
947 
950  typedef i::Object Base;
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 
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 {
997  typedef typename Type::TypeHandle TypeHandle;
998  typedef typename Type::Region Region;
999 
1002 
1004  explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
1005  BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
1006  DCHECK(lower->Is(upper));
1007  }
1008 
1009  // Unrestricted bounds.
1010  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.
1015  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.
1024  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 
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  }
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 
1042  bool Narrows(BoundsImpl that) {
1043  return that.lower->Is(this->lower) && this->upper->Is(that.upper);
1044  }
1045 };
1046 
1048 
1049 } } // namespace v8::internal
1050 
1051 #endif // V8_TYPES_H_
static ArrayType * cast(TypeImpl *type)
Definition: types.h:840
static ArrayHandle New(TypeHandle element, Region *region)
Definition: types.h:833
static size_t BitsetMinsSize()
Definition: types.h:624
static bool Is(bitset bits1, bitset bits2)
Definition: types.h:592
static TypeImpl * New(bitset bits)
Definition: types.h:577
static bool IsInhabited(bitset bits)
Definition: types.h:588
static bitset Lub(TypeImpl *type)
Definition: types.cc:137
static TypeHandle New(bitset bits, Region *region)
Definition: types.h:581
static const BitsetMin * BitsetMins()
Definition: types.h:621
static bitset Glb(TypeImpl *type)
Definition: types.cc:120
i::Handle< i::Map > Map()
Definition: types.h:719
static ClassHandle New(i::Handle< i::Map > map, Region *region)
Definition: types.h:724
TypeHandle Bound(Region *region)
Definition: types.h:714
static ClassType * cast(TypeImpl *type)
Definition: types.h:736
static ConstantHandle New(i::Handle< i::Object > value, Region *region)
Definition: types.h:752
i::Handle< i::Object > Value()
Definition: types.h:750
static ConstantType * cast(TypeImpl *type)
Definition: types.h:760
static ContextHandle New(TypeHandle outer, Region *region)
Definition: types.h:811
static ContextType * cast(TypeImpl *type)
Definition: types.h:818
static FunctionHandle New(TypeHandle result, TypeHandle receiver, int arity, Region *region)
Definition: types.h:860
void InitParameter(int i, TypeHandle type)
Definition: types.h:858
static FunctionType * cast(TypeImpl *type)
Definition: types.h:869
TypeHandle Parameter(int i)
Definition: types.h:856
Iterator(TypeHandle type)
Definition: types.h:890
i::Handle< i::Object > Min()
Definition: types.h:776
i::Handle< i::Object > Max()
Definition: types.h:777
static RangeHandle New(Limits lim, Region *region)
Definition: types.h:790
static RangeType * cast(TypeImpl *type)
Definition: types.h:794
static RangeHandle New(i::Handle< i::Object > min, i::Handle< i::Object > max, Region *region)
Definition: types.h:779
void SetValue(int i, i::Handle< V > x)
Definition: types.h:672
void Set(int i, TypeHandle type)
Definition: types.h:660
i::Handle< V > GetValue(int i)
Definition: types.h:668
static TypeHandle New(Tag tag, int length, Region *region)
Definition: types.h:677
static UnionType * cast(TypeImpl *type)
Definition: types.h:699
static UnionHandle New(int length, Region *region)
Definition: types.h:694
Config::Region Region
Definition: types.h:313
static bool IsInteger(double x)
Definition: types.h:521
static TypeHandle Function(TypeHandle result, TypeHandle param0, TypeHandle param1, TypeHandle param2, Region *region)
Definition: types.h:363
Config::template Handle< ContextType >::type ContextHandle
Definition: types.h:309
bool Maybe(TypeHandle that)
Definition: types.h:396
UnionType * AsUnion()
Definition: types.h:512
Config::template Handle< RangeType >::type RangeHandle
Definition: types.h:308
Config::template Handle< FunctionType >::type FunctionHandle
Definition: types.h:311
static bool Contains(RangeType *lhs, RangeType *rhs)
static TypeHandle Of(double value, Region *region)
Definition: types.h:376
static TypeHandle NowOf(i::Handle< i::Object > value, Region *region)
Definition: types.h:409
static Config::template Handle< T >::type handle(T *type)
Definition: types.h:496
bool NowIs(TypeImpl *that)
Definition: types.cc:472
static TypeHandle Convert(typename OtherTypeImpl::TypeHandle type, Region *region)
static FunctionHandle Function(TypeHandle result, TypeHandle receiver, int arity, Region *region)
Definition: types.h:343
RangeType * AsRange()
Definition: types.h:444
bitset AsBitset()
Definition: types.h:508
ContextType * AsContext()
Definition: types.h:445
static TypeHandle NormalizeUnion(UnionHandle unioned, int size)
Definition: types.cc:808
Config::template Handle< TypeImpl >::type TypeHandle
Definition: types.h:303
Config::template Handle< ArrayType >::type ArrayHandle
Definition: types.h:310
static TypeHandle NowOf(i::Object *value, Region *region)
Definition: types-inl.h:30
ConstantType * AsConstant()
Definition: types.h:443
bool SimplyEquals(TypeHandle that)
Definition: types.h:549
static TypeHandle Of(i::Handle< i::Object > value, Region *region)
Definition: types.h:382
Iterator< i::Map > Classes()
Definition: types.h:460
static TypeHandle Array(TypeHandle element, Region *region)
Definition: types.h:340
bool Equals(TypeHandle that)
Definition: types.h:400
bool Is(TypeImpl *that)
Definition: types.h:390
bool SlowIs(TypeImpl *that)
Definition: types.cc:434
bool Is(TypeHandle that)
Definition: types.h:392
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:330
static bool Contains(RangeType *range, i::Object *val)
bool NowContains(i::Object *val)
Definition: types-inl.h:41
bool NowContains(i::Handle< i::Object > val)
Definition: types.h:416
Config::template Handle< ClassType >::type ClassHandle
Definition: types.h:306
ClassType * AsClass()
Definition: types.h:442
static TypeImpl * cast(typename Config::Base *object)
Definition: types-inl.h:20
bool Contains(i::Object *val)
Definition: types.cc:559
bool Equals(TypeImpl *that)
Definition: types.h:398
void PrintTo(OStream &os, PrintDimension dim=BOTH_DIMS)
Definition: types.cc:1034
RangeType * GetRange()
Definition: types.cc:548
bool SimplyEquals(TypeImpl *that)
Definition: types.cc:395
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:607
Config::template Handle< UnionType >::type UnionHandle
Definition: types.h:312
bool NowIs(TypeHandle that)
Definition: types.h:414
static TypeHandle Class(i::Handle< i::Map > map, Region *region)
Definition: types.h:327
static TypeHandle Function(TypeHandle result, TypeHandle param0, Region *region)
Definition: types.h:350
static bool IsInteger(i::Object *x)
Definition: types.h:524
static TypeHandle Range(i::Handle< i::Object > min, i::Handle< i::Object > max, Region *region)
Definition: types.h:333
static TypeHandle Function(TypeHandle result, Region *region)
Definition: types.h:347
ArrayType * AsArray()
Definition: types.h:446
Config::template Handle< ConstantType >::type ConstantHandle
Definition: types.h:307
TypeImpl * unhandle()
Definition: types.h:499
FunctionType * AsFunction()
Definition: types.h:447
bitset BitsetLub()
Definition: types.h:517
static TypeHandle Of(i::Object *value, Region *region)
Definition: types.h:379
static TypeHandle Function(TypeHandle result, TypeHandle param0, TypeHandle param1, Region *region)
Definition: types.h:356
Iterator< i::Object > Constants()
Definition: types.h:464
static int IntersectAux(TypeHandle type, TypeHandle other, UnionHandle result, int size, Region *region)
Definition: types.cc:680
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:737
static int AddToUnion(TypeHandle type, UnionHandle result, int size, Region *region)
Definition: types.cc:790
friend class Iterator
Definition: types.h:490
static bool Overlap(RangeType *lhs, RangeType *rhs)
Definition: types.cc:45
bool Maybe(TypeImpl *that)
Definition: types.cc:504
static TypeHandle Context(TypeHandle outer, Region *region)
Definition: types.h:337
static int UpdateRange(RangeHandle type, UnionHandle result, int size, Region *region)
Definition: types.cc:656
bitset BitsetGlb()
Definition: types.h:516
bool Contains(i::Handle< i::Object > val)
Definition: types.h:404
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object size
#define DCHECK(condition)
Definition: logging.h:205
int int32_t
Definition: unicode.cc:24
TypeImpl< ZoneTypeConfig > Type
static int min(int a, int b)
Definition: liveedit.cc:273
TypeImpl< HeapTypeConfig > HeapType
Definition: list.h:191
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
BoundsImpl< ZoneTypeConfig > Bounds
Definition: types.h:1047
static bool SmiValuesAre31Bits()
Definition: v8.h:5807
static bool IsMinusZero(double value)
Definition: conversions.h:154
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211
static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region *region)
Definition: types.h:1030
Type::Region Region
Definition: types.h:998
static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:1015
BoundsImpl(TypeHandle l, TypeHandle u)
Definition: types.h:1005
static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region *region)
Definition: types.h:1036
BoundsImpl(TypeHandle t)
Definition: types.h:1004
Type::TypeHandle TypeHandle
Definition: types.h:997
TypeImpl< Config > Type
Definition: types.h:996
static BoundsImpl Unbounded(Region *region)
Definition: types.h:1010
bool Narrows(BoundsImpl that)
Definition: types.h:1042
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:1024
TypeImpl< HeapTypeConfig > Type
Definition: types.h:949
i::FixedArray Struct
Definition: types.h:951
Limits(i::Handle< i::Object > min, i::Handle< i::Object > max)
Definition: types.h:531
i::Handle< i::Object > max
Definition: types.h:530
i::Handle< i::Object > min
Definition: types.h:529
Limits(RangeType *range)
Definition: types.h:533
TypeImpl< ZoneTypeConfig > Type
Definition: types.h:907
#define T(name, string, precedence)
Definition: token.cc:25
#define PROPER_BITSET_TYPE_LIST(V)
Definition: types.h:247
#define DECLARE_TYPE(type, value)
Definition: types.h:569
Tag
Definition: types.h:643
#define DEFINE_TYPE_CONSTRUCTOR(type, value)
Definition: types.h:317
#define BITSET_TYPE_LIST(V)
Definition: types.h:251