Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / v8 / src / types.h
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 // The following equations and inequations hold:
46 //
47 //   None <= T
48 //   T <= Any
49 //
50 //   Oddball = Boolean \/ Null \/ Undefined
51 //   Number = Signed32 \/ Unsigned32 \/ Double
52 //   Smi <= Signed32
53 //   Name = String \/ Symbol
54 //   UniqueName = InternalizedString \/ Symbol
55 //   InternalizedString < String
56 //
57 //   Allocated = Receiver \/ Number \/ Name
58 //   Detectable = Allocated - Undetectable
59 //   Undetectable < Object
60 //   Receiver = Object \/ Proxy
61 //   Array < Object
62 //   Function < Object
63 //   RegExp < Object
64 //
65 //   Class(map) < T   iff instance_type(map) < T
66 //   Constant(x) < T  iff instance_type(map(x)) < T
67 //
68 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
69 // change! (Its instance type cannot, however.)
70 // TODO(rossberg): the latter is not currently true for proxies, because of fix,
71 // but will hold once we implement direct proxies.
72 //
73 // There are two main functions for testing types:
74 //
75 //   T1->Is(T2)     -- tests whether T1 is included in T2 (i.e., T1 <= T2)
76 //   T1->Maybe(T2)  -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
77 //
78 // Typically, the former is to be used to select representations (e.g., via
79 // T->Is(Integer31())), and the to check whether a specific case needs handling
80 // (e.g., via T->Maybe(Number())).
81 //
82 // There is no functionality to discover whether a type is a leaf in the
83 // lattice. That is intentional. It should always be possible to refine the
84 // lattice (e.g., splitting up number types further) without invalidating any
85 // existing assumptions or tests.
86 //
87 // Consequently, do not use pointer equality for type tests, always use Is!
88 //
89 // Internally, all 'primitive' types, and their unions, are represented as
90 // bitsets via smis. Class is a heap pointer to the respective map. Only
91 // Constant's, or unions containing Class'es or Constant's, require allocation.
92 // Note that the bitset representation is closed under both Union and Intersect.
93 //
94 // The type representation is heap-allocated, so cannot (currently) be used in
95 // a concurrent compilation context.
96
97
98 #define BITSET_TYPE_LIST(V)              \
99   V(None,                0)              \
100   V(Null,                1 << 0)         \
101   V(Undefined,           1 << 1)         \
102   V(Boolean,             1 << 2)         \
103   V(Smi,                 1 << 3)         \
104   V(OtherSigned32,       1 << 4)         \
105   V(Unsigned32,          1 << 5)         \
106   V(Double,              1 << 6)         \
107   V(Float32x4,           1 << 7)         \
108   V(Int32x4,             1 << 8)         \
109   V(Symbol,              1 << 9)         \
110   V(InternalizedString,  1 << 10)        \
111   V(OtherString,         1 << 11)        \
112   V(Undetectable,        1 << 12)        \
113   V(Array,               1 << 13)        \
114   V(Function,            1 << 14)        \
115   V(RegExp,              1 << 15)        \
116   V(OtherObject,         1 << 16)        \
117   V(Proxy,               1 << 17)        \
118   V(Internal,            1 << 18)        \
119   \
120   V(Oddball,         kBoolean | kNull | kUndefined)                        \
121   V(Signed32,        kSmi | kOtherSigned32)                                \
122   V(Number,          kSigned32 | kUnsigned32 | kDouble)                    \
123   V(String,          kInternalizedString | kOtherString)                   \
124   V(UniqueName,      kSymbol | kInternalizedString)                        \
125   V(Name,            kSymbol | kString)                                    \
126   V(NumberOrString,  kNumber | kString)                                    \
127   V(Object,          kUndetectable | kArray | kFunction |                  \
128                      kRegExp | kOtherObject)                               \
129   V(Receiver,        kObject | kProxy)                                     \
130   V(Allocated,       kDouble | kFloat32x4 | kInt32x4 | kName | kReceiver)  \
131   V(Any,             kOddball | kNumber | kAllocated | kInternal)          \
132   V(NonNumber,       kAny - kNumber)                                       \
133   V(Detectable,      kAllocated - kUndetectable)
134
135
136 // struct Config {
137 //   typedef Base;
138 //   typedef Unioned;
139 //   typedef Region;
140 //   template<class> struct Handle { typedef type; }  // No template typedefs...
141 //   static Handle<Type>::type handle(Type* type);    // !is_bitset(type)
142 //   static bool is_bitset(Type*);
143 //   static bool is_class(Type*);
144 //   static bool is_constant(Type*);
145 //   static bool is_union(Type*);
146 //   static int as_bitset(Type*);
147 //   static i::Handle<i::Map> as_class(Type*);
148 //   static i::Handle<i::Object> as_constant(Type*);
149 //   static Handle<Unioned>::type as_union(Type*);
150 //   static Type* from_bitset(int bitset);
151 //   static Handle<Type>::type from_bitset(int bitset, Region*);
152 //   static Handle<Type>::type from_class(i::Handle<i::Map>, Region*)
153 //   static Handle<Type>::type from_constant(i::Handle<i::Object>, Region*);
154 //   static Handle<Type>::type from_union(Handle<Unioned>::type);
155 //   static Handle<Unioned>::type union_create(int size, Region*);
156 //   static void union_shrink(Handle<Unioned>::type, int size);
157 //   static Handle<Type>::type union_get(Handle<Unioned>::type, int);
158 //   static void union_set(Handle<Unioned>::type, int, Handle<Type>::type);
159 //   static int union_length(Handle<Unioned>::type);
160 // }
161 template<class Config>
162 class TypeImpl : public Config::Base {
163  public:
164   typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
165   typedef typename Config::Region Region;
166
167   #define DEFINE_TYPE_CONSTRUCTOR(type, value)                        \
168     static TypeImpl* type() { return Config::from_bitset(k##type); }  \
169     static TypeHandle type(Region* region) {                          \
170       return Config::from_bitset(k##type, region);                    \
171     }
172   BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
173   #undef DEFINE_TYPE_CONSTRUCTOR
174
175   static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
176     return Config::from_class(map, region);
177   }
178   static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
179     return Config::from_constant(value, region);
180   }
181
182   static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
183   static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
184
185   static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
186     return Config::from_bitset(LubBitset(*value), region);
187   }
188
189   bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
190   template<class TypeHandle>
191   bool Is(TypeHandle that) { return this->Is(*that); }
192   bool Maybe(TypeImpl* that);
193   template<class TypeHandle>
194   bool Maybe(TypeHandle that) { return this->Maybe(*that); }
195
196   // State-dependent versions of Of and Is that consider subtyping between
197   // a constant and its map class.
198   static TypeHandle OfCurrently(i::Handle<i::Object> value, Region* region);
199   bool IsCurrently(TypeImpl* that);
200   template<class TypeHandle>
201   bool IsCurrently(TypeHandle that)  { return this->IsCurrently(*that); }
202
203   bool IsClass() { return Config::is_class(this); }
204   bool IsConstant() { return Config::is_constant(this); }
205   i::Handle<i::Map> AsClass() { return Config::as_class(this); }
206   i::Handle<i::Object> AsConstant() { return Config::as_constant(this); }
207
208   int NumClasses();
209   int NumConstants();
210
211   template<class T>
212   class Iterator {
213    public:
214     bool Done() const { return index_ < 0; }
215     i::Handle<T> Current();
216     void Advance();
217
218    private:
219     template<class> friend class TypeImpl;
220
221     Iterator() : index_(-1) {}
222     explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
223       Advance();
224     }
225
226     inline bool matches(TypeHandle type);
227     inline TypeHandle get_type();
228
229     TypeHandle type_;
230     int index_;
231   };
232
233   Iterator<i::Map> Classes() {
234     if (this->IsBitset()) return Iterator<i::Map>();
235     return Iterator<i::Map>(Config::handle(this));
236   }
237   Iterator<i::Object> Constants() {
238     if (this->IsBitset()) return Iterator<i::Object>();
239     return Iterator<i::Object>(Config::handle(this));
240   }
241
242   static TypeImpl* cast(typename Config::Base* object) {
243     TypeImpl* t = static_cast<TypeImpl*>(object);
244     ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
245     return t;
246   }
247
248   template<class OtherTypeImpl>
249   static TypeHandle Convert(
250       typename OtherTypeImpl::TypeHandle type, Region* region);
251
252 #ifdef OBJECT_PRINT
253   void TypePrint();
254   void TypePrint(FILE* out);
255 #endif
256
257  private:
258   template<class> friend class Iterator;
259   template<class> friend class TypeImpl;
260
261   // A union is a fixed array containing types. Invariants:
262   // - its length is at least 2
263   // - at most one field is a bitset, and it must go into index 0
264   // - no field is a union
265   typedef typename Config::Unioned Unioned;
266   typedef typename Config::template Handle<Unioned>::type UnionedHandle;
267
268   enum {
269     #define DECLARE_TYPE(type, value) k##type = (value),
270     BITSET_TYPE_LIST(DECLARE_TYPE)
271     #undef DECLARE_TYPE
272     kUnusedEOL = 0
273   };
274
275   bool IsNone() { return this == None(); }
276   bool IsAny() { return this == Any(); }
277   bool IsBitset() { return Config::is_bitset(this); }
278   bool IsUnion() { return Config::is_union(this); }
279   int AsBitset() { return Config::as_bitset(this); }
280   UnionedHandle AsUnion() { return Config::as_union(this); }
281
282   static int UnionLength(UnionedHandle unioned) {
283     return Config::union_length(unioned);
284   }
285   static TypeHandle UnionGet(UnionedHandle unioned, int i) {
286     return Config::union_get(unioned, i);
287   }
288
289   bool SlowIs(TypeImpl* that);
290
291   int LubBitset();  // least upper bound that's a bitset
292   int GlbBitset();  // greatest lower bound that's a bitset
293
294   static int LubBitset(i::Object* value);
295   static int LubBitset(i::Map* map);
296
297   bool InUnion(UnionedHandle unioned, int current_size);
298   static int ExtendUnion(
299       UnionedHandle unioned, TypeHandle t, int current_size);
300   static int ExtendIntersection(
301       UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size);
302
303 #ifdef OBJECT_PRINT
304   static const char* bitset_name(int bitset);
305 #endif
306 };
307
308
309 // Zone-allocated types are either (odd) integers to represent bitsets, or
310 // (even) pointers to zone lists for everything else. The first slot of every
311 // list is an explicit tag value to distinguish representation.
312 struct ZoneTypeConfig {
313  private:
314   typedef i::ZoneList<void*> Tagged;
315
316   enum Tag {
317     kClassTag,
318     kConstantTag,
319     kUnionTag
320   };
321
322   static Tagged* tagged_create(Tag tag, int size, Zone* zone) {
323     Tagged* tagged = new(zone) Tagged(size + 1, zone);
324     tagged->Add(reinterpret_cast<void*>(tag), zone);
325     tagged->AddBlock(NULL, size, zone);
326     return tagged;
327   }
328   static void tagged_shrink(Tagged* tagged, int size) {
329     tagged->Rewind(size + 1);
330   }
331   static Tag tagged_tag(Tagged* tagged) {
332     return static_cast<Tag>(reinterpret_cast<intptr_t>(tagged->at(0)));
333   }
334   template<class T>
335   static T tagged_get(Tagged* tagged, int i) {
336     return reinterpret_cast<T>(tagged->at(i + 1));
337   }
338   template<class T>
339   static void tagged_set(Tagged* tagged, int i, T value) {
340     tagged->at(i + 1) = reinterpret_cast<T>(value);
341   }
342   static int tagged_length(Tagged* tagged) {
343     return tagged->length() - 1;
344   }
345
346  public:
347   typedef TypeImpl<ZoneTypeConfig> Type;
348   class Base {};
349   typedef i::ZoneList<Type*> Unioned;
350   typedef i::Zone Region;
351   template<class T> struct Handle { typedef T* type; };
352
353   static Type* handle(Type* type) { return type; }
354
355   static bool is(Type* type, Tag tag) {
356     return is_tagged(type) && tagged_tag(as_tagged(type)) == tag;
357   }
358
359   static bool is_bitset(Type* type) {
360     return reinterpret_cast<intptr_t>(type) & 1;
361   }
362   static bool is_tagged(Type* type) { return !is_bitset(type); }
363   static bool is_class(Type* type) { return is(type, kClassTag); }
364   static bool is_constant(Type* type) { return is(type, kConstantTag); }
365   static bool is_union(Type* type) { return is(type, kUnionTag); }
366   static bool tagged_is_union(Tagged* tagged) {
367     return is(from_tagged(tagged), kUnionTag);
368   }
369
370   static int as_bitset(Type* type) {
371     ASSERT(is_bitset(type));
372     return static_cast<int>(reinterpret_cast<intptr_t>(type) >> 1);
373   }
374   static Tagged* as_tagged(Type* type) {
375     ASSERT(is_tagged(type));
376     return reinterpret_cast<Tagged*>(type);
377   }
378   static i::Handle<i::Map> as_class(Type* type) {
379     ASSERT(is_class(type));
380     return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 0));
381   }
382   static i::Handle<i::Object> as_constant(Type* type) {
383     ASSERT(is_constant(type));
384     return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 0));
385   }
386   static Unioned* as_union(Type* type) {
387     ASSERT(is_union(type));
388     return tagged_as_union(as_tagged(type));
389   }
390   static Unioned* tagged_as_union(Tagged* tagged) {
391     ASSERT(tagged_is_union(tagged));
392     return reinterpret_cast<Unioned*>(tagged);
393   }
394
395   static Type* from_bitset(int bitset) {
396     return reinterpret_cast<Type*>((bitset << 1) | 1);
397   }
398   static Type* from_bitset(int bitset, Zone* Zone) {
399     return from_bitset(bitset);
400   }
401   static Type* from_tagged(Tagged* tagged) {
402     return reinterpret_cast<Type*>(tagged);
403   }
404   static Type* from_class(i::Handle<i::Map> map, Zone* zone) {
405     Tagged* tagged = tagged_create(kClassTag, 1, zone);
406     tagged_set(tagged, 0, map.location());
407     return from_tagged(tagged);
408   }
409   static Type* from_constant(i::Handle<i::Object> value, Zone* zone) {
410     Tagged* tagged = tagged_create(kConstantTag, 1, zone);
411     tagged_set(tagged, 0, value.location());
412     return from_tagged(tagged);
413   }
414   static Type* from_union(Unioned* unioned) {
415     return from_tagged(tagged_from_union(unioned));
416   }
417   static Tagged* tagged_from_union(Unioned* unioned) {
418     return reinterpret_cast<Tagged*>(unioned);
419   }
420
421   static Unioned* union_create(int size, Zone* zone) {
422     return tagged_as_union(tagged_create(kUnionTag, size, zone));
423   }
424   static void union_shrink(Unioned* unioned, int size) {
425     tagged_shrink(tagged_from_union(unioned), size);
426   }
427   static Type* union_get(Unioned* unioned, int i) {
428     Type* type = tagged_get<Type*>(tagged_from_union(unioned), i);
429     ASSERT(!is_union(type));
430     return type;
431   }
432   static void union_set(Unioned* unioned, int i, Type* type) {
433     ASSERT(!is_union(type));
434     tagged_set(tagged_from_union(unioned), i, type);
435   }
436   static int union_length(Unioned* unioned) {
437     return tagged_length(tagged_from_union(unioned));
438   }
439 };
440
441
442 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for
443 // constants, or fixed arrays for unions.
444 struct HeapTypeConfig {
445   typedef TypeImpl<HeapTypeConfig> Type;
446   typedef i::Object Base;
447   typedef i::FixedArray Unioned;
448   typedef i::Isolate Region;
449   template<class T> struct Handle { typedef i::Handle<T> type; };
450
451   static i::Handle<Type> handle(Type* type) {
452     return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
453   }
454
455   static bool is_bitset(Type* type) { return type->IsSmi(); }
456   static bool is_class(Type* type) { return type->IsMap(); }
457   static bool is_constant(Type* type) { return type->IsBox(); }
458   static bool is_union(Type* type) { return type->IsFixedArray(); }
459
460   static int as_bitset(Type* type) {
461     return Smi::cast(type)->value();
462   }
463   static i::Handle<i::Map> as_class(Type* type) {
464     return i::handle(i::Map::cast(type));
465   }
466   static i::Handle<i::Object> as_constant(Type* type) {
467     i::Box* box = i::Box::cast(type);
468     return i::handle(box->value(), box->GetIsolate());
469   }
470   static i::Handle<Unioned> as_union(Type* type) {
471     return i::handle(i::FixedArray::cast(type));
472   }
473
474   static Type* from_bitset(int bitset) {
475     return Type::cast(i::Smi::FromInt(bitset));
476   }
477   static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) {
478     return i::handle(from_bitset(bitset), isolate);
479   }
480   static i::Handle<Type> from_class(i::Handle<i::Map> map, Isolate* isolate) {
481     return i::Handle<Type>::cast(i::Handle<Object>::cast(map));
482   }
483   static i::Handle<Type> from_constant(
484       i::Handle<i::Object> value, Isolate* isolate) {
485     i::Handle<Box> box = isolate->factory()->NewBox(value);
486     return i::Handle<Type>::cast(i::Handle<Object>::cast(box));
487   }
488   static i::Handle<Type> from_union(i::Handle<Unioned> unioned) {
489     return i::Handle<Type>::cast(i::Handle<Object>::cast(unioned));
490   }
491
492   static i::Handle<Unioned> union_create(int size, Isolate* isolate) {
493     return isolate->factory()->NewFixedArray(size);
494   }
495   static void union_shrink(i::Handle<Unioned> unioned, int size) {
496     unioned->Shrink(size);
497   }
498   static i::Handle<Type> union_get(i::Handle<Unioned> unioned, int i) {
499     Type* type = static_cast<Type*>(unioned->get(i));
500     ASSERT(!is_union(type));
501     return i::handle(type, unioned->GetIsolate());
502   }
503   static void union_set(
504       i::Handle<Unioned> unioned, int i, i::Handle<Type> type) {
505     ASSERT(!is_union(*type));
506     unioned->set(i, *type);
507   }
508   static int union_length(i::Handle<Unioned> unioned) {
509     return unioned->length();
510   }
511 };
512
513 typedef TypeImpl<ZoneTypeConfig> Type;
514 typedef TypeImpl<HeapTypeConfig> HeapType;
515
516
517 // A simple struct to represent a pair of lower/upper type bounds.
518 template<class Config>
519 struct BoundsImpl {
520   typedef TypeImpl<Config> Type;
521   typedef typename Type::TypeHandle TypeHandle;
522   typedef typename Type::Region Region;
523
524   TypeHandle lower;
525   TypeHandle upper;
526
527   BoundsImpl() {}
528   explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
529   BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
530     ASSERT(lower->Is(upper));
531   }
532
533   // Unrestricted bounds.
534   static BoundsImpl Unbounded(Region* region) {
535     return BoundsImpl(Type::None(region), Type::Any(region));
536   }
537
538   // Meet: both b1 and b2 are known to hold.
539   static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
540     TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
541     TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
542     // Lower bounds are considered approximate, correct as necessary.
543     lower = Type::Intersect(lower, upper, region);
544     return BoundsImpl(lower, upper);
545   }
546
547   // Join: either b1 or b2 is known to hold.
548   static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
549     TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
550     TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
551     return BoundsImpl(lower, upper);
552   }
553
554   static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
555     // Lower bounds are considered approximate, correct as necessary.
556     t = Type::Intersect(t, b.upper, region);
557     TypeHandle lower = Type::Union(b.lower, t, region);
558     return BoundsImpl(lower, b.upper);
559   }
560   static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) {
561     TypeHandle lower = Type::Intersect(b.lower, t, region);
562     TypeHandle upper = Type::Intersect(b.upper, t, region);
563     return BoundsImpl(lower, upper);
564   }
565 };
566
567 typedef BoundsImpl<ZoneTypeConfig> Bounds;
568
569
570 } }  // namespace v8::internal
571
572 #endif  // V8_TYPES_H_