1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_TYPES_H_ 6 #define V8_TYPES_H_ 7 8 #include "src/conversions.h" 9 #include "src/factory.h" 10 #include "src/handles.h" 11 #include "src/ostreams.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // SUMMARY 17 // 18 // A simple type system for compiler-internal use. It is based entirely on 19 // union types, and all subtyping hence amounts to set inclusion. Besides the 20 // obvious primitive types and some predefined unions, the type language also 21 // can express class types (a.k.a. specific maps) and singleton types (i.e., 22 // concrete constants). 23 // 24 // Types consist of two dimensions: semantic (value range) and representation. 25 // Both are related through subtyping. 26 // 27 // 28 // SEMANTIC DIMENSION 29 // 30 // The following equations and inequations hold for the semantic axis: 31 // 32 // None <= T 33 // T <= Any 34 // 35 // Number = Signed32 \/ Unsigned32 \/ Double 36 // Smi <= Signed32 37 // Name = String \/ Symbol 38 // UniqueName = InternalizedString \/ Symbol 39 // InternalizedString < String 40 // 41 // Receiver = Object \/ Proxy 42 // Array < Object 43 // Function < Object 44 // RegExp < Object 45 // Undetectable < Object 46 // Detectable = Receiver \/ Number \/ Name - Undetectable 47 // 48 // Class(map) < T iff instance_type(map) < T 49 // Constant(x) < T iff instance_type(map(x)) < T 50 // Array(T) < Array 51 // Function(R, S, T0, T1, ...) < Function 52 // Context(T) < Internal 53 // 54 // Both structural Array and Function types are invariant in all parameters; 55 // relaxing this would make Union and Intersect operations more involved. 56 // There is no subtyping relation between Array, Function, or Context types 57 // and respective Constant types, since these types cannot be reconstructed 58 // for arbitrary heap values. 59 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can 60 // change! (Its instance type cannot, however.) 61 // TODO(rossberg): the latter is not currently true for proxies, because of fix, 62 // but will hold once we implement direct proxies. 63 // However, we also define a 'temporal' variant of the subtyping relation that 64 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). 65 // 66 // 67 // REPRESENTATIONAL DIMENSION 68 // 69 // For the representation axis, the following holds: 70 // 71 // None <= R 72 // R <= Any 73 // 74 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ 75 // UntaggedInt16 \/ UntaggedInt32 76 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 77 // UntaggedNumber = UntaggedInt \/ UntaggedFloat 78 // Untagged = UntaggedNumber \/ UntaggedPtr 79 // Tagged = TaggedInt \/ TaggedPtr 80 // 81 // Subtyping relates the two dimensions, for example: 82 // 83 // Number <= Tagged \/ UntaggedNumber 84 // Object <= TaggedPtr \/ UntaggedPtr 85 // 86 // That holds because the semantic type constructors defined by the API create 87 // types that allow for all possible representations, and dually, the ones for 88 // representation types initially include all semantic ranges. Representations 89 // can then e.g. be narrowed for a given semantic type using intersection: 90 // 91 // SignedSmall /\ TaggedInt (a 'smi') 92 // Number /\ TaggedPtr (a heap number) 93 // 94 // 95 // RANGE TYPES 96 // 97 // A range type represents a continuous integer interval by its minimum and 98 // maximum value. Either value might be an infinity. 99 // 100 // Constant(v) is considered a subtype of Range(x..y) if v happens to be an 101 // integer between x and y. 102 // 103 // 104 // PREDICATES 105 // 106 // There are two main functions for testing types: 107 // 108 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) 109 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) 110 // 111 // Typically, the former is to be used to select representations (e.g., via 112 // T->Is(SignedSmall())), and the latter to check whether a specific case needs 113 // handling (e.g., via T->Maybe(Number())). 114 // 115 // There is no functionality to discover whether a type is a leaf in the 116 // lattice. That is intentional. It should always be possible to refine the 117 // lattice (e.g., splitting up number types further) without invalidating any 118 // existing assumptions or tests. 119 // Consequently, do not normally use Equals for type tests, always use Is! 120 // 121 // The NowIs operator implements state-sensitive subtying, as described above. 122 // Any compilation decision based on such temporary properties requires runtime 123 // guarding! 124 // 125 // 126 // PROPERTIES 127 // 128 // Various formal properties hold for constructors, operators, and predicates 129 // over types. For example, constructors are injective and subtyping is a 130 // complete partial order. 131 // 132 // See test/cctest/test-types.cc for a comprehensive executable specification, 133 // especially with respect to the properties of the more exotic 'temporal' 134 // constructors and predicates (those prefixed 'Now'). 135 // 136 // 137 // IMPLEMENTATION 138 // 139 // Internally, all 'primitive' types, and their unions, are represented as 140 // bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the 141 // respective map. Only structured types require allocation. 142 // Note that the bitset representation is closed under both Union and Intersect. 143 // 144 // There are two type representations, using different allocation: 145 // 146 // - class Type (zone-allocated, for compiler and concurrent compilation) 147 // - class HeapType (heap-allocated, for persistent types) 148 // 149 // Both provide the same API, and the Convert method can be used to interconvert 150 // them. For zone types, no query method touches the heap, only constructors do. 151 152 153 // ----------------------------------------------------------------------------- 154 // Values for bitset types 155 156 #define MASK_BITSET_TYPE_LIST(V) \ 157 V(Representation, 0xff800000u) \ 158 V(Semantic, 0x007ffffeu) 159 160 #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation) 161 #define SEMANTIC(k) ((k) & BitsetType::kSemantic) 162 163 #define REPRESENTATION_BITSET_TYPE_LIST(V) \ 164 V(None, 0) \ 165 V(UntaggedInt1, 1u << 23 | kSemantic) \ 166 V(UntaggedInt8, 1u << 24 | kSemantic) \ 167 V(UntaggedInt16, 1u << 25 | kSemantic) \ 168 V(UntaggedInt32, 1u << 26 | kSemantic) \ 169 V(UntaggedFloat32, 1u << 27 | kSemantic) \ 170 V(UntaggedFloat64, 1u << 28 | kSemantic) \ 171 V(UntaggedPtr, 1u << 29 | kSemantic) \ 172 V(TaggedInt, 1u << 30 | kSemantic) \ 173 V(TaggedPtr, 1u << 31 | kSemantic) \ 174 \ 175 V(UntaggedInt, kUntaggedInt1 | kUntaggedInt8 | \ 176 kUntaggedInt16 | kUntaggedInt32) \ 177 V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \ 178 V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \ 179 V(Untagged, kUntaggedNumber | kUntaggedPtr) \ 180 V(Tagged, kTaggedInt | kTaggedPtr) 181 182 #define SEMANTIC_BITSET_TYPE_LIST(V) \ 183 V(Null, 1u << 1 | REPRESENTATION(kTaggedPtr)) \ 184 V(Undefined, 1u << 2 | REPRESENTATION(kTaggedPtr)) \ 185 V(Boolean, 1u << 3 | REPRESENTATION(kTaggedPtr)) \ 186 V(UnsignedSmall, 1u << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 187 V(OtherSignedSmall, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 188 V(OtherUnsigned31, 1u << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 189 V(OtherUnsigned32, 1u << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 190 V(OtherSigned32, 1u << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 191 V(MinusZero, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 192 V(NaN, 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 193 V(OtherNumber, 1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \ 194 V(Symbol, 1u << 12 | REPRESENTATION(kTaggedPtr)) \ 195 V(InternalizedString, 1u << 13 | REPRESENTATION(kTaggedPtr)) \ 196 V(OtherString, 1u << 14 | REPRESENTATION(kTaggedPtr)) \ 197 V(Undetectable, 1u << 15 | REPRESENTATION(kTaggedPtr)) \ 198 V(Array, 1u << 16 | REPRESENTATION(kTaggedPtr)) \ 199 V(Buffer, 1u << 17 | REPRESENTATION(kTaggedPtr)) \ 200 V(Function, 1u << 18 | REPRESENTATION(kTaggedPtr)) \ 201 V(RegExp, 1u << 19 | REPRESENTATION(kTaggedPtr)) \ 202 V(OtherObject, 1u << 20 | REPRESENTATION(kTaggedPtr)) \ 203 V(Proxy, 1u << 21 | REPRESENTATION(kTaggedPtr)) \ 204 V(Internal, 1u << 22 | REPRESENTATION(kTagged | kUntagged)) \ 205 \ 206 V(SignedSmall, kUnsignedSmall | kOtherSignedSmall) \ 207 V(Signed32, kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \ 208 V(Unsigned32, kUnsignedSmall | kOtherUnsigned31 | kOtherUnsigned32) \ 209 V(Integral32, kSigned32 | kUnsigned32) \ 210 V(OrderedNumber, kIntegral32 | kMinusZero | kOtherNumber) \ 211 V(Number, kOrderedNumber | kNaN) \ 212 V(String, kInternalizedString | kOtherString) \ 213 V(UniqueName, kSymbol | kInternalizedString) \ 214 V(Name, kSymbol | kString) \ 215 V(NumberOrString, kNumber | kString) \ 216 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ 217 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ 218 V(DetectableReceiver, kDetectableObject | kProxy) \ 219 V(Detectable, kDetectableReceiver | kNumber | kName) \ 220 V(Object, kDetectableObject | kUndetectable) \ 221 V(Receiver, kObject | kProxy) \ 222 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ 223 kUndefined | kInternal) \ 224 V(Any, 0xfffffffeu) 225 226 /* 227 * The following diagrams show how integers (in the mathematical sense) are 228 * divided among the different atomic numerical types. 229 * 230 * If SmiValuesAre31Bits(): 231 * 232 * ON OS32 OSS US OU31 OU32 ON 233 * ______[_______[_______[_______[_______[_______[_______ 234 * -2^31 -2^30 0 2^30 2^31 2^32 235 * 236 * Otherwise: 237 * 238 * ON OSS US OU32 ON 239 * ______[_______________[_______________[_______[_______ 240 * -2^31 0 2^31 2^32 241 * 242 * 243 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. 244 * 245 */ 246 247 #define PROPER_BITSET_TYPE_LIST(V) \ 248 REPRESENTATION_BITSET_TYPE_LIST(V) \ 249 SEMANTIC_BITSET_TYPE_LIST(V) 250 251 #define BITSET_TYPE_LIST(V) \ 252 MASK_BITSET_TYPE_LIST(V) \ 253 PROPER_BITSET_TYPE_LIST(V) 254 255 256 // ----------------------------------------------------------------------------- 257 // The abstract Type class, parameterized over the low-level representation. 258 259 // struct Config { 260 // typedef TypeImpl<Config> Type; 261 // typedef Base; 262 // typedef Struct; 263 // typedef Region; 264 // template<class> struct Handle { typedef type; } // No template typedefs... 265 // template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t) 266 // template<class T> static Handle<T>::type cast(Handle<Type>::type); 267 // static bool is_bitset(Type*); 268 // static bool is_class(Type*); 269 // static bool is_struct(Type*, int tag); 270 // static bitset as_bitset(Type*); 271 // static i::Handle<i::Map> as_class(Type*); 272 // static Handle<Struct>::type as_struct(Type*); 273 // static Type* from_bitset(bitset); 274 // static Handle<Type>::type from_bitset(bitset, Region*); 275 // static Handle<Type>::type from_class(i::Handle<Map>, Region*); 276 // static Handle<Type>::type from_struct(Handle<Struct>::type, int tag); 277 // static Handle<Struct>::type struct_create(int tag, int length, Region*); 278 // static void struct_shrink(Handle<Struct>::type, int length); 279 // static int struct_tag(Handle<Struct>::type); 280 // static int struct_length(Handle<Struct>::type); 281 // static Handle<Type>::type struct_get(Handle<Struct>::type, int); 282 // static void struct_set(Handle<Struct>::type, int, Handle<Type>::type); 283 // template<class V> 284 // static i::Handle<V> struct_get_value(Handle<Struct>::type, int); 285 // template<class V> 286 // static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>); 287 // } 288 template<class Config> 289 class TypeImpl : public Config::Base { 290 public: 291 // Auxiliary types. 292 293 typedef uint32_t bitset; // Internal 294 class BitsetType; // Internal 295 class StructuralType; // Internal 296 class UnionType; // Internal 297 298 class ClassType; 299 class ConstantType; 300 class RangeType; 301 class ContextType; 302 class ArrayType; 303 class FunctionType; 304 305 typedef typename Config::template Handle<TypeImpl>::type TypeHandle; 306 typedef typename Config::template Handle<ClassType>::type ClassHandle; 307 typedef typename Config::template Handle<ConstantType>::type ConstantHandle; 308 typedef typename Config::template Handle<RangeType>::type RangeHandle; 309 typedef typename Config::template Handle<ContextType>::type ContextHandle; 310 typedef typename Config::template Handle<ArrayType>::type ArrayHandle; 311 typedef typename Config::template Handle<FunctionType>::type FunctionHandle; 312 typedef typename Config::template Handle<UnionType>::type UnionHandle; 313 typedef typename Config::Region Region; 314 315 // Constructors. 316 317 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ 318 static TypeImpl* type() { \ 319 return BitsetType::New(BitsetType::k##type); \ 320 } \ 321 static TypeHandle type(Region* region) { \ 322 return BitsetType::New(BitsetType::k##type, region); \ 323 } PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)324 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) 325 #undef DEFINE_TYPE_CONSTRUCTOR 326 327 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { 328 return ClassType::New(map, region); 329 } Constant(i::Handle<i::Object> value,Region * region)330 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { 331 return ConstantType::New(value, region); 332 } Range(i::Handle<i::Object> min,i::Handle<i::Object> max,Region * region)333 static TypeHandle Range( 334 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { 335 return RangeType::New(min, max, region); 336 } Context(TypeHandle outer,Region * region)337 static TypeHandle Context(TypeHandle outer, Region* region) { 338 return ContextType::New(outer, region); 339 } Array(TypeHandle element,Region * region)340 static TypeHandle Array(TypeHandle element, Region* region) { 341 return ArrayType::New(element, region); 342 } Function(TypeHandle result,TypeHandle receiver,int arity,Region * region)343 static FunctionHandle Function( 344 TypeHandle result, TypeHandle receiver, int arity, Region* region) { 345 return FunctionType::New(result, receiver, arity, region); 346 } Function(TypeHandle result,Region * region)347 static TypeHandle Function(TypeHandle result, Region* region) { 348 return Function(result, Any(region), 0, region); 349 } Function(TypeHandle result,TypeHandle param0,Region * region)350 static TypeHandle Function( 351 TypeHandle result, TypeHandle param0, Region* region) { 352 FunctionHandle function = Function(result, Any(region), 1, region); 353 function->InitParameter(0, param0); 354 return function; 355 } Function(TypeHandle result,TypeHandle param0,TypeHandle param1,Region * region)356 static TypeHandle Function( 357 TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) { 358 FunctionHandle function = Function(result, Any(region), 2, region); 359 function->InitParameter(0, param0); 360 function->InitParameter(1, param1); 361 return function; 362 } Function(TypeHandle result,TypeHandle param0,TypeHandle param1,TypeHandle param2,Region * region)363 static TypeHandle Function( 364 TypeHandle result, TypeHandle param0, TypeHandle param1, 365 TypeHandle param2, Region* region) { 366 FunctionHandle function = Function(result, Any(region), 3, region); 367 function->InitParameter(0, param0); 368 function->InitParameter(1, param1); 369 function->InitParameter(2, param2); 370 return function; 371 } 372 373 static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); 374 static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); 375 Of(double value,Region * region)376 static TypeHandle Of(double value, Region* region) { 377 return Config::from_bitset(BitsetType::Lub(value), region); 378 } Of(i::Object * value,Region * region)379 static TypeHandle Of(i::Object* value, Region* region) { 380 return Config::from_bitset(BitsetType::Lub(value), region); 381 } Of(i::Handle<i::Object> value,Region * region)382 static TypeHandle Of(i::Handle<i::Object> value, Region* region) { 383 return Of(*value, region); 384 } 385 386 // Predicates. 387 IsInhabited()388 bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); } 389 Is(TypeImpl * that)390 bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } 391 template<class TypeHandle> Is(TypeHandle that)392 bool Is(TypeHandle that) { return this->Is(*that); } 393 394 bool Maybe(TypeImpl* that); 395 template<class TypeHandle> Maybe(TypeHandle that)396 bool Maybe(TypeHandle that) { return this->Maybe(*that); } 397 Equals(TypeImpl * that)398 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } 399 template<class TypeHandle> Equals(TypeHandle that)400 bool Equals(TypeHandle that) { return this->Equals(*that); } 401 402 // Equivalent to Constant(val)->Is(this), but avoiding allocation. 403 bool Contains(i::Object* val); Contains(i::Handle<i::Object> val)404 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } 405 406 // State-dependent versions of the above that consider subtyping between 407 // a constant and its map class. 408 inline static TypeHandle NowOf(i::Object* value, Region* region); NowOf(i::Handle<i::Object> value,Region * region)409 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { 410 return NowOf(*value, region); 411 } 412 bool NowIs(TypeImpl* that); 413 template<class TypeHandle> NowIs(TypeHandle that)414 bool NowIs(TypeHandle that) { return this->NowIs(*that); } 415 inline bool NowContains(i::Object* val); NowContains(i::Handle<i::Object> val)416 bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); } 417 418 bool NowStable(); 419 420 // Inspection. 421 IsClass()422 bool IsClass() { 423 return Config::is_class(this) 424 || Config::is_struct(this, StructuralType::kClassTag); 425 } IsConstant()426 bool IsConstant() { 427 return Config::is_struct(this, StructuralType::kConstantTag); 428 } IsRange()429 bool IsRange() { 430 return Config::is_struct(this, StructuralType::kRangeTag); 431 } IsContext()432 bool IsContext() { 433 return Config::is_struct(this, StructuralType::kContextTag); 434 } IsArray()435 bool IsArray() { 436 return Config::is_struct(this, StructuralType::kArrayTag); 437 } IsFunction()438 bool IsFunction() { 439 return Config::is_struct(this, StructuralType::kFunctionTag); 440 } 441 AsClass()442 ClassType* AsClass() { return ClassType::cast(this); } AsConstant()443 ConstantType* AsConstant() { return ConstantType::cast(this); } AsRange()444 RangeType* AsRange() { return RangeType::cast(this); } AsContext()445 ContextType* AsContext() { return ContextType::cast(this); } AsArray()446 ArrayType* AsArray() { return ArrayType::cast(this); } AsFunction()447 FunctionType* AsFunction() { return FunctionType::cast(this); } 448 449 // Minimum and maximum of a numeric type. 450 // These functions do not distinguish between -0 and +0. If the type equals 451 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these 452 // functions on subtypes of Number. 453 double Min(); 454 double Max(); 455 456 int NumClasses(); 457 int NumConstants(); 458 459 template<class T> class Iterator; Classes()460 Iterator<i::Map> Classes() { 461 if (this->IsBitset()) return Iterator<i::Map>(); 462 return Iterator<i::Map>(Config::handle(this)); 463 } Constants()464 Iterator<i::Object> Constants() { 465 if (this->IsBitset()) return Iterator<i::Object>(); 466 return Iterator<i::Object>(Config::handle(this)); 467 } 468 469 // Casting and conversion. 470 471 static inline TypeImpl* cast(typename Config::Base* object); 472 473 template<class OtherTypeImpl> 474 static TypeHandle Convert( 475 typename OtherTypeImpl::TypeHandle type, Region* region); 476 477 // Printing. 478 479 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; 480 481 void PrintTo(OStream& os, PrintDimension dim = BOTH_DIMS); // NOLINT 482 483 #ifdef DEBUG 484 void Print(); 485 #endif 486 487 protected: 488 // Friends. 489 490 template<class> friend class Iterator; 491 template<class> friend class TypeImpl; 492 493 // Handle conversion. 494 495 template<class T> handle(T * type)496 static typename Config::template Handle<T>::type handle(T* type) { 497 return Config::handle(type); 498 } unhandle()499 TypeImpl* unhandle() { return this; } 500 501 // Internal inspection. 502 IsNone()503 bool IsNone() { return this == None(); } IsAny()504 bool IsAny() { return this == Any(); } IsBitset()505 bool IsBitset() { return Config::is_bitset(this); } IsUnion()506 bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); } 507 AsBitset()508 bitset AsBitset() { 509 DCHECK(this->IsBitset()); 510 return static_cast<BitsetType*>(this)->Bitset(); 511 } AsUnion()512 UnionType* AsUnion() { return UnionType::cast(this); } 513 514 // Auxiliary functions. 515 BitsetGlb()516 bitset BitsetGlb() { return BitsetType::Glb(this); } BitsetLub()517 bitset BitsetLub() { return BitsetType::Lub(this); } 518 519 bool SlowIs(TypeImpl* that); 520 IsInteger(double x)521 static bool IsInteger(double x) { 522 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. 523 } IsInteger(i::Object * x)524 static bool IsInteger(i::Object* x) { 525 return x->IsNumber() && IsInteger(x->Number()); 526 } 527 528 struct Limits { 529 i::Handle<i::Object> min; 530 i::Handle<i::Object> max; LimitsLimits531 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) : 532 min(min), max(max) {} LimitsLimits533 explicit Limits(RangeType* range) : 534 min(range->Min()), max(range->Max()) {} 535 }; 536 537 static Limits Intersect(Limits lhs, Limits rhs); 538 static Limits Union(Limits lhs, Limits rhs); 539 static bool Overlap(RangeType* lhs, RangeType* rhs); 540 static bool Contains(RangeType* lhs, RangeType* rhs); 541 static bool Contains(RangeType* range, i::Object* val); 542 543 RangeType* GetRange(); 544 static int UpdateRange( 545 RangeHandle type, UnionHandle result, int size, Region* region); 546 547 bool SimplyEquals(TypeImpl* that); 548 template<class TypeHandle> SimplyEquals(TypeHandle that)549 bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); } 550 551 static int AddToUnion( 552 TypeHandle type, UnionHandle result, int size, Region* region); 553 static int IntersectAux( 554 TypeHandle type, TypeHandle other, 555 UnionHandle result, int size, Region* region); 556 static TypeHandle NormalizeUnion(UnionHandle unioned, int size); 557 }; 558 559 560 // ----------------------------------------------------------------------------- 561 // Bitset types (internal). 562 563 template<class Config> 564 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { 565 protected: 566 friend class TypeImpl<Config>; 567 568 enum { 569 #define DECLARE_TYPE(type, value) k##type = (value), 570 BITSET_TYPE_LIST(DECLARE_TYPE) 571 #undef DECLARE_TYPE 572 kUnusedEOL = 0 573 }; 574 Bitset()575 bitset Bitset() { return Config::as_bitset(this); } 576 New(bitset bits)577 static TypeImpl* New(bitset bits) { 578 DCHECK(bits == kNone || IsInhabited(bits)); 579 return Config::from_bitset(bits); 580 } New(bitset bits,Region * region)581 static TypeHandle New(bitset bits, Region* region) { 582 DCHECK(bits == kNone || IsInhabited(bits)); 583 return Config::from_bitset(bits, region); 584 } 585 // TODO(neis): Eventually allow again for types with empty semantics 586 // part and modify intersection and possibly subtyping accordingly. 587 IsInhabited(bitset bits)588 static bool IsInhabited(bitset bits) { 589 return bits & kSemantic; 590 } 591 Is(bitset bits1,bitset bits2)592 static bool Is(bitset bits1, bitset bits2) { 593 return (bits1 | bits2) == bits2; 594 } 595 596 static double Min(bitset); 597 static double Max(bitset); 598 599 static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset 600 static bitset Lub(TypeImpl* type); // least upper bound that's a bitset 601 static bitset Lub(i::Object* value); 602 static bitset Lub(double value); 603 static bitset Lub(int32_t value); 604 static bitset Lub(uint32_t value); 605 static bitset Lub(i::Map* map); 606 static bitset Lub(Limits lim); 607 608 static const char* Name(bitset); 609 static void Print(OStream& os, bitset); // NOLINT 610 #ifdef DEBUG 611 static void Print(bitset); 612 #endif 613 614 private: 615 struct BitsetMin{ 616 bitset bits; 617 double min; 618 }; 619 static const BitsetMin BitsetMins31[]; 620 static const BitsetMin BitsetMins32[]; BitsetMins()621 static const BitsetMin* BitsetMins() { 622 return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32; 623 } BitsetMinsSize()624 static size_t BitsetMinsSize() { 625 return i::SmiValuesAre31Bits() ? 7 : 5; 626 /* arraysize(BitsetMins31) : arraysize(BitsetMins32); */ 627 // Using arraysize here doesn't compile on Windows. 628 } 629 }; 630 631 632 // ----------------------------------------------------------------------------- 633 // Superclass for non-bitset types (internal). 634 // Contains a tag and a variable number of type or value fields. 635 636 template<class Config> 637 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { 638 protected: 639 template<class> friend class TypeImpl; 640 friend struct ZoneTypeConfig; // For tags. 641 friend struct HeapTypeConfig; 642 643 enum Tag { 644 kClassTag, 645 kConstantTag, 646 kRangeTag, 647 kContextTag, 648 kArrayTag, 649 kFunctionTag, 650 kUnionTag 651 }; 652 Length()653 int Length() { 654 return Config::struct_length(Config::as_struct(this)); 655 } Get(int i)656 TypeHandle Get(int i) { 657 DCHECK(0 <= i && i < this->Length()); 658 return Config::struct_get(Config::as_struct(this), i); 659 } Set(int i,TypeHandle type)660 void Set(int i, TypeHandle type) { 661 DCHECK(0 <= i && i < this->Length()); 662 Config::struct_set(Config::as_struct(this), i, type); 663 } Shrink(int length)664 void Shrink(int length) { 665 DCHECK(2 <= length && length <= this->Length()); 666 Config::struct_shrink(Config::as_struct(this), length); 667 } GetValue(int i)668 template<class V> i::Handle<V> GetValue(int i) { 669 DCHECK(0 <= i && i < this->Length()); 670 return Config::template struct_get_value<V>(Config::as_struct(this), i); 671 } SetValue(int i,i::Handle<V> x)672 template<class V> void SetValue(int i, i::Handle<V> x) { 673 DCHECK(0 <= i && i < this->Length()); 674 Config::struct_set_value(Config::as_struct(this), i, x); 675 } 676 New(Tag tag,int length,Region * region)677 static TypeHandle New(Tag tag, int length, Region* region) { 678 DCHECK(1 <= length); 679 return Config::from_struct(Config::struct_create(tag, length, region)); 680 } 681 }; 682 683 684 // ----------------------------------------------------------------------------- 685 // Union types (internal). 686 // A union is a structured type with the following invariants: 687 // - its length is at least 2 688 // - at most one field is a bitset, and it must go into index 0 689 // - no field is a union 690 // - no field is a subtype of any other field 691 template<class Config> 692 class TypeImpl<Config>::UnionType : public StructuralType { 693 public: New(int length,Region * region)694 static UnionHandle New(int length, Region* region) { 695 return Config::template cast<UnionType>( 696 StructuralType::New(StructuralType::kUnionTag, length, region)); 697 } 698 cast(TypeImpl * type)699 static UnionType* cast(TypeImpl* type) { 700 DCHECK(type->IsUnion()); 701 return static_cast<UnionType*>(type); 702 } 703 704 bool Wellformed(); 705 }; 706 707 708 // ----------------------------------------------------------------------------- 709 // Class types. 710 711 template<class Config> 712 class TypeImpl<Config>::ClassType : public StructuralType { 713 public: Bound(Region * region)714 TypeHandle Bound(Region* region) { 715 return Config::is_class(this) ? 716 BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) : 717 this->Get(0); 718 } Map()719 i::Handle<i::Map> Map() { 720 return Config::is_class(this) ? Config::as_class(this) : 721 this->template GetValue<i::Map>(1); 722 } 723 New(i::Handle<i::Map> map,Region * region)724 static ClassHandle New(i::Handle<i::Map> map, Region* region) { 725 ClassHandle type = 726 Config::template cast<ClassType>(Config::from_class(map, region)); 727 if (!type->IsClass()) { 728 type = Config::template cast<ClassType>( 729 StructuralType::New(StructuralType::kClassTag, 2, region)); 730 type->Set(0, BitsetType::New(BitsetType::Lub(*map), region)); 731 type->SetValue(1, map); 732 } 733 return type; 734 } 735 cast(TypeImpl * type)736 static ClassType* cast(TypeImpl* type) { 737 DCHECK(type->IsClass()); 738 return static_cast<ClassType*>(type); 739 } 740 }; 741 742 743 // ----------------------------------------------------------------------------- 744 // Constant types. 745 746 template<class Config> 747 class TypeImpl<Config>::ConstantType : public StructuralType { 748 public: Bound()749 TypeHandle Bound() { return this->Get(0); } Value()750 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } 751 New(i::Handle<i::Object> value,Region * region)752 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { 753 ConstantHandle type = Config::template cast<ConstantType>( 754 StructuralType::New(StructuralType::kConstantTag, 2, region)); 755 type->Set(0, BitsetType::New(BitsetType::Lub(*value), region)); 756 type->SetValue(1, value); 757 return type; 758 } 759 cast(TypeImpl * type)760 static ConstantType* cast(TypeImpl* type) { 761 DCHECK(type->IsConstant()); 762 return static_cast<ConstantType*>(type); 763 } 764 }; 765 // TODO(neis): Also cache value if numerical. 766 // TODO(neis): Allow restricting the representation. 767 768 769 // ----------------------------------------------------------------------------- 770 // Range types. 771 772 template<class Config> 773 class TypeImpl<Config>::RangeType : public StructuralType { 774 public: BitsetLub()775 int BitsetLub() { return this->Get(0)->AsBitset(); } Min()776 i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); } Max()777 i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); } 778 New(i::Handle<i::Object> min,i::Handle<i::Object> max,Region * region)779 static RangeHandle New( 780 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { 781 DCHECK(min->Number() <= max->Number()); 782 RangeHandle type = Config::template cast<RangeType>( 783 StructuralType::New(StructuralType::kRangeTag, 3, region)); 784 type->Set(0, BitsetType::New(BitsetType::Lub(Limits(min, max)), region)); 785 type->SetValue(1, min); 786 type->SetValue(2, max); 787 return type; 788 } 789 New(Limits lim,Region * region)790 static RangeHandle New(Limits lim, Region* region) { 791 return New(lim.min, lim.max, region); 792 } 793 cast(TypeImpl * type)794 static RangeType* cast(TypeImpl* type) { 795 DCHECK(type->IsRange()); 796 return static_cast<RangeType*>(type); 797 } 798 }; 799 // TODO(neis): Also cache min and max values. 800 // TODO(neis): Allow restricting the representation. 801 802 803 // ----------------------------------------------------------------------------- 804 // Context types. 805 806 template<class Config> 807 class TypeImpl<Config>::ContextType : public StructuralType { 808 public: Outer()809 TypeHandle Outer() { return this->Get(0); } 810 New(TypeHandle outer,Region * region)811 static ContextHandle New(TypeHandle outer, Region* region) { 812 ContextHandle type = Config::template cast<ContextType>( 813 StructuralType::New(StructuralType::kContextTag, 1, region)); 814 type->Set(0, outer); 815 return type; 816 } 817 cast(TypeImpl * type)818 static ContextType* cast(TypeImpl* type) { 819 DCHECK(type->IsContext()); 820 return static_cast<ContextType*>(type); 821 } 822 }; 823 824 825 // ----------------------------------------------------------------------------- 826 // Array types. 827 828 template<class Config> 829 class TypeImpl<Config>::ArrayType : public StructuralType { 830 public: Element()831 TypeHandle Element() { return this->Get(0); } 832 New(TypeHandle element,Region * region)833 static ArrayHandle New(TypeHandle element, Region* region) { 834 ArrayHandle type = Config::template cast<ArrayType>( 835 StructuralType::New(StructuralType::kArrayTag, 1, region)); 836 type->Set(0, element); 837 return type; 838 } 839 cast(TypeImpl * type)840 static ArrayType* cast(TypeImpl* type) { 841 DCHECK(type->IsArray()); 842 return static_cast<ArrayType*>(type); 843 } 844 }; 845 846 847 // ----------------------------------------------------------------------------- 848 // Function types. 849 850 template<class Config> 851 class TypeImpl<Config>::FunctionType : public StructuralType { 852 public: Arity()853 int Arity() { return this->Length() - 2; } Result()854 TypeHandle Result() { return this->Get(0); } Receiver()855 TypeHandle Receiver() { return this->Get(1); } Parameter(int i)856 TypeHandle Parameter(int i) { return this->Get(2 + i); } 857 InitParameter(int i,TypeHandle type)858 void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); } 859 New(TypeHandle result,TypeHandle receiver,int arity,Region * region)860 static FunctionHandle New( 861 TypeHandle result, TypeHandle receiver, int arity, Region* region) { 862 FunctionHandle type = Config::template cast<FunctionType>( 863 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); 864 type->Set(0, result); 865 type->Set(1, receiver); 866 return type; 867 } 868 cast(TypeImpl * type)869 static FunctionType* cast(TypeImpl* type) { 870 DCHECK(type->IsFunction()); 871 return static_cast<FunctionType*>(type); 872 } 873 }; 874 875 876 // ----------------------------------------------------------------------------- 877 // Type iterators. 878 879 template<class Config> template<class T> 880 class TypeImpl<Config>::Iterator { 881 public: Done()882 bool Done() const { return index_ < 0; } 883 i::Handle<T> Current(); 884 void Advance(); 885 886 private: 887 template<class> friend class TypeImpl; 888 Iterator()889 Iterator() : index_(-1) {} Iterator(TypeHandle type)890 explicit Iterator(TypeHandle type) : type_(type), index_(-1) { 891 Advance(); 892 } 893 894 inline bool matches(TypeHandle type); 895 inline TypeHandle get_type(); 896 897 TypeHandle type_; 898 int index_; 899 }; 900 901 902 // ----------------------------------------------------------------------------- 903 // Zone-allocated types; they are either (odd) integers to represent bitsets, or 904 // (even) pointers to structures for everything else. 905 906 struct ZoneTypeConfig { 907 typedef TypeImpl<ZoneTypeConfig> Type; 908 class Base {}; 909 typedef void* Struct; 910 typedef i::Zone Region; 911 template<class T> struct Handle { typedef T* type; }; 912 913 template<class T> static inline T* handle(T* type); 914 template<class T> static inline T* cast(Type* type); 915 916 static inline bool is_bitset(Type* type); 917 static inline bool is_class(Type* type); 918 static inline bool is_struct(Type* type, int tag); 919 920 static inline Type::bitset as_bitset(Type* type); 921 static inline i::Handle<i::Map> as_class(Type* type); 922 static inline Struct* as_struct(Type* type); 923 924 static inline Type* from_bitset(Type::bitset); 925 static inline Type* from_bitset(Type::bitset, Zone* zone); 926 static inline Type* from_class(i::Handle<i::Map> map, Zone* zone); 927 static inline Type* from_struct(Struct* structured); 928 929 static inline Struct* struct_create(int tag, int length, Zone* zone); 930 static inline void struct_shrink(Struct* structure, int length); 931 static inline int struct_tag(Struct* structure); 932 static inline int struct_length(Struct* structure); 933 static inline Type* struct_get(Struct* structure, int i); 934 static inline void struct_set(Struct* structure, int i, Type* type); 935 template<class V> 936 static inline i::Handle<V> struct_get_value(Struct* structure, int i); 937 template<class V> static inline void struct_set_value( 938 Struct* structure, int i, i::Handle<V> x); 939 }; 940 941 typedef TypeImpl<ZoneTypeConfig> Type; 942 943 944 // ----------------------------------------------------------------------------- 945 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for 946 // constants, or fixed arrays for unions. 947 948 struct HeapTypeConfig { 949 typedef TypeImpl<HeapTypeConfig> Type; 950 typedef i::Object Base; 951 typedef i::FixedArray Struct; 952 typedef i::Isolate Region; 953 template<class T> struct Handle { typedef i::Handle<T> type; }; 954 955 template<class T> static inline i::Handle<T> handle(T* type); 956 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); 957 958 static inline bool is_bitset(Type* type); 959 static inline bool is_class(Type* type); 960 static inline bool is_struct(Type* type, int tag); 961 962 static inline Type::bitset as_bitset(Type* type); 963 static inline i::Handle<i::Map> as_class(Type* type); 964 static inline i::Handle<Struct> as_struct(Type* type); 965 966 static inline Type* from_bitset(Type::bitset); 967 static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate); 968 static inline i::Handle<Type> from_class( 969 i::Handle<i::Map> map, Isolate* isolate); 970 static inline i::Handle<Type> from_struct(i::Handle<Struct> structure); 971 972 static inline i::Handle<Struct> struct_create( 973 int tag, int length, Isolate* isolate); 974 static inline void struct_shrink(i::Handle<Struct> structure, int length); 975 static inline int struct_tag(i::Handle<Struct> structure); 976 static inline int struct_length(i::Handle<Struct> structure); 977 static inline i::Handle<Type> struct_get(i::Handle<Struct> structure, int i); 978 static inline void struct_set( 979 i::Handle<Struct> structure, int i, i::Handle<Type> type); 980 template<class V> 981 static inline i::Handle<V> struct_get_value( 982 i::Handle<Struct> structure, int i); 983 template<class V> 984 static inline void struct_set_value( 985 i::Handle<Struct> structure, int i, i::Handle<V> x); 986 }; 987 988 typedef TypeImpl<HeapTypeConfig> HeapType; 989 990 991 // ----------------------------------------------------------------------------- 992 // Type bounds. A simple struct to represent a pair of lower/upper types. 993 994 template<class Config> 995 struct BoundsImpl { 996 typedef TypeImpl<Config> Type; 997 typedef typename Type::TypeHandle TypeHandle; 998 typedef typename Type::Region Region; 999 1000 TypeHandle lower; 1001 TypeHandle upper; 1002 BoundsImplBoundsImpl1003 BoundsImpl() {} BoundsImplBoundsImpl1004 explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {} BoundsImplBoundsImpl1005 BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) { 1006 DCHECK(lower->Is(upper)); 1007 } 1008 1009 // Unrestricted bounds. UnboundedBoundsImpl1010 static BoundsImpl Unbounded(Region* region) { 1011 return BoundsImpl(Type::None(region), Type::Any(region)); 1012 } 1013 1014 // Meet: both b1 and b2 are known to hold. BothBoundsImpl1015 static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) { 1016 TypeHandle lower = Type::Union(b1.lower, b2.lower, region); 1017 TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region); 1018 // Lower bounds are considered approximate, correct as necessary. 1019 lower = Type::Intersect(lower, upper, region); 1020 return BoundsImpl(lower, upper); 1021 } 1022 1023 // Join: either b1 or b2 is known to hold. EitherBoundsImpl1024 static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) { 1025 TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region); 1026 TypeHandle upper = Type::Union(b1.upper, b2.upper, region); 1027 return BoundsImpl(lower, upper); 1028 } 1029 NarrowLowerBoundsImpl1030 static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) { 1031 // Lower bounds are considered approximate, correct as necessary. 1032 t = Type::Intersect(t, b.upper, region); 1033 TypeHandle lower = Type::Union(b.lower, t, region); 1034 return BoundsImpl(lower, b.upper); 1035 } NarrowUpperBoundsImpl1036 static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) { 1037 TypeHandle lower = Type::Intersect(b.lower, t, region); 1038 TypeHandle upper = Type::Intersect(b.upper, t, region); 1039 return BoundsImpl(lower, upper); 1040 } 1041 NarrowsBoundsImpl1042 bool Narrows(BoundsImpl that) { 1043 return that.lower->Is(this->lower) && this->upper->Is(that.upper); 1044 } 1045 }; 1046 1047 typedef BoundsImpl<ZoneTypeConfig> Bounds; 1048 1049 } } // namespace v8::internal 1050 1051 #endif // V8_TYPES_H_ 1052