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