OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_TYPES_H_ | 5 #ifndef V8_TYPES_H_ |
6 #define V8_TYPES_H_ | 6 #define V8_TYPES_H_ |
7 | 7 |
8 #include "handles.h" | 8 #include "handles.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 25 matching lines...) Expand all Loading... |
36 // | 36 // |
37 // Receiver = Object \/ Proxy | 37 // Receiver = Object \/ Proxy |
38 // Array < Object | 38 // Array < Object |
39 // Function < Object | 39 // Function < Object |
40 // RegExp < Object | 40 // RegExp < Object |
41 // Undetectable < Object | 41 // Undetectable < Object |
42 // Detectable = Receiver \/ Number \/ Name - Undetectable | 42 // Detectable = Receiver \/ Number \/ Name - Undetectable |
43 // | 43 // |
44 // Class(map) < T iff instance_type(map) < T | 44 // Class(map) < T iff instance_type(map) < T |
45 // Constant(x) < T iff instance_type(map(x)) < T | 45 // Constant(x) < T iff instance_type(map(x)) < T |
46 // Array(T) < Array | |
47 // Function(R, S, T0, T1, ...) < Function | |
48 // | 46 // |
49 // Both structural Array and Function types are invariant in all parameters. | |
50 // Relaxing this would make Union and Intersect operations more involved. | |
51 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 47 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
52 // change! (Its instance type cannot, however.) | 48 // change! (Its instance type cannot, however.) |
53 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 49 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
54 // but will hold once we implement direct proxies. | 50 // but will hold once we implement direct proxies. |
55 // However, we also define a 'temporal' variant of the subtyping relation that | 51 // However, we also define a 'temporal' variant of the subtyping relation that |
56 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). | 52 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). |
57 // | 53 // |
58 // REPRESENTATIONAL DIMENSION | 54 // REPRESENTATIONAL DIMENSION |
59 // | 55 // |
60 // For the representation axis, the following holds: | 56 // For the representation axis, the following holds: |
(...skipping 28 matching lines...) Expand all Loading... |
89 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | 85 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
90 // | 86 // |
91 // Typically, the former is to be used to select representations (e.g., via | 87 // Typically, the former is to be used to select representations (e.g., via |
92 // T->Is(SignedSmall())), and the latter to check whether a specific case needs | 88 // T->Is(SignedSmall())), and the latter to check whether a specific case needs |
93 // handling (e.g., via T->Maybe(Number())). | 89 // handling (e.g., via T->Maybe(Number())). |
94 // | 90 // |
95 // There is no functionality to discover whether a type is a leaf in the | 91 // There is no functionality to discover whether a type is a leaf in the |
96 // lattice. That is intentional. It should always be possible to refine the | 92 // lattice. That is intentional. It should always be possible to refine the |
97 // lattice (e.g., splitting up number types further) without invalidating any | 93 // lattice (e.g., splitting up number types further) without invalidating any |
98 // existing assumptions or tests. | 94 // existing assumptions or tests. |
99 // Consequently, do not normally use Equals for type tests, always use Is! | 95 // Consequently, do not use pointer equality for type tests, always use Is! |
100 // | 96 // |
101 // The NowIs operator implements state-sensitive subtying, as described above. | 97 // The NowIs operator implements state-sensitive subtying, as described above. |
102 // Any compilation decision based on such temporary properties requires runtime | 98 // Any compilation decision based on such temporary properties requires runtime |
103 // guarding! | 99 // guarding! |
104 // | 100 // |
105 // PROPERTIES | 101 // PROPERTIES |
106 // | 102 // |
107 // Various formal properties hold for constructors, operators, and predicates | 103 // Various formal properties hold for constructors, operators, and predicates |
108 // over types. For example, constructors are injective, subtyping is a complete | 104 // over types. For example, constructors are injective, subtyping is a complete |
109 // partial order, union and intersection satisfy the usual algebraic properties. | 105 // partial order, union and intersection satisfy the usual algebraic properties. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 kUndefined | kInternal) \ | 182 kUndefined | kInternal) \ |
187 V(Any, -1) | 183 V(Any, -1) |
188 | 184 |
189 #define BITSET_TYPE_LIST(V) \ | 185 #define BITSET_TYPE_LIST(V) \ |
190 MASK_BITSET_TYPE_LIST(V) \ | 186 MASK_BITSET_TYPE_LIST(V) \ |
191 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 187 REPRESENTATION_BITSET_TYPE_LIST(V) \ |
192 SEMANTIC_BITSET_TYPE_LIST(V) | 188 SEMANTIC_BITSET_TYPE_LIST(V) |
193 | 189 |
194 | 190 |
195 // struct Config { | 191 // struct Config { |
196 // typedef TypeImpl<Config> Type; | |
197 // typedef Base; | 192 // typedef Base; |
198 // typedef Struct; | 193 // typedef Struct; |
199 // typedef Region; | 194 // typedef Region; |
200 // template<class> struct Handle { typedef type; } // No template typedefs... | 195 // template<class> struct Handle { typedef type; } // No template typedefs... |
201 // template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t) | 196 // static Handle<Type>::type handle(Type* type); // !is_bitset(type) |
202 // template<class T> static Handle<T>::type cast(Handle<Type>::type); | |
203 // static bool is_bitset(Type*); | 197 // static bool is_bitset(Type*); |
204 // static bool is_class(Type*); | 198 // static bool is_class(Type*); |
205 // static bool is_constant(Type*); | 199 // static bool is_constant(Type*); |
206 // static bool is_struct(Type*, int tag); | 200 // static bool is_struct(Type*); |
207 // static int as_bitset(Type*); | 201 // static int as_bitset(Type*); |
208 // static i::Handle<i::Map> as_class(Type*); | 202 // static i::Handle<i::Map> as_class(Type*); |
209 // static i::Handle<i::Object> as_constant(Type*); | 203 // static i::Handle<i::Object> as_constant(Type*); |
210 // static Handle<Struct>::type as_struct(Type*); | 204 // static Handle<Struct>::type as_struct(Type*); |
211 // static Type* from_bitset(int bitset); | 205 // static Type* from_bitset(int bitset); |
212 // static Handle<Type>::type from_bitset(int bitset, Region*); | 206 // static Handle<Type>::type from_bitset(int bitset, Region*); |
213 // static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*); | 207 // static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*); |
214 // static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*); | 208 // static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*); |
215 // static Handle<Type>::type from_struct(Handle<Struct>::type, int tag); | 209 // static Handle<Type>::type from_struct(Handle<Struct>::type); |
216 // static Handle<Struct>::type struct_create(int tag, int length, Region*); | 210 // static Handle<Struct>::type struct_create(int tag, int length, Region*); |
217 // static void struct_shrink(Handle<Struct>::type, int length); | 211 // static void struct_shrink(Handle<Struct>::type, int length); |
218 // static int struct_tag(Handle<Struct>::type); | 212 // static int struct_tag(Handle<Struct>::type); |
219 // static int struct_length(Handle<Struct>::type); | 213 // static int struct_length(Handle<Struct>::type); |
220 // static Handle<Type>::type struct_get(Handle<Struct>::type, int); | 214 // static Handle<Type>::type struct_get(Handle<Struct>::type, int); |
221 // static void struct_set(Handle<Struct>::type, int, Handle<Type>::type); | 215 // static void struct_set(Handle<Struct>::type, int, Handle<Type>::type); |
222 // static int lub_bitset(Type*); | 216 // static int lub_bitset(Type*); |
223 // } | 217 // } |
224 template<class Config> | 218 template<class Config> |
225 class TypeImpl : public Config::Base { | 219 class TypeImpl : public Config::Base { |
226 public: | 220 public: |
227 class BitsetType; // Internal | |
228 class StructuralType; // Internal | |
229 class UnionType; // Internal | |
230 | |
231 class ClassType; | |
232 class ConstantType; | |
233 class ArrayType; | |
234 class FunctionType; | |
235 | |
236 typedef typename Config::template Handle<TypeImpl>::type TypeHandle; | 221 typedef typename Config::template Handle<TypeImpl>::type TypeHandle; |
237 typedef typename Config::template Handle<ClassType>::type ClassHandle; | |
238 typedef typename Config::template Handle<ConstantType>::type ConstantHandle; | |
239 typedef typename Config::template Handle<ArrayType>::type ArrayHandle; | |
240 typedef typename Config::template Handle<FunctionType>::type FunctionHandle; | |
241 typedef typename Config::template Handle<UnionType>::type UnionHandle; | |
242 typedef typename Config::Region Region; | 222 typedef typename Config::Region Region; |
243 | 223 |
244 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | 224 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
245 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ | 225 static TypeImpl* type() { return Config::from_bitset(k##type); } \ |
246 static TypeHandle type(Region* region) { \ | 226 static TypeHandle type(Region* region) { \ |
247 return BitsetType::New(BitsetType::k##type, region); \ | 227 return Config::from_bitset(k##type, region); \ |
248 } | 228 } |
249 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | 229 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
250 #undef DEFINE_TYPE_CONSTRUCTOR | 230 #undef DEFINE_TYPE_CONSTRUCTOR |
251 | 231 |
252 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { | 232 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { |
253 return ClassType::New(map, region); | 233 return Config::from_class(map, LubBitset(*map), region); |
254 } | 234 } |
255 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { | 235 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { |
256 return ConstantType::New(value, region); | 236 return Config::from_constant(value, LubBitset(*value), region); |
257 } | |
258 static TypeHandle Array(TypeHandle element, Region* region) { | |
259 return ArrayType::New(element, region); | |
260 } | |
261 static FunctionHandle Function( | |
262 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | |
263 return FunctionType::New(result, receiver, arity, region); | |
264 } | |
265 static TypeHandle Function(TypeHandle result, Region* region) { | |
266 return Function(result, Any(region), 0, region); | |
267 } | |
268 static TypeHandle Function( | |
269 TypeHandle result, TypeHandle param0, Region* region) { | |
270 FunctionHandle function = Function(result, Any(region), 1, region); | |
271 function->InitParameter(0, param0); | |
272 return function; | |
273 } | |
274 static TypeHandle Function( | |
275 TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) { | |
276 FunctionHandle function = Function(result, Any(region), 2, region); | |
277 function->InitParameter(0, param0); | |
278 function->InitParameter(1, param1); | |
279 return function; | |
280 } | 237 } |
281 | 238 |
282 static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); | 239 static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); |
283 static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); | 240 static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); |
284 | 241 |
285 static TypeHandle Of(i::Object* value, Region* region) { | 242 static TypeHandle Of(i::Object* value, Region* region) { |
286 return Config::from_bitset(BitsetType::Lub(value), region); | 243 return Config::from_bitset(LubBitset(value), region); |
287 } | 244 } |
288 static TypeHandle Of(i::Handle<i::Object> value, Region* region) { | 245 static TypeHandle Of(i::Handle<i::Object> value, Region* region) { |
289 return Of(*value, region); | 246 return Of(*value, region); |
290 } | 247 } |
291 | 248 |
292 bool IsInhabited() { | 249 bool IsInhabited() { |
293 return !this->IsBitset() || BitsetType::IsInhabited(this->AsBitset()); | 250 return !this->IsBitset() || IsInhabited(this->AsBitset()); |
294 } | 251 } |
295 | 252 |
296 bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } | 253 bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } |
297 template<class TypeHandle> | 254 template<class TypeHandle> |
298 bool Is(TypeHandle that) { return this->Is(*that); } | 255 bool Is(TypeHandle that) { return this->Is(*that); } |
299 | 256 |
300 bool Maybe(TypeImpl* that); | 257 bool Maybe(TypeImpl* that); |
301 template<class TypeHandle> | 258 template<class TypeHandle> |
302 bool Maybe(TypeHandle that) { return this->Maybe(*that); } | 259 bool Maybe(TypeHandle that) { return this->Maybe(*that); } |
303 | 260 |
304 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } | |
305 template<class TypeHandle> | |
306 bool Equals(TypeHandle that) { return this->Equals(*that); } | |
307 | |
308 // Equivalent to Constant(value)->Is(this), but avoiding allocation. | 261 // Equivalent to Constant(value)->Is(this), but avoiding allocation. |
309 bool Contains(i::Object* val); | 262 bool Contains(i::Object* val); |
310 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | 263 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } |
311 | 264 |
312 // State-dependent versions of Of and Is that consider subtyping between | 265 // State-dependent versions of Of and Is that consider subtyping between |
313 // a constant and its map class. | 266 // a constant and its map class. |
314 static TypeHandle NowOf(i::Object* value, Region* region); | 267 static TypeHandle NowOf(i::Object* value, Region* region); |
315 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { | 268 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { |
316 return NowOf(*value, region); | 269 return NowOf(*value, region); |
317 } | 270 } |
318 bool NowIs(TypeImpl* that); | 271 bool NowIs(TypeImpl* that); |
319 template<class TypeHandle> | 272 template<class TypeHandle> |
320 bool NowIs(TypeHandle that) { return this->NowIs(*that); } | 273 bool NowIs(TypeHandle that) { return this->NowIs(*that); } |
321 inline bool NowContains(i::Object* val); | 274 inline bool NowContains(i::Object* val); |
322 bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); } | 275 bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); } |
323 | 276 |
324 bool IsClass() { return Config::is_class(this); } | 277 bool IsClass() { return Config::is_class(this); } |
325 bool IsConstant() { return Config::is_constant(this); } | 278 bool IsConstant() { return Config::is_constant(this); } |
326 bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); } | 279 i::Handle<i::Map> AsClass() { return Config::as_class(this); } |
327 bool IsFunction() { | 280 i::Handle<i::Object> AsConstant() { return Config::as_constant(this); } |
328 return Config::is_struct(this, StructuralType::kFunctionTag); | |
329 } | |
330 | |
331 ClassType* AsClass() { return ClassType::cast(this); } | |
332 ConstantType* AsConstant() { return ConstantType::cast(this); } | |
333 ArrayType* AsArray() { return ArrayType::cast(this); } | |
334 FunctionType* AsFunction() { return FunctionType::cast(this); } | |
335 | 281 |
336 int NumClasses(); | 282 int NumClasses(); |
337 int NumConstants(); | 283 int NumConstants(); |
338 | 284 |
339 template<class T> class Iterator; | 285 template<class T> |
340 inline Iterator<i::Map> Classes(); | 286 class Iterator { |
341 inline Iterator<i::Object> Constants(); | 287 public: |
| 288 bool Done() const { return index_ < 0; } |
| 289 i::Handle<T> Current(); |
| 290 void Advance(); |
342 | 291 |
343 static inline TypeImpl* cast(typename Config::Base* object); | 292 private: |
| 293 template<class> friend class TypeImpl; |
| 294 |
| 295 Iterator() : index_(-1) {} |
| 296 explicit Iterator(TypeHandle type) : type_(type), index_(-1) { |
| 297 Advance(); |
| 298 } |
| 299 |
| 300 inline bool matches(TypeHandle type); |
| 301 inline TypeHandle get_type(); |
| 302 |
| 303 TypeHandle type_; |
| 304 int index_; |
| 305 }; |
| 306 |
| 307 Iterator<i::Map> Classes() { |
| 308 if (this->IsBitset()) return Iterator<i::Map>(); |
| 309 return Iterator<i::Map>(Config::handle(this)); |
| 310 } |
| 311 Iterator<i::Object> Constants() { |
| 312 if (this->IsBitset()) return Iterator<i::Object>(); |
| 313 return Iterator<i::Object>(Config::handle(this)); |
| 314 } |
| 315 |
| 316 static TypeImpl* cast(typename Config::Base* object) { |
| 317 TypeImpl* t = static_cast<TypeImpl*>(object); |
| 318 ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); |
| 319 return t; |
| 320 } |
344 | 321 |
345 template<class OtherTypeImpl> | 322 template<class OtherTypeImpl> |
346 static TypeHandle Convert( | 323 static TypeHandle Convert( |
347 typename OtherTypeImpl::TypeHandle type, Region* region); | 324 typename OtherTypeImpl::TypeHandle type, Region* region); |
348 | 325 |
349 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; | 326 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
350 void TypePrint(PrintDimension = BOTH_DIMS); | 327 void TypePrint(PrintDimension = BOTH_DIMS); |
351 void TypePrint(FILE* out, PrintDimension = BOTH_DIMS); | 328 void TypePrint(FILE* out, PrintDimension = BOTH_DIMS); |
352 | 329 |
353 protected: | 330 private: |
354 template<class> friend class Iterator; | 331 template<class> friend class Iterator; |
355 template<class> friend class TypeImpl; | 332 template<class> friend class TypeImpl; |
| 333 friend struct ZoneTypeConfig; |
| 334 friend struct HeapTypeConfig; |
356 | 335 |
357 template<class T> | 336 enum Tag { |
358 static typename Config::template Handle<T>::type handle(T* type) { | 337 kClassTag, |
359 return Config::handle(type); | 338 kConstantTag, |
360 } | 339 kUnionTag |
| 340 }; |
361 | 341 |
362 bool IsNone() { return this == None(); } | 342 // A structured type contains a tag an a variable number of type fields. |
363 bool IsAny() { return this == Any(); } | 343 // A union is a structured type with the following invariants: |
364 bool IsBitset() { return Config::is_bitset(this); } | 344 // - its length is at least 2 |
365 bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); } | 345 // - at most one field is a bitset, and it must go into index 0 |
366 | 346 // - no field is a union |
367 int AsBitset() { | 347 typedef typename Config::Struct Struct; |
368 ASSERT(this->IsBitset()); | 348 typedef typename Config::template Handle<Struct>::type StructHandle; |
369 return static_cast<BitsetType*>(this)->Bitset(); | |
370 } | |
371 UnionType* AsUnion() { return UnionType::cast(this); } | |
372 | |
373 bool SlowIs(TypeImpl* that); | |
374 | |
375 bool InUnion(UnionHandle unioned, int current_size); | |
376 static int ExtendUnion( | |
377 UnionHandle unioned, TypeHandle t, int current_size); | |
378 static int ExtendIntersection( | |
379 UnionHandle unioned, TypeHandle t, TypeHandle other, int current_size); | |
380 | |
381 int BitsetGlb() { return BitsetType::Glb(this); } | |
382 int BitsetLub() { return BitsetType::Lub(this); } | |
383 }; | |
384 | |
385 | |
386 template<class Config> | |
387 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | |
388 private: | |
389 friend class TypeImpl<Config>; | |
390 | 349 |
391 enum { | 350 enum { |
392 #define DECLARE_TYPE(type, value) k##type = (value), | 351 #define DECLARE_TYPE(type, value) k##type = (value), |
393 BITSET_TYPE_LIST(DECLARE_TYPE) | 352 BITSET_TYPE_LIST(DECLARE_TYPE) |
394 #undef DECLARE_TYPE | 353 #undef DECLARE_TYPE |
395 kUnusedEOL = 0 | 354 kUnusedEOL = 0 |
396 }; | 355 }; |
397 | 356 |
398 int Bitset() { return Config::as_bitset(this); } | 357 bool IsNone() { return this == None(); } |
| 358 bool IsAny() { return this == Any(); } |
| 359 bool IsBitset() { return Config::is_bitset(this); } |
| 360 bool IsStruct(Tag tag) { |
| 361 return Config::is_struct(this) |
| 362 && Config::struct_tag(Config::as_struct(this)) == tag; |
| 363 } |
| 364 bool IsUnion() { return IsStruct(kUnionTag); } |
399 | 365 |
400 static BitsetType* New(int bitset) { | 366 int AsBitset() { return Config::as_bitset(this); } |
401 return static_cast<BitsetType*>(Config::from_bitset(bitset)); | 367 StructHandle AsStruct(Tag tag) { |
| 368 ASSERT(IsStruct(tag)); |
| 369 return Config::as_struct(this); |
402 } | 370 } |
403 static TypeHandle New(int bitset, Region* region) { | 371 StructHandle AsUnion() { return AsStruct(kUnionTag); } |
404 return Config::from_bitset(bitset, region); | 372 |
| 373 static int StructLength(StructHandle structured) { |
| 374 return Config::struct_length(structured); |
405 } | 375 } |
| 376 static TypeHandle StructGet(StructHandle structured, int i) { |
| 377 return Config::struct_get(structured, i); |
| 378 } |
| 379 |
| 380 bool SlowIs(TypeImpl* that); |
406 | 381 |
407 static bool IsInhabited(int bitset) { | 382 static bool IsInhabited(int bitset) { |
408 return (bitset & kRepresentation) && (bitset & kSemantic); | 383 return (bitset & kRepresentation) && (bitset & kSemantic); |
409 } | 384 } |
410 | 385 |
411 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset | 386 int LubBitset(); // least upper bound that's a bitset |
412 static int Lub(TypeImpl* type); // least upper bound that's a bitset | 387 int GlbBitset(); // greatest lower bound that's a bitset |
413 static int Lub(i::Object* value); | |
414 static int Lub(i::Map* map); | |
415 | 388 |
416 static const char* Name(int bitset); | 389 static int LubBitset(i::Object* value); |
| 390 static int LubBitset(i::Map* map); |
| 391 |
| 392 bool InUnion(StructHandle unioned, int current_size); |
| 393 static int ExtendUnion( |
| 394 StructHandle unioned, TypeHandle t, int current_size); |
| 395 static int ExtendIntersection( |
| 396 StructHandle unioned, TypeHandle t, TypeHandle other, int current_size); |
| 397 |
| 398 static const char* bitset_name(int bitset); |
417 static void BitsetTypePrint(FILE* out, int bitset); | 399 static void BitsetTypePrint(FILE* out, int bitset); |
418 }; | 400 }; |
419 | 401 |
420 | 402 |
421 // Internal | |
422 // A structured type contains a tag and a variable number of type fields. | |
423 template<class Config> | |
424 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | |
425 protected: | |
426 template<class> friend class TypeImpl; | |
427 friend struct ZoneTypeConfig; // For tags. | |
428 friend struct HeapTypeConfig; | |
429 | |
430 enum Tag { | |
431 kClassTag, | |
432 kConstantTag, | |
433 kArrayTag, | |
434 kFunctionTag, | |
435 kUnionTag | |
436 }; | |
437 | |
438 int Length() { | |
439 return Config::struct_length(Config::as_struct(this)); | |
440 } | |
441 TypeHandle Get(int i) { | |
442 return Config::struct_get(Config::as_struct(this), i); | |
443 } | |
444 void Set(int i, TypeHandle type) { | |
445 Config::struct_set(Config::as_struct(this), i, type); | |
446 } | |
447 void Shrink(int length) { | |
448 Config::struct_shrink(Config::as_struct(this), length); | |
449 } | |
450 | |
451 static TypeHandle New(Tag tag, int length, Region* region) { | |
452 return Config::from_struct(Config::struct_create(tag, length, region)); | |
453 } | |
454 }; | |
455 | |
456 | |
457 template<class Config> | |
458 class TypeImpl<Config>::ClassType : public TypeImpl<Config> { | |
459 public: | |
460 i::Handle<i::Map> Map() { return Config::as_class(this); } | |
461 | |
462 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | |
463 return Config::template cast<ClassType>( | |
464 Config::from_class(map, BitsetType::Lub(*map), region)); | |
465 } | |
466 | |
467 static ClassType* cast(TypeImpl* type) { | |
468 ASSERT(type->IsClass()); | |
469 return static_cast<ClassType*>(type); | |
470 } | |
471 }; | |
472 | |
473 | |
474 template<class Config> | |
475 class TypeImpl<Config>::ConstantType : public TypeImpl<Config> { | |
476 public: | |
477 i::Handle<i::Object> Value() { return Config::as_constant(this); } | |
478 | |
479 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { | |
480 return Config::template cast<ConstantType>( | |
481 Config::from_constant(value, BitsetType::Lub(*value), region)); | |
482 } | |
483 | |
484 static ConstantType* cast(TypeImpl* type) { | |
485 ASSERT(type->IsConstant()); | |
486 return static_cast<ConstantType*>(type); | |
487 } | |
488 }; | |
489 | |
490 | |
491 // Internal | |
492 // A union is a structured type with the following invariants: | |
493 // - its length is at least 2 | |
494 // - at most one field is a bitset, and it must go into index 0 | |
495 // - no field is a union | |
496 template<class Config> | |
497 class TypeImpl<Config>::UnionType : public StructuralType { | |
498 public: | |
499 static UnionHandle New(int length, Region* region) { | |
500 return Config::template cast<UnionType>( | |
501 StructuralType::New(StructuralType::kUnionTag, length, region)); | |
502 } | |
503 | |
504 static UnionType* cast(TypeImpl* type) { | |
505 ASSERT(type->IsUnion()); | |
506 return static_cast<UnionType*>(type); | |
507 } | |
508 }; | |
509 | |
510 | |
511 template<class Config> | |
512 class TypeImpl<Config>::ArrayType : public StructuralType { | |
513 public: | |
514 TypeHandle Element() { return this->Get(0); } | |
515 | |
516 static ArrayHandle New(TypeHandle element, Region* region) { | |
517 ArrayHandle type = Config::template cast<ArrayType>( | |
518 StructuralType::New(StructuralType::kArrayTag, 1, region)); | |
519 type->Set(0, element); | |
520 return type; | |
521 } | |
522 | |
523 static ArrayType* cast(TypeImpl* type) { | |
524 ASSERT(type->IsArray()); | |
525 return static_cast<ArrayType*>(type); | |
526 } | |
527 }; | |
528 | |
529 | |
530 template<class Config> | |
531 class TypeImpl<Config>::FunctionType : public StructuralType { | |
532 public: | |
533 int Arity() { return this->Length() - 2; } | |
534 TypeHandle Result() { return this->Get(0); } | |
535 TypeHandle Receiver() { return this->Get(1); } | |
536 TypeHandle Parameter(int i) { return this->Get(2 + i); } | |
537 | |
538 void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); } | |
539 | |
540 static FunctionHandle New( | |
541 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | |
542 FunctionHandle type = Config::template cast<FunctionType>( | |
543 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); | |
544 type->Set(0, result); | |
545 type->Set(1, receiver); | |
546 return type; | |
547 } | |
548 | |
549 static FunctionType* cast(TypeImpl* type) { | |
550 ASSERT(type->IsFunction()); | |
551 return static_cast<FunctionType*>(type); | |
552 } | |
553 }; | |
554 | |
555 | |
556 template<class Config> template<class T> | |
557 class TypeImpl<Config>::Iterator { | |
558 public: | |
559 bool Done() const { return index_ < 0; } | |
560 i::Handle<T> Current(); | |
561 void Advance(); | |
562 | |
563 private: | |
564 template<class> friend class TypeImpl; | |
565 | |
566 Iterator() : index_(-1) {} | |
567 explicit Iterator(TypeHandle type) : type_(type), index_(-1) { | |
568 Advance(); | |
569 } | |
570 | |
571 inline bool matches(TypeHandle type); | |
572 inline TypeHandle get_type(); | |
573 | |
574 TypeHandle type_; | |
575 int index_; | |
576 }; | |
577 | |
578 | |
579 // Zone-allocated types are either (odd) integers to represent bitsets, or | 403 // Zone-allocated types are either (odd) integers to represent bitsets, or |
580 // (even) pointers to structures for everything else. | 404 // (even) pointers to structures for everything else. |
581 struct ZoneTypeConfig { | 405 struct ZoneTypeConfig { |
582 typedef TypeImpl<ZoneTypeConfig> Type; | 406 typedef TypeImpl<ZoneTypeConfig> Type; |
583 class Base {}; | 407 class Base {}; |
584 typedef void* Struct; | 408 typedef void* Struct; |
585 typedef i::Zone Region; | 409 typedef i::Zone Region; |
586 template<class T> struct Handle { typedef T* type; }; | 410 template<class T> struct Handle { typedef T* type; }; |
587 | 411 |
588 template<class T> static inline T* handle(T* type); | 412 static inline Type* handle(Type* type); |
589 template<class T> static inline T* cast(Type* type); | |
590 | |
591 static inline bool is_bitset(Type* type); | 413 static inline bool is_bitset(Type* type); |
592 static inline bool is_class(Type* type); | 414 static inline bool is_class(Type* type); |
593 static inline bool is_constant(Type* type); | 415 static inline bool is_constant(Type* type); |
594 static inline bool is_struct(Type* type, int tag); | 416 static inline bool is_struct(Type* type); |
595 | |
596 static inline int as_bitset(Type* type); | 417 static inline int as_bitset(Type* type); |
597 static inline Struct* as_struct(Type* type); | 418 static inline Struct* as_struct(Type* type); |
598 static inline i::Handle<i::Map> as_class(Type* type); | 419 static inline i::Handle<i::Map> as_class(Type* type); |
599 static inline i::Handle<i::Object> as_constant(Type* type); | 420 static inline i::Handle<i::Object> as_constant(Type* type); |
600 | |
601 static inline Type* from_bitset(int bitset); | 421 static inline Type* from_bitset(int bitset); |
602 static inline Type* from_bitset(int bitset, Zone* zone); | 422 static inline Type* from_bitset(int bitset, Zone* zone); |
603 static inline Type* from_struct(Struct* structured); | 423 static inline Type* from_struct(Struct* structured); |
604 static inline Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone); | 424 static inline Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone); |
605 static inline Type* from_constant( | 425 static inline Type* from_constant( |
606 i::Handle<i::Object> value, int lub, Zone* zone); | 426 i::Handle<i::Object> value, int lub, Zone* zone); |
607 | |
608 static inline Struct* struct_create(int tag, int length, Zone* zone); | 427 static inline Struct* struct_create(int tag, int length, Zone* zone); |
609 static inline void struct_shrink(Struct* structured, int length); | 428 static inline void struct_shrink(Struct* structured, int length); |
610 static inline int struct_tag(Struct* structured); | 429 static inline int struct_tag(Struct* structured); |
611 static inline int struct_length(Struct* structured); | 430 static inline int struct_length(Struct* structured); |
612 static inline Type* struct_get(Struct* structured, int i); | 431 static inline Type* struct_get(Struct* structured, int i); |
613 static inline void struct_set(Struct* structured, int i, Type* type); | 432 static inline void struct_set(Struct* structured, int i, Type* type); |
614 | |
615 static inline int lub_bitset(Type* type); | 433 static inline int lub_bitset(Type* type); |
616 }; | 434 }; |
617 | 435 |
618 typedef TypeImpl<ZoneTypeConfig> Type; | 436 typedef TypeImpl<ZoneTypeConfig> Type; |
619 | 437 |
620 | 438 |
621 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for | 439 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for |
622 // constants, or fixed arrays for unions. | 440 // constants, or fixed arrays for unions. |
623 struct HeapTypeConfig { | 441 struct HeapTypeConfig { |
624 typedef TypeImpl<HeapTypeConfig> Type; | 442 typedef TypeImpl<HeapTypeConfig> Type; |
625 typedef i::Object Base; | 443 typedef i::Object Base; |
626 typedef i::FixedArray Struct; | 444 typedef i::FixedArray Struct; |
627 typedef i::Isolate Region; | 445 typedef i::Isolate Region; |
628 template<class T> struct Handle { typedef i::Handle<T> type; }; | 446 template<class T> struct Handle { typedef i::Handle<T> type; }; |
629 | 447 |
630 template<class T> static inline i::Handle<T> handle(T* type); | 448 static inline i::Handle<Type> handle(Type* type); |
631 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); | |
632 | |
633 static inline bool is_bitset(Type* type); | 449 static inline bool is_bitset(Type* type); |
634 static inline bool is_class(Type* type); | 450 static inline bool is_class(Type* type); |
635 static inline bool is_constant(Type* type); | 451 static inline bool is_constant(Type* type); |
636 static inline bool is_struct(Type* type, int tag); | 452 static inline bool is_struct(Type* type); |
637 | |
638 static inline int as_bitset(Type* type); | 453 static inline int as_bitset(Type* type); |
639 static inline i::Handle<i::Map> as_class(Type* type); | 454 static inline i::Handle<i::Map> as_class(Type* type); |
640 static inline i::Handle<i::Object> as_constant(Type* type); | 455 static inline i::Handle<i::Object> as_constant(Type* type); |
641 static inline i::Handle<Struct> as_struct(Type* type); | 456 static inline i::Handle<Struct> as_struct(Type* type); |
642 | |
643 static inline Type* from_bitset(int bitset); | 457 static inline Type* from_bitset(int bitset); |
644 static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate); | 458 static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate); |
645 static inline i::Handle<Type> from_class( | 459 static inline i::Handle<Type> from_class( |
646 i::Handle<i::Map> map, int lub, Isolate* isolate); | 460 i::Handle<i::Map> map, int lub, Isolate* isolate); |
647 static inline i::Handle<Type> from_constant( | 461 static inline i::Handle<Type> from_constant( |
648 i::Handle<i::Object> value, int lub, Isolate* isolate); | 462 i::Handle<i::Object> value, int lub, Isolate* isolate); |
649 static inline i::Handle<Type> from_struct(i::Handle<Struct> structured); | 463 static inline i::Handle<Type> from_struct(i::Handle<Struct> structured); |
650 | |
651 static inline i::Handle<Struct> struct_create( | 464 static inline i::Handle<Struct> struct_create( |
652 int tag, int length, Isolate* isolate); | 465 int tag, int length, Isolate* isolate); |
653 static inline void struct_shrink(i::Handle<Struct> structured, int length); | 466 static inline void struct_shrink(i::Handle<Struct> structured, int length); |
654 static inline int struct_tag(i::Handle<Struct> structured); | 467 static inline int struct_tag(i::Handle<Struct> structured); |
655 static inline int struct_length(i::Handle<Struct> structured); | 468 static inline int struct_length(i::Handle<Struct> structured); |
656 static inline i::Handle<Type> struct_get(i::Handle<Struct> structured, int i); | 469 static inline i::Handle<Type> struct_get(i::Handle<Struct> structured, int i); |
657 static inline void struct_set( | 470 static inline void struct_set( |
658 i::Handle<Struct> structured, int i, i::Handle<Type> type); | 471 i::Handle<Struct> structured, int i, i::Handle<Type> type); |
659 | |
660 static inline int lub_bitset(Type* type); | 472 static inline int lub_bitset(Type* type); |
661 }; | 473 }; |
662 | 474 |
663 typedef TypeImpl<HeapTypeConfig> HeapType; | 475 typedef TypeImpl<HeapTypeConfig> HeapType; |
664 | 476 |
665 | 477 |
666 // A simple struct to represent a pair of lower/upper type bounds. | 478 // A simple struct to represent a pair of lower/upper type bounds. |
667 template<class Config> | 479 template<class Config> |
668 struct BoundsImpl { | 480 struct BoundsImpl { |
669 typedef TypeImpl<Config> Type; | 481 typedef TypeImpl<Config> Type; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 bool Narrows(BoundsImpl that) { | 527 bool Narrows(BoundsImpl that) { |
716 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 528 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
717 } | 529 } |
718 }; | 530 }; |
719 | 531 |
720 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 532 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
721 | 533 |
722 } } // namespace v8::internal | 534 } } // namespace v8::internal |
723 | 535 |
724 #endif // V8_TYPES_H_ | 536 #endif // V8_TYPES_H_ |
OLD | NEW |