v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
types.h
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_TYPES_H_
29 #define V8_TYPES_H_
30 
31 #include "v8.h"
32 
33 #include "objects.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 
39 // A simple type system for compiler-internal use. It is based entirely on
40 // union types, and all subtyping hence amounts to set inclusion. Besides the
41 // obvious primitive types and some predefined unions, the type language also
42 // can express class types (a.k.a. specific maps) and singleton types (i.e.,
43 // concrete constants).
44 //
45 // Types consist of two dimensions: semantic (value range) and representation.
46 // Both are related through subtyping.
47 //
48 // The following equations and inequations hold for the semantic axis:
49 //
50 // None <= T
51 // T <= Any
52 //
53 // Oddball = Boolean \/ Null \/ Undefined
54 // Number = Signed32 \/ Unsigned32 \/ Double
55 // Smi <= Signed32
56 // Name = String \/ Symbol
57 // UniqueName = InternalizedString \/ Symbol
58 // InternalizedString < String
59 //
60 // Receiver = Object \/ Proxy
61 // Array < Object
62 // Function < Object
63 // RegExp < Object
64 // Undetectable < Object
65 // Detectable = Receiver \/ Number \/ Name - Undetectable
66 //
67 // Class(map) < T iff instance_type(map) < T
68 // Constant(x) < T iff instance_type(map(x)) < T
69 //
70 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
71 // change! (Its instance type cannot, however.)
72 // TODO(rossberg): the latter is not currently true for proxies, because of fix,
73 // but will hold once we implement direct proxies.
74 //
75 // For the representation axis, the following holds:
76 //
77 // None <= R
78 // R <= Any
79 //
80 // UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32)
81 // UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64
82 // UntaggedNumber <= UntaggedInt \/ UntaggedFloat
83 // Untagged <= UntaggedNumber \/ UntaggedPtr
84 // Tagged <= TaggedInt \/ TaggedPtr
85 //
86 // Subtyping relates the two dimensions, for example:
87 //
88 // Number <= Tagged \/ UntaggedNumber
89 // Object <= TaggedPtr \/ UntaggedPtr
90 //
91 // That holds because the semantic type constructors defined by the API create
92 // types that allow for all possible representations, and dually, the ones for
93 // representation types initially include all semantic ranges. Representations
94 // can then e.g. be narrowed for a given semantic type using intersection:
95 //
96 // SignedSmall /\ TaggedInt (a 'smi')
97 // Number /\ TaggedPtr (a heap number)
98 //
99 // There are two main functions for testing types:
100 //
101 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2)
102 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
103 //
104 // Typically, the former is to be used to select representations (e.g., via
105 // T->Is(SignedSmall())), and the latter to check whether a specific case needs
106 // handling (e.g., via T->Maybe(Number())).
107 //
108 // There is no functionality to discover whether a type is a leaf in the
109 // lattice. That is intentional. It should always be possible to refine the
110 // lattice (e.g., splitting up number types further) without invalidating any
111 // existing assumptions or tests.
112 // Consequently, do not use pointer equality for type tests, always use Is!
113 //
114 // Internally, all 'primitive' types, and their unions, are represented as
115 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or
116 // unions containing Class'es or Constant's, currently require allocation.
117 // Note that the bitset representation is closed under both Union and Intersect.
118 //
119 // There are two type representations, using different allocation:
120 //
121 // - class Type (zone-allocated, for compiler and concurrent compilation)
122 // - class HeapType (heap-allocated, for persistent types)
123 //
124 // Both provide the same API, and the Convert method can be used to interconvert
125 // them. For zone types, no query method touches the heap, only constructors do.
126 
127 
128 #define MASK_BITSET_TYPE_LIST(V) \
129  V(Representation, static_cast<int>(0xff800000)) \
130  V(Semantic, static_cast<int>(0x007fffff))
131 
132 #define REPRESENTATION(k) ((k) & kRepresentation)
133 #define SEMANTIC(k) ((k) & kSemantic)
134 
135 #define REPRESENTATION_BITSET_TYPE_LIST(V) \
136  V(None, 0) \
137  V(UntaggedInt8, 1 << 23 | kSemantic) \
138  V(UntaggedInt16, 1 << 24 | kSemantic) \
139  V(UntaggedInt32, 1 << 25 | kSemantic) \
140  V(UntaggedFloat32, 1 << 26 | kSemantic) \
141  V(UntaggedFloat64, 1 << 27 | kSemantic) \
142  V(UntaggedPtr, 1 << 28 | kSemantic) \
143  V(TaggedInt, 1 << 29 | kSemantic) \
144  V(TaggedPtr, -1 << 30 | kSemantic) /* MSB has to be sign-extended */ \
145  \
146  V(UntaggedInt, kUntaggedInt8 | kUntaggedInt16 | kUntaggedInt32) \
147  V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
148  V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \
149  V(Untagged, kUntaggedNumber | kUntaggedPtr) \
150  V(Tagged, kTaggedInt | kTaggedPtr)
151 
152 #define SEMANTIC_BITSET_TYPE_LIST(V) \
153  V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \
154  V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \
155  V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \
156  V(SignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
157  V(OtherSigned32, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
158  V(Unsigned32, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
159  V(Float, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
160  V(Symbol, 1 << 7 | REPRESENTATION(kTaggedPtr)) \
161  V(InternalizedString, 1 << 8 | REPRESENTATION(kTaggedPtr)) \
162  V(OtherString, 1 << 9 | REPRESENTATION(kTaggedPtr)) \
163  V(Undetectable, 1 << 10 | REPRESENTATION(kTaggedPtr)) \
164  V(Array, 1 << 11 | REPRESENTATION(kTaggedPtr)) \
165  V(Function, 1 << 12 | REPRESENTATION(kTaggedPtr)) \
166  V(RegExp, 1 << 13 | REPRESENTATION(kTaggedPtr)) \
167  V(OtherObject, 1 << 14 | REPRESENTATION(kTaggedPtr)) \
168  V(Proxy, 1 << 15 | REPRESENTATION(kTaggedPtr)) \
169  V(Internal, 1 << 16 | REPRESENTATION(kTagged | kUntagged)) \
170  \
171  V(Oddball, kBoolean | kNull | kUndefined) \
172  V(Signed32, kSignedSmall | kOtherSigned32) \
173  V(Number, kSigned32 | kUnsigned32 | kFloat) \
174  V(String, kInternalizedString | kOtherString) \
175  V(UniqueName, kSymbol | kInternalizedString) \
176  V(Name, kSymbol | kString) \
177  V(NumberOrString, kNumber | kString) \
178  V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \
179  V(DetectableReceiver, kDetectableObject | kProxy) \
180  V(Detectable, kDetectableReceiver | kNumber | kName) \
181  V(Object, kDetectableObject | kUndetectable) \
182  V(Receiver, kObject | kProxy) \
183  V(NonNumber, kOddball | kName | kReceiver | kInternal) \
184  V(Any, kNumber | kNonNumber)
185 
186 #define BITSET_TYPE_LIST(V) \
187  MASK_BITSET_TYPE_LIST(V) \
188  REPRESENTATION_BITSET_TYPE_LIST(V) \
189  SEMANTIC_BITSET_TYPE_LIST(V)
190 
191 
192 // struct Config {
193 // typedef Base;
194 // typedef Unioned;
195 // typedef Region;
196 // template<class> struct Handle { typedef type; } // No template typedefs...
197 // static Handle<Type>::type handle(Type* type); // !is_bitset(type)
198 // static bool is_bitset(Type*);
199 // static bool is_class(Type*);
200 // static bool is_constant(Type*);
201 // static bool is_union(Type*);
202 // static int as_bitset(Type*);
203 // static i::Handle<i::Map> as_class(Type*);
204 // static i::Handle<i::Object> as_constant(Type*);
205 // static Handle<Unioned>::type as_union(Type*);
206 // static Type* from_bitset(int bitset);
207 // static Handle<Type>::type from_bitset(int bitset, Region*);
208 // static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*);
209 // static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*);
210 // static Handle<Type>::type from_union(Handle<Unioned>::type);
211 // static Handle<Unioned>::type union_create(int size, Region*);
212 // static void union_shrink(Handle<Unioned>::type, int size);
213 // static Handle<Type>::type union_get(Handle<Unioned>::type, int);
214 // static void union_set(Handle<Unioned>::type, int, Handle<Type>::type);
215 // static int union_length(Handle<Unioned>::type);
216 // static int lub_bitset(Type*);
217 // }
218 template<class Config>
219 class TypeImpl : public Config::Base {
220  public:
221  typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
222  typedef typename Config::Region Region;
223 
224  #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
225  static TypeImpl* type() { return Config::from_bitset(k##type); } \
226  static TypeHandle type(Region* region) { \
227  return Config::from_bitset(k##type, region); \
228  }
230  #undef DEFINE_TYPE_CONSTRUCTOR
231 
233  return Config::from_class(map, LubBitset(*map), region);
234  }
236  return Config::from_constant(value, LubBitset(*value), region);
237  }
238 
239  static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
240  static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
241 
242  static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
243  return Config::from_bitset(LubBitset(*value), region);
244  }
245 
246  bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
247  template<class TypeHandle>
248  bool Is(TypeHandle that) { return this->Is(*that); }
249  bool Maybe(TypeImpl* that);
250  template<class TypeHandle>
251  bool Maybe(TypeHandle that) { return this->Maybe(*that); }
252 
253  // State-dependent versions of Of and Is that consider subtyping between
254  // a constant and its map class.
255  static TypeHandle OfCurrently(i::Handle<i::Object> value, Region* region);
256  bool IsCurrently(TypeImpl* that);
257  template<class TypeHandle>
258  bool IsCurrently(TypeHandle that) { return this->IsCurrently(*that); }
259 
260  bool IsClass() { return Config::is_class(this); }
261  bool IsConstant() { return Config::is_constant(this); }
262  i::Handle<i::Map> AsClass() { return Config::as_class(this); }
263  i::Handle<i::Object> AsConstant() { return Config::as_constant(this); }
264 
265  int NumClasses();
266  int NumConstants();
267 
268  template<class T>
269  class Iterator {
270  public:
271  bool Done() const { return index_ < 0; }
273  void Advance();
274 
275  private:
276  template<class> friend class TypeImpl;
277 
278  Iterator() : index_(-1) {}
279  explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
280  Advance();
281  }
282 
283  inline bool matches(TypeHandle type);
284  inline TypeHandle get_type();
285 
286  TypeHandle type_;
287  int index_;
288  };
289 
290  Iterator<i::Map> Classes() {
291  if (this->IsBitset()) return Iterator<i::Map>();
292  return Iterator<i::Map>(Config::handle(this));
293  }
294  Iterator<i::Object> Constants() {
295  if (this->IsBitset()) return Iterator<i::Object>();
296  return Iterator<i::Object>(Config::handle(this));
297  }
298 
299  static TypeImpl* cast(typename Config::Base* object) {
300  TypeImpl* t = static_cast<TypeImpl*>(object);
301  ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
302  return t;
303  }
304 
305  template<class OtherTypeImpl>
306  static TypeHandle Convert(
307  typename OtherTypeImpl::TypeHandle type, Region* region);
308 
309 #ifdef OBJECT_PRINT
310  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
311  void TypePrint(PrintDimension = BOTH_DIMS);
312  void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
313 #endif
314 
315  private:
316  template<class> friend class Iterator;
317  template<class> friend class TypeImpl;
318 
319  // A union is a fixed array containing types. Invariants:
320  // - its length is at least 2
321  // - at most one field is a bitset, and it must go into index 0
322  // - no field is a union
323  typedef typename Config::Unioned Unioned;
324  typedef typename Config::template Handle<Unioned>::type UnionedHandle;
325 
326  enum {
327  #define DECLARE_TYPE(type, value) k##type = (value),
329  #undef DECLARE_TYPE
330  kUnusedEOL = 0
331  };
332 
333  bool IsNone() { return this == None(); }
334  bool IsAny() { return this == Any(); }
335  bool IsBitset() { return Config::is_bitset(this); }
336  bool IsUnion() { return Config::is_union(this); }
337  int AsBitset() { return Config::as_bitset(this); }
338  UnionedHandle AsUnion() { return Config::as_union(this); }
339 
340  static int UnionLength(UnionedHandle unioned) {
341  return Config::union_length(unioned);
342  }
343  static TypeHandle UnionGet(UnionedHandle unioned, int i) {
344  return Config::union_get(unioned, i);
345  }
346 
347  bool SlowIs(TypeImpl* that);
348 
349  static bool IsInhabited(int bitset) {
350  return (bitset & kRepresentation) && (bitset & kSemantic);
351  }
352 
353  int LubBitset(); // least upper bound that's a bitset
354  int GlbBitset(); // greatest lower bound that's a bitset
355 
356  static int LubBitset(i::Object* value);
357  static int LubBitset(i::Map* map);
358 
359  bool InUnion(UnionedHandle unioned, int current_size);
360  static int ExtendUnion(
361  UnionedHandle unioned, TypeHandle t, int current_size);
362  static int ExtendIntersection(
363  UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size);
364 
365 #ifdef OBJECT_PRINT
366  static const char* bitset_name(int bitset);
367  static void BitsetTypePrint(FILE* out, int bitset);
368 #endif
369 };
370 
371 
372 // Zone-allocated types are either (odd) integers to represent bitsets, or
373 // (even) pointers to zone lists for everything else. The first slot of every
374 // list is an explicit tag value to distinguish representation.
376  private:
377  typedef i::ZoneList<void*> Tagged;
378 
379  enum Tag {
380  kClassTag,
381  kConstantTag,
382  kUnionTag
383  };
384 
385  static Tagged* tagged_create(Tag tag, int size, Zone* zone) {
386  Tagged* tagged = new(zone) Tagged(size + 1, zone);
387  tagged->Add(reinterpret_cast<void*>(tag), zone);
388  tagged->AddBlock(NULL, size, zone);
389  return tagged;
390  }
391  static void tagged_shrink(Tagged* tagged, int size) {
392  tagged->Rewind(size + 1);
393  }
394  static Tag tagged_tag(Tagged* tagged) {
395  return static_cast<Tag>(reinterpret_cast<intptr_t>(tagged->at(0)));
396  }
397  template<class T>
398  static T tagged_get(Tagged* tagged, int i) {
399  return reinterpret_cast<T>(tagged->at(i + 1));
400  }
401  template<class T>
402  static void tagged_set(Tagged* tagged, int i, T value) {
403  tagged->at(i + 1) = reinterpret_cast<void*>(value);
404  }
405  static int tagged_length(Tagged* tagged) {
406  return tagged->length() - 1;
407  }
408 
409  public:
411  class Base {};
413  typedef i::Zone Region;
414  template<class T> struct Handle { typedef T* type; };
415 
416  static Type* handle(Type* type) { return type; }
417 
418  static bool is(Type* type, Tag tag) {
419  return is_tagged(type) && tagged_tag(as_tagged(type)) == tag;
420  }
421 
422  static bool is_bitset(Type* type) {
423  return reinterpret_cast<intptr_t>(type) & 1;
424  }
425  static bool is_tagged(Type* type) { return !is_bitset(type); }
426  static bool is_class(Type* type) { return is(type, kClassTag); }
427  static bool is_constant(Type* type) { return is(type, kConstantTag); }
428  static bool is_union(Type* type) { return is(type, kUnionTag); }
429  static bool tagged_is_union(Tagged* tagged) {
430  return is(from_tagged(tagged), kUnionTag);
431  }
432 
433  static int as_bitset(Type* type) {
434  ASSERT(is_bitset(type));
435  return static_cast<int>(reinterpret_cast<intptr_t>(type) >> 1);
436  }
437  static Tagged* as_tagged(Type* type) {
438  ASSERT(is_tagged(type));
439  return reinterpret_cast<Tagged*>(type);
440  }
442  ASSERT(is_class(type));
443  return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 1));
444  }
446  ASSERT(is_constant(type));
447  return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 1));
448  }
449  static Unioned* as_union(Type* type) {
450  ASSERT(is_union(type));
451  return tagged_as_union(as_tagged(type));
452  }
453  static Unioned* tagged_as_union(Tagged* tagged) {
454  ASSERT(tagged_is_union(tagged));
455  return reinterpret_cast<Unioned*>(tagged);
456  }
457 
458  static Type* from_bitset(int bitset) {
459  return reinterpret_cast<Type*>((bitset << 1) | 1);
460  }
461  static Type* from_bitset(int bitset, Zone* Zone) {
462  return from_bitset(bitset);
463  }
464  static Type* from_tagged(Tagged* tagged) {
465  return reinterpret_cast<Type*>(tagged);
466  }
467  static Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone) {
468  Tagged* tagged = tagged_create(kClassTag, 2, zone);
469  tagged_set(tagged, 0, lub);
470  tagged_set(tagged, 1, map.location());
471  return from_tagged(tagged);
472  }
473  static Type* from_constant(i::Handle<i::Object> value, int lub, Zone* zone) {
474  Tagged* tagged = tagged_create(kConstantTag, 2, zone);
475  tagged_set(tagged, 0, lub);
476  tagged_set(tagged, 1, value.location());
477  return from_tagged(tagged);
478  }
479  static Type* from_union(Unioned* unioned) {
480  return from_tagged(tagged_from_union(unioned));
481  }
482  static Tagged* tagged_from_union(Unioned* unioned) {
483  return reinterpret_cast<Tagged*>(unioned);
484  }
485 
486  static Unioned* union_create(int size, Zone* zone) {
487  return tagged_as_union(tagged_create(kUnionTag, size, zone));
488  }
489  static void union_shrink(Unioned* unioned, int size) {
490  tagged_shrink(tagged_from_union(unioned), size);
491  }
492  static Type* union_get(Unioned* unioned, int i) {
493  Type* type = tagged_get<Type*>(tagged_from_union(unioned), i);
494  ASSERT(!is_union(type));
495  return type;
496  }
497  static void union_set(Unioned* unioned, int i, Type* type) {
498  ASSERT(!is_union(type));
499  tagged_set(tagged_from_union(unioned), i, type);
500  }
501  static int union_length(Unioned* unioned) {
502  return tagged_length(tagged_from_union(unioned));
503  }
504  static int lub_bitset(Type* type) {
505  ASSERT(is_class(type) || is_constant(type));
506  return static_cast<int>(tagged_get<intptr_t>(as_tagged(type), 0));
507  }
508 };
509 
510 
511 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for
512 // constants, or fixed arrays for unions.
515  typedef i::Object Base;
518  template<class T> struct Handle { typedef i::Handle<T> type; };
519 
520  static i::Handle<Type> handle(Type* type) {
521  return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
522  }
523 
524  static bool is_bitset(Type* type) { return type->IsSmi(); }
525  static bool is_class(Type* type) { return type->IsMap(); }
526  static bool is_constant(Type* type) { return type->IsBox(); }
527  static bool is_union(Type* type) { return type->IsFixedArray(); }
528 
529  static int as_bitset(Type* type) {
530  return Smi::cast(type)->value();
531  }
533  return i::handle(i::Map::cast(type));
534  }
536  i::Box* box = i::Box::cast(type);
537  return i::handle(box->value(), box->GetIsolate());
538  }
540  return i::handle(i::FixedArray::cast(type));
541  }
542 
543  static Type* from_bitset(int bitset) {
544  return Type::cast(i::Smi::FromInt(bitset));
545  }
546  static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) {
547  return i::handle(from_bitset(bitset), isolate);
548  }
550  i::Handle<i::Map> map, int lub, Isolate* isolate) {
552  }
554  i::Handle<i::Object> value, int lub, Isolate* isolate) {
555  i::Handle<Box> box = isolate->factory()->NewBox(value);
557  }
560  }
561 
562  static i::Handle<Unioned> union_create(int size, Isolate* isolate) {
563  return isolate->factory()->NewFixedArray(size);
564  }
565  static void union_shrink(i::Handle<Unioned> unioned, int size) {
566  unioned->Shrink(size);
567  }
569  Type* type = static_cast<Type*>(unioned->get(i));
570  ASSERT(!is_union(type));
571  return i::handle(type, unioned->GetIsolate());
572  }
573  static void union_set(
574  i::Handle<Unioned> unioned, int i, i::Handle<Type> type) {
575  ASSERT(!is_union(*type));
576  unioned->set(i, *type);
577  }
578  static int union_length(i::Handle<Unioned> unioned) {
579  return unioned->length();
580  }
581  static int lub_bitset(Type* type) {
582  return 0; // kNone, which causes recomputation.
583  }
584 };
585 
586 typedef TypeImpl<ZoneTypeConfig> Type;
587 typedef TypeImpl<HeapTypeConfig> HeapType;
588 
589 
590 // A simple struct to represent a pair of lower/upper type bounds.
591 template<class Config>
592 struct BoundsImpl {
594  typedef typename Type::TypeHandle TypeHandle;
595  typedef typename Type::Region Region;
596 
599 
601  explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
603  ASSERT(lower->Is(upper));
604  }
605 
606  // Unrestricted bounds.
607  static BoundsImpl Unbounded(Region* region) {
608  return BoundsImpl(Type::None(region), Type::Any(region));
609  }
610 
611  // Meet: both b1 and b2 are known to hold.
612  static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
613  TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
614  TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
615  // Lower bounds are considered approximate, correct as necessary.
616  lower = Type::Intersect(lower, upper, region);
617  return BoundsImpl(lower, upper);
618  }
619 
620  // Join: either b1 or b2 is known to hold.
621  static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
622  TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
623  TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
624  return BoundsImpl(lower, upper);
625  }
626 
628  // Lower bounds are considered approximate, correct as necessary.
629  t = Type::Intersect(t, b.upper, region);
630  TypeHandle lower = Type::Union(b.lower, t, region);
631  return BoundsImpl(lower, b.upper);
632  }
634  TypeHandle lower = Type::Intersect(b.lower, t, region);
635  TypeHandle upper = Type::Intersect(b.upper, t, region);
636  return BoundsImpl(lower, upper);
637  }
638 
639  bool Narrows(BoundsImpl that) {
640  return that.lower->Is(this->lower) && this->upper->Is(that.upper);
641  }
642 };
643 
645 
646 
647 } } // namespace v8::internal
648 
649 #endif // V8_TYPES_H_
i::ZoneList< Type * > Unioned
Definition: types.h:412
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static Type * from_tagged(Tagged *tagged)
Definition: types.h:464
static Type * from_bitset(int bitset, Zone *Zone)
Definition: types.h:461
static void union_shrink(i::Handle< Unioned > unioned, int size)
Definition: types.h:565
static TypeImpl * cast(typename Config::Base *object)
Definition: types.h:299
static int union_length(Unioned *unioned)
Definition: types.h:501
i::Handle< i::Map > AsClass()
Definition: types.h:262
BoundsImpl(TypeHandle t)
Definition: types.h:601
static i::Handle< Type > from_bitset(int bitset, Isolate *isolate)
Definition: types.h:546
static Unioned * tagged_as_union(Tagged *tagged)
Definition: types.h:453
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
static i::Handle< Type > from_union(i::Handle< Unioned > unioned)
Definition: types.h:558
TypeImpl< ZoneTypeConfig > Type
Definition: types.h:410
static bool is_tagged(Type *type)
Definition: types.h:425
static i::Handle< i::Object > as_constant(Type *type)
Definition: types.h:445
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static i::Handle< Unioned > as_union(Type *type)
Definition: types.h:539
static void union_set(Unioned *unioned, int i, Type *type)
Definition: types.h:497
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
static i::Handle< i::Map > as_class(Type *type)
Definition: types.h:441
static int lub_bitset(Type *type)
Definition: types.h:504
friend class TypeImpl
Definition: types.h:317
static Map * cast(Object *obj)
static Type * from_constant(i::Handle< i::Object > value, int lub, Zone *zone)
Definition: types.h:473
static bool is_constant(Type *type)
Definition: types.h:526
T & at(int i) const
Definition: list.h:90
static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region *region)
Definition: types.h:633
#define DEFINE_TYPE_CONSTRUCTOR(type, value)
Definition: types.h:224
BoundsImpl< ZoneTypeConfig > Bounds
Definition: types.h:644
TypeImpl< ZoneTypeConfig > Type
bool Is(TypeHandle that)
Definition: types.h:248
static i::Handle< i::Map > as_class(Type *type)
Definition: types.h:532
TypeHandle upper
Definition: types.h:598
#define ASSERT(condition)
Definition: checks.h:329
static Type * from_bitset(int bitset)
Definition: types.h:543
Iterator< i::Map > Classes()
Definition: types.h:290
i::Handle< i::Object > AsConstant()
Definition: types.h:263
static bool tagged_is_union(Tagged *tagged)
Definition: types.h:429
#define DECLARE_TYPE(type, value)
Definition: types.h:327
bool Maybe(TypeImpl *that)
Definition: types.cc:339
Factory * factory()
Definition: isolate.h:995
static bool is_class(Type *type)
Definition: types.h:525
static bool is_class(Type *type)
Definition: types.h:426
static void union_shrink(Unioned *unioned, int size)
Definition: types.h:489
static Smi * cast(Object *object)
Type::Region Region
Definition: types.h:595
static Type * from_union(Unioned *unioned)
Definition: types.h:479
static i::Handle< i::Object > as_constant(Type *type)
Definition: types.h:535
TypeImpl< Config > Type
Definition: types.h:593
static bool is_bitset(Type *type)
Definition: types.h:524
static i::Handle< Type > from_class(i::Handle< i::Map > map, int lub, Isolate *isolate)
Definition: types.h:549
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
static Type * from_class(i::Handle< i::Map > map, int lub, Zone *zone)
Definition: types.h:467
static i::Handle< Unioned > union_create(int size, Isolate *isolate)
Definition: types.h:562
static Box * cast(Object *obj)
static void union_set(i::Handle< Unioned > unioned, int i, i::Handle< Type > type)
Definition: types.h:573
static int as_bitset(Type *type)
Definition: types.h:433
static TypeHandle Convert(typename OtherTypeImpl::TypeHandle type, Region *region)
#define BITSET_TYPE_LIST(V)
Definition: types.h:186
static int as_bitset(Type *type)
Definition: types.h:529
static Unioned * as_union(Type *type)
Definition: types.h:449
Handle< FixedArray > NewFixedArray(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
static bool is_bitset(Type *type)
Definition: types.h:422
static i::Handle< Type > from_constant(i::Handle< i::Object > value, int lub, Isolate *isolate)
Definition: types.h:553
bool IsCurrently(TypeImpl *that)
Definition: types.cc:329
#define T(name, string, precedence)
Definition: token.cc:48
bool Maybe(TypeHandle that)
Definition: types.h:251
bool Narrows(BoundsImpl that)
Definition: types.h:639
bool Is(TypeImpl *that)
Definition: types.h:246
Definition: v8.h:2107
Iterator< i::Object > Constants()
Definition: types.h:294
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:495
TypeImpl< HeapTypeConfig > Type
Definition: types.h:514
Handle< Box > NewBox(Handle< Object > value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:45
Config::Region Region
Definition: types.h:222
static Tagged * as_tagged(Type *type)
Definition: types.h:437
Config::template Handle< TypeImpl >::type TypeHandle
Definition: types.h:221
static int lub_bitset(Type *type)
Definition: types.h:581
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
static i::Handle< Type > union_get(i::Handle< Unioned > unioned, int i)
Definition: types.h:568
static bool is_union(Type *type)
Definition: types.h:428
static Type * handle(Type *type)
Definition: types.h:416
static bool is_constant(Type *type)
Definition: types.h:427
static Type * from_bitset(int bitset)
Definition: types.h:458
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:621
BoundsImpl(TypeHandle l, TypeHandle u)
Definition: types.h:602
static Type * union_get(Unioned *unioned, int i)
Definition: types.h:492
static bool is(Type *type, Tag tag)
Definition: types.h:418
Type::TypeHandle TypeHandle
Definition: types.h:594
TypeHandle lower
Definition: types.h:597
friend class Iterator
Definition: types.h:316
static FixedArray * cast(Object *obj)
static Tagged * tagged_from_union(Unioned *unioned)
Definition: types.h:482
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:235
i::Handle< T > Current()
Definition: types.cc:111
static TypeHandle OfCurrently(i::Handle< i::Object > value, Region *region)
Definition: types.cc:274
static Unioned * union_create(int size, Zone *zone)
Definition: types.h:486
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:419
static BoundsImpl Unbounded(Region *region)
Definition: types.h:607
i::FixedArray Unioned
Definition: types.h:516
static TypeHandle Class(i::Handle< i::Map > map, Region *region)
Definition: types.h:232
static TypeHandle Of(i::Handle< i::Object > value, Region *region)
Definition: types.h:242
static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:612
TypeImpl< HeapTypeConfig > HeapType
Definition: list.h:212
bool IsCurrently(TypeHandle that)
Definition: types.h:258
static bool is_union(Type *type)
Definition: types.h:527
static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region *region)
Definition: types.h:627
Vector< T > AddBlock(T value, int count, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:99
static int union_length(i::Handle< Unioned > unioned)
Definition: types.h:578
static i::Handle< Type > handle(Type *type)
Definition: types.h:520