| OLD | NEW |
| (Empty) |
| 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/handles.h" | |
| 10 #include "src/objects.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 // RegExp < Object | |
| 43 // OtherUndetectable < Object | |
| 44 // DetectableReceiver = Receiver - OtherUndetectable | |
| 45 // | |
| 46 // Constant(x) < T iff instance_type(map(x)) < T | |
| 47 // | |
| 48 // | |
| 49 // REPRESENTATIONAL DIMENSION | |
| 50 // | |
| 51 // For the representation axis, the following holds: | |
| 52 // | |
| 53 // None <= R | |
| 54 // R <= Any | |
| 55 // | |
| 56 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ | |
| 57 // UntaggedInt16 \/ UntaggedInt32 | |
| 58 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 | |
| 59 // UntaggedNumber = UntaggedInt \/ UntaggedFloat | |
| 60 // Untagged = UntaggedNumber \/ UntaggedPtr | |
| 61 // Tagged = TaggedInt \/ TaggedPtr | |
| 62 // | |
| 63 // Subtyping relates the two dimensions, for example: | |
| 64 // | |
| 65 // Number <= Tagged \/ UntaggedNumber | |
| 66 // Object <= TaggedPtr \/ UntaggedPtr | |
| 67 // | |
| 68 // That holds because the semantic type constructors defined by the API create | |
| 69 // types that allow for all possible representations, and dually, the ones for | |
| 70 // representation types initially include all semantic ranges. Representations | |
| 71 // can then e.g. be narrowed for a given semantic type using intersection: | |
| 72 // | |
| 73 // SignedSmall /\ TaggedInt (a 'smi') | |
| 74 // Number /\ TaggedPtr (a heap number) | |
| 75 // | |
| 76 // | |
| 77 // RANGE TYPES | |
| 78 // | |
| 79 // A range type represents a continuous integer interval by its minimum and | |
| 80 // maximum value. Either value may be an infinity, in which case that infinity | |
| 81 // itself is also included in the range. A range never contains NaN or -0. | |
| 82 // | |
| 83 // If a value v happens to be an integer n, then Constant(v) is considered a | |
| 84 // subtype of Range(n, n) (and therefore also a subtype of any larger range). | |
| 85 // In order to avoid large unions, however, it is usually a good idea to use | |
| 86 // Range rather than Constant. | |
| 87 // | |
| 88 // | |
| 89 // PREDICATES | |
| 90 // | |
| 91 // There are two main functions for testing types: | |
| 92 // | |
| 93 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | |
| 94 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | |
| 95 // | |
| 96 // Typically, the former is to be used to select representations (e.g., via | |
| 97 // T->Is(SignedSmall())), and the latter to check whether a specific case needs | |
| 98 // handling (e.g., via T->Maybe(Number())). | |
| 99 // | |
| 100 // There is no functionality to discover whether a type is a leaf in the | |
| 101 // lattice. That is intentional. It should always be possible to refine the | |
| 102 // lattice (e.g., splitting up number types further) without invalidating any | |
| 103 // existing assumptions or tests. | |
| 104 // Consequently, do not normally use Equals for type tests, always use Is! | |
| 105 // | |
| 106 // The NowIs operator implements state-sensitive subtying, as described above. | |
| 107 // Any compilation decision based on such temporary properties requires runtime | |
| 108 // guarding! | |
| 109 // | |
| 110 // | |
| 111 // PROPERTIES | |
| 112 // | |
| 113 // Various formal properties hold for constructors, operators, and predicates | |
| 114 // over types. For example, constructors are injective and subtyping is a | |
| 115 // complete partial order. | |
| 116 // | |
| 117 // See test/cctest/test-types.cc for a comprehensive executable specification, | |
| 118 // especially with respect to the properties of the more exotic 'temporal' | |
| 119 // constructors and predicates (those prefixed 'Now'). | |
| 120 // | |
| 121 // | |
| 122 // IMPLEMENTATION | |
| 123 // | |
| 124 // Internally, all 'primitive' types, and their unions, are represented as | |
| 125 // bitsets. Bit 0 is reserved for tagging. Only structured types require | |
| 126 // allocation. | |
| 127 // Note that the bitset representation is closed under both Union and Intersect. | |
| 128 | |
| 129 // ----------------------------------------------------------------------------- | |
| 130 // Values for bitset types | |
| 131 | |
| 132 // clang-format off | |
| 133 | |
| 134 #define MASK_BITSET_TYPE_LIST(V) \ | |
| 135 V(Representation, 0xffc00000u) \ | |
| 136 V(Semantic, 0x003ffffeu) | |
| 137 | |
| 138 #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation) | |
| 139 #define SEMANTIC(k) ((k) & BitsetType::kSemantic) | |
| 140 | |
| 141 #define REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
| 142 V(None, 0) \ | |
| 143 V(UntaggedBit, 1u << 22 | kSemantic) \ | |
| 144 V(UntaggedIntegral8, 1u << 23 | kSemantic) \ | |
| 145 V(UntaggedIntegral16, 1u << 24 | kSemantic) \ | |
| 146 V(UntaggedIntegral32, 1u << 25 | kSemantic) \ | |
| 147 V(UntaggedFloat32, 1u << 26 | kSemantic) \ | |
| 148 V(UntaggedFloat64, 1u << 27 | kSemantic) \ | |
| 149 V(UntaggedSimd128, 1u << 28 | kSemantic) \ | |
| 150 V(UntaggedPointer, 1u << 29 | kSemantic) \ | |
| 151 V(TaggedSigned, 1u << 30 | kSemantic) \ | |
| 152 V(TaggedPointer, 1u << 31 | kSemantic) \ | |
| 153 \ | |
| 154 V(UntaggedIntegral, kUntaggedBit | kUntaggedIntegral8 | \ | |
| 155 kUntaggedIntegral16 | kUntaggedIntegral32) \ | |
| 156 V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \ | |
| 157 V(UntaggedNumber, kUntaggedIntegral | kUntaggedFloat) \ | |
| 158 V(Untagged, kUntaggedNumber | kUntaggedPointer) \ | |
| 159 V(Tagged, kTaggedSigned | kTaggedPointer) | |
| 160 | |
| 161 #define INTERNAL_BITSET_TYPE_LIST(V) \ | |
| 162 V(OtherUnsigned31, 1u << 1 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 163 V(OtherUnsigned32, 1u << 2 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 164 V(OtherSigned32, 1u << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 165 V(OtherNumber, 1u << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) | |
| 166 | |
| 167 #define SEMANTIC_BITSET_TYPE_LIST(V) \ | |
| 168 V(Negative31, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 169 V(Null, 1u << 6 | REPRESENTATION(kTaggedPointer)) \ | |
| 170 V(Undefined, 1u << 7 | REPRESENTATION(kTaggedPointer)) \ | |
| 171 V(Boolean, 1u << 8 | REPRESENTATION(kTaggedPointer)) \ | |
| 172 V(Unsigned30, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 173 V(MinusZero, 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 174 V(NaN, 1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \ | |
| 175 V(Symbol, 1u << 12 | REPRESENTATION(kTaggedPointer)) \ | |
| 176 V(InternalizedString, 1u << 13 | REPRESENTATION(kTaggedPointer)) \ | |
| 177 V(OtherString, 1u << 14 | REPRESENTATION(kTaggedPointer)) \ | |
| 178 V(Simd, 1u << 15 | REPRESENTATION(kTaggedPointer)) \ | |
| 179 V(OtherObject, 1u << 17 | REPRESENTATION(kTaggedPointer)) \ | |
| 180 V(OtherUndetectable, 1u << 16 | REPRESENTATION(kTaggedPointer)) \ | |
| 181 V(Proxy, 1u << 18 | REPRESENTATION(kTaggedPointer)) \ | |
| 182 V(Function, 1u << 19 | REPRESENTATION(kTaggedPointer)) \ | |
| 183 V(Hole, 1u << 20 | REPRESENTATION(kTaggedPointer)) \ | |
| 184 V(OtherInternal, 1u << 21 | REPRESENTATION(kTagged | kUntagged)) \ | |
| 185 \ | |
| 186 V(Signed31, kUnsigned30 | kNegative31) \ | |
| 187 V(Signed32, kSigned31 | kOtherUnsigned31 | kOtherSigned32) \ | |
| 188 V(Signed32OrMinusZero, kSigned32 | kMinusZero) \ | |
| 189 V(Signed32OrMinusZeroOrNaN, kSigned32 | kMinusZero | kNaN) \ | |
| 190 V(Negative32, kNegative31 | kOtherSigned32) \ | |
| 191 V(Unsigned31, kUnsigned30 | kOtherUnsigned31) \ | |
| 192 V(Unsigned32, kUnsigned30 | kOtherUnsigned31 | \ | |
| 193 kOtherUnsigned32) \ | |
| 194 V(Unsigned32OrMinusZero, kUnsigned32 | kMinusZero) \ | |
| 195 V(Unsigned32OrMinusZeroOrNaN, kUnsigned32 | kMinusZero | kNaN) \ | |
| 196 V(Integral32, kSigned32 | kUnsigned32) \ | |
| 197 V(PlainNumber, kIntegral32 | kOtherNumber) \ | |
| 198 V(OrderedNumber, kPlainNumber | kMinusZero) \ | |
| 199 V(MinusZeroOrNaN, kMinusZero | kNaN) \ | |
| 200 V(Number, kOrderedNumber | kNaN) \ | |
| 201 V(String, kInternalizedString | kOtherString) \ | |
| 202 V(UniqueName, kSymbol | kInternalizedString) \ | |
| 203 V(Name, kSymbol | kString) \ | |
| 204 V(BooleanOrNumber, kBoolean | kNumber) \ | |
| 205 V(BooleanOrNullOrNumber, kBooleanOrNumber | kNull) \ | |
| 206 V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \ | |
| 207 V(NullOrNumber, kNull | kNumber) \ | |
| 208 V(NullOrUndefined, kNull | kUndefined) \ | |
| 209 V(Undetectable, kNullOrUndefined | kOtherUndetectable) \ | |
| 210 V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | kHole) \ | |
| 211 V(NumberOrSimdOrString, kNumber | kSimd | kString) \ | |
| 212 V(NumberOrString, kNumber | kString) \ | |
| 213 V(NumberOrUndefined, kNumber | kUndefined) \ | |
| 214 V(PlainPrimitive, kNumberOrString | kBoolean | kNullOrUndefined) \ | |
| 215 V(Primitive, kSymbol | kSimd | kPlainPrimitive) \ | |
| 216 V(DetectableReceiver, kFunction | kOtherObject | kProxy) \ | |
| 217 V(Object, kFunction | kOtherObject | kOtherUndetectable) \ | |
| 218 V(Receiver, kObject | kProxy) \ | |
| 219 V(StringOrReceiver, kString | kReceiver) \ | |
| 220 V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \ | |
| 221 kReceiver) \ | |
| 222 V(Internal, kHole | kOtherInternal) \ | |
| 223 V(NonInternal, kPrimitive | kReceiver) \ | |
| 224 V(NonNumber, kUnique | kString | kInternal) \ | |
| 225 V(Any, 0xfffffffeu) | |
| 226 | |
| 227 // clang-format on | |
| 228 | |
| 229 /* | |
| 230 * The following diagrams show how integers (in the mathematical sense) are | |
| 231 * divided among the different atomic numerical types. | |
| 232 * | |
| 233 * ON OS32 N31 U30 OU31 OU32 ON | |
| 234 * ______[_______[_______[_______[_______[_______[_______ | |
| 235 * -2^31 -2^30 0 2^30 2^31 2^32 | |
| 236 * | |
| 237 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. | |
| 238 * | |
| 239 * Some of the atomic numerical bitsets are internal only (see | |
| 240 * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in | |
| 241 * union with certain other bitsets. For instance, OtherNumber should only | |
| 242 * occur as part of PlainNumber. | |
| 243 */ | |
| 244 | |
| 245 #define PROPER_BITSET_TYPE_LIST(V) \ | |
| 246 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
| 247 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 248 | |
| 249 #define BITSET_TYPE_LIST(V) \ | |
| 250 MASK_BITSET_TYPE_LIST(V) \ | |
| 251 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
| 252 INTERNAL_BITSET_TYPE_LIST(V) \ | |
| 253 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 254 | |
| 255 class Type; | |
| 256 | |
| 257 // ----------------------------------------------------------------------------- | |
| 258 // Bitset types (internal). | |
| 259 | |
| 260 class BitsetType { | |
| 261 public: | |
| 262 typedef uint32_t bitset; // Internal | |
| 263 | |
| 264 enum : uint32_t { | |
| 265 #define DECLARE_TYPE(type, value) k##type = (value), | |
| 266 BITSET_TYPE_LIST(DECLARE_TYPE) | |
| 267 #undef DECLARE_TYPE | |
| 268 kUnusedEOL = 0 | |
| 269 }; | |
| 270 | |
| 271 static bitset SignedSmall(); | |
| 272 static bitset UnsignedSmall(); | |
| 273 | |
| 274 bitset Bitset() { | |
| 275 return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u); | |
| 276 } | |
| 277 | |
| 278 static bool IsInhabited(bitset bits) { | |
| 279 return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone; | |
| 280 } | |
| 281 | |
| 282 static bool SemanticIsInhabited(bitset bits) { | |
| 283 return SEMANTIC(bits) != kNone; | |
| 284 } | |
| 285 | |
| 286 static bool Is(bitset bits1, bitset bits2) { | |
| 287 return (bits1 | bits2) == bits2; | |
| 288 } | |
| 289 | |
| 290 static double Min(bitset); | |
| 291 static double Max(bitset); | |
| 292 | |
| 293 static bitset Glb(Type* type); // greatest lower bound that's a bitset | |
| 294 static bitset Glb(double min, double max); | |
| 295 static bitset Lub(Type* type); // least upper bound that's a bitset | |
| 296 static bitset Lub(i::Map* map); | |
| 297 static bitset Lub(i::Object* value); | |
| 298 static bitset Lub(double value); | |
| 299 static bitset Lub(double min, double max); | |
| 300 static bitset ExpandInternals(bitset bits); | |
| 301 | |
| 302 static const char* Name(bitset); | |
| 303 static void Print(std::ostream& os, bitset); // NOLINT | |
| 304 #ifdef DEBUG | |
| 305 static void Print(bitset); | |
| 306 #endif | |
| 307 | |
| 308 static bitset NumberBits(bitset bits); | |
| 309 | |
| 310 static bool IsBitset(Type* type) { | |
| 311 return reinterpret_cast<uintptr_t>(type) & 1; | |
| 312 } | |
| 313 | |
| 314 static Type* NewForTesting(bitset bits) { return New(bits); } | |
| 315 | |
| 316 private: | |
| 317 friend class Type; | |
| 318 | |
| 319 static Type* New(bitset bits) { | |
| 320 return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u)); | |
| 321 } | |
| 322 | |
| 323 struct Boundary { | |
| 324 bitset internal; | |
| 325 bitset external; | |
| 326 double min; | |
| 327 }; | |
| 328 static const Boundary BoundariesArray[]; | |
| 329 static inline const Boundary* Boundaries(); | |
| 330 static inline size_t BoundariesSize(); | |
| 331 }; | |
| 332 | |
| 333 // ----------------------------------------------------------------------------- | |
| 334 // Superclass for non-bitset types (internal). | |
| 335 class TypeBase { | |
| 336 protected: | |
| 337 friend class Type; | |
| 338 | |
| 339 enum Kind { | |
| 340 kConstant, | |
| 341 kTuple, | |
| 342 kUnion, | |
| 343 kRange | |
| 344 }; | |
| 345 | |
| 346 Kind kind() const { return kind_; } | |
| 347 explicit TypeBase(Kind kind) : kind_(kind) {} | |
| 348 | |
| 349 static bool IsKind(Type* type, Kind kind) { | |
| 350 if (BitsetType::IsBitset(type)) return false; | |
| 351 TypeBase* base = reinterpret_cast<TypeBase*>(type); | |
| 352 return base->kind() == kind; | |
| 353 } | |
| 354 | |
| 355 // The hacky conversion to/from Type*. | |
| 356 static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); } | |
| 357 static TypeBase* FromType(Type* type) { | |
| 358 return reinterpret_cast<TypeBase*>(type); | |
| 359 } | |
| 360 | |
| 361 private: | |
| 362 Kind kind_; | |
| 363 }; | |
| 364 | |
| 365 // ----------------------------------------------------------------------------- | |
| 366 // Constant types. | |
| 367 | |
| 368 class ConstantType : public TypeBase { | |
| 369 public: | |
| 370 i::Handle<i::Object> Value() { return object_; } | |
| 371 | |
| 372 private: | |
| 373 friend class Type; | |
| 374 friend class BitsetType; | |
| 375 | |
| 376 static Type* New(i::Handle<i::Object> value, Zone* zone) { | |
| 377 BitsetType::bitset bitset = BitsetType::Lub(*value); | |
| 378 return AsType(new (zone->New(sizeof(ConstantType))) | |
| 379 ConstantType(bitset, value)); | |
| 380 } | |
| 381 | |
| 382 static ConstantType* cast(Type* type) { | |
| 383 DCHECK(IsKind(type, kConstant)); | |
| 384 return static_cast<ConstantType*>(FromType(type)); | |
| 385 } | |
| 386 | |
| 387 ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object) | |
| 388 : TypeBase(kConstant), bitset_(bitset), object_(object) {} | |
| 389 | |
| 390 BitsetType::bitset Lub() { return bitset_; } | |
| 391 | |
| 392 BitsetType::bitset bitset_; | |
| 393 Handle<i::Object> object_; | |
| 394 }; | |
| 395 // TODO(neis): Also cache value if numerical. | |
| 396 // TODO(neis): Allow restricting the representation. | |
| 397 | |
| 398 // ----------------------------------------------------------------------------- | |
| 399 // Range types. | |
| 400 | |
| 401 class RangeType : public TypeBase { | |
| 402 public: | |
| 403 struct Limits { | |
| 404 double min; | |
| 405 double max; | |
| 406 Limits(double min, double max) : min(min), max(max) {} | |
| 407 explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {} | |
| 408 bool IsEmpty(); | |
| 409 static Limits Empty() { return Limits(1, 0); } | |
| 410 static Limits Intersect(Limits lhs, Limits rhs); | |
| 411 static Limits Union(Limits lhs, Limits rhs); | |
| 412 }; | |
| 413 | |
| 414 double Min() { return limits_.min; } | |
| 415 double Max() { return limits_.max; } | |
| 416 | |
| 417 private: | |
| 418 friend class Type; | |
| 419 friend class BitsetType; | |
| 420 friend class UnionType; | |
| 421 | |
| 422 static Type* New(double min, double max, BitsetType::bitset representation, | |
| 423 Zone* zone) { | |
| 424 return New(Limits(min, max), representation, zone); | |
| 425 } | |
| 426 | |
| 427 static bool IsInteger(double x) { | |
| 428 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. | |
| 429 } | |
| 430 | |
| 431 static Type* New(Limits lim, BitsetType::bitset representation, Zone* zone) { | |
| 432 DCHECK(IsInteger(lim.min) && IsInteger(lim.max)); | |
| 433 DCHECK(lim.min <= lim.max); | |
| 434 DCHECK(REPRESENTATION(representation) == representation); | |
| 435 BitsetType::bitset bits = | |
| 436 SEMANTIC(BitsetType::Lub(lim.min, lim.max)) | representation; | |
| 437 | |
| 438 return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim)); | |
| 439 } | |
| 440 | |
| 441 static RangeType* cast(Type* type) { | |
| 442 DCHECK(IsKind(type, kRange)); | |
| 443 return static_cast<RangeType*>(FromType(type)); | |
| 444 } | |
| 445 | |
| 446 RangeType(BitsetType::bitset bitset, Limits limits) | |
| 447 : TypeBase(kRange), bitset_(bitset), limits_(limits) {} | |
| 448 | |
| 449 BitsetType::bitset Lub() { return bitset_; } | |
| 450 | |
| 451 BitsetType::bitset bitset_; | |
| 452 Limits limits_; | |
| 453 }; | |
| 454 | |
| 455 // ----------------------------------------------------------------------------- | |
| 456 // Superclass for types with variable number of type fields. | |
| 457 class StructuralType : public TypeBase { | |
| 458 public: | |
| 459 int LengthForTesting() { return Length(); } | |
| 460 | |
| 461 protected: | |
| 462 friend class Type; | |
| 463 | |
| 464 int Length() { return length_; } | |
| 465 | |
| 466 Type* Get(int i) { | |
| 467 DCHECK(0 <= i && i < this->Length()); | |
| 468 return elements_[i]; | |
| 469 } | |
| 470 | |
| 471 void Set(int i, Type* type) { | |
| 472 DCHECK(0 <= i && i < this->Length()); | |
| 473 elements_[i] = type; | |
| 474 } | |
| 475 | |
| 476 void Shrink(int length) { | |
| 477 DCHECK(2 <= length && length <= this->Length()); | |
| 478 length_ = length; | |
| 479 } | |
| 480 | |
| 481 StructuralType(Kind kind, int length, i::Zone* zone) | |
| 482 : TypeBase(kind), length_(length) { | |
| 483 elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length)); | |
| 484 } | |
| 485 | |
| 486 private: | |
| 487 int length_; | |
| 488 Type** elements_; | |
| 489 }; | |
| 490 | |
| 491 // ----------------------------------------------------------------------------- | |
| 492 // Tuple types. | |
| 493 | |
| 494 class TupleType : public StructuralType { | |
| 495 public: | |
| 496 int Arity() { return this->Length(); } | |
| 497 Type* Element(int i) { return this->Get(i); } | |
| 498 | |
| 499 void InitElement(int i, Type* type) { this->Set(i, type); } | |
| 500 | |
| 501 private: | |
| 502 friend class Type; | |
| 503 | |
| 504 TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {} | |
| 505 | |
| 506 static Type* New(int length, Zone* zone) { | |
| 507 return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone)); | |
| 508 } | |
| 509 | |
| 510 static TupleType* cast(Type* type) { | |
| 511 DCHECK(IsKind(type, kTuple)); | |
| 512 return static_cast<TupleType*>(FromType(type)); | |
| 513 } | |
| 514 }; | |
| 515 | |
| 516 // ----------------------------------------------------------------------------- | |
| 517 // Union types (internal). | |
| 518 // A union is a structured type with the following invariants: | |
| 519 // - its length is at least 2 | |
| 520 // - at most one field is a bitset, and it must go into index 0 | |
| 521 // - no field is a union | |
| 522 // - no field is a subtype of any other field | |
| 523 class UnionType : public StructuralType { | |
| 524 private: | |
| 525 friend Type; | |
| 526 friend BitsetType; | |
| 527 | |
| 528 UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {} | |
| 529 | |
| 530 static Type* New(int length, Zone* zone) { | |
| 531 return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone)); | |
| 532 } | |
| 533 | |
| 534 static UnionType* cast(Type* type) { | |
| 535 DCHECK(IsKind(type, kUnion)); | |
| 536 return static_cast<UnionType*>(FromType(type)); | |
| 537 } | |
| 538 | |
| 539 bool Wellformed(); | |
| 540 }; | |
| 541 | |
| 542 class Type { | |
| 543 public: | |
| 544 typedef BitsetType::bitset bitset; // Internal | |
| 545 | |
| 546 // Constructors. | |
| 547 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | |
| 548 static Type* type() { return BitsetType::New(BitsetType::k##type); } | |
| 549 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | |
| 550 #undef DEFINE_TYPE_CONSTRUCTOR | |
| 551 | |
| 552 static Type* SignedSmall() { | |
| 553 return BitsetType::New(BitsetType::SignedSmall()); | |
| 554 } | |
| 555 static Type* UnsignedSmall() { | |
| 556 return BitsetType::New(BitsetType::UnsignedSmall()); | |
| 557 } | |
| 558 | |
| 559 static Type* Constant(i::Handle<i::Object> value, Zone* zone) { | |
| 560 return ConstantType::New(value, zone); | |
| 561 } | |
| 562 static Type* Range(double min, double max, Zone* zone) { | |
| 563 return RangeType::New(min, max, REPRESENTATION(BitsetType::kTagged | | |
| 564 BitsetType::kUntaggedNumber), | |
| 565 zone); | |
| 566 } | |
| 567 static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) { | |
| 568 Type* tuple = TupleType::New(3, zone); | |
| 569 tuple->AsTuple()->InitElement(0, first); | |
| 570 tuple->AsTuple()->InitElement(1, second); | |
| 571 tuple->AsTuple()->InitElement(2, third); | |
| 572 return tuple; | |
| 573 } | |
| 574 | |
| 575 static Type* Union(Type* type1, Type* type2, Zone* zone); | |
| 576 static Type* Intersect(Type* type1, Type* type2, Zone* zone); | |
| 577 | |
| 578 static Type* Of(double value, Zone* zone) { | |
| 579 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value))); | |
| 580 } | |
| 581 static Type* Of(i::Object* value, Zone* zone) { | |
| 582 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value))); | |
| 583 } | |
| 584 static Type* Of(i::Handle<i::Object> value, Zone* zone) { | |
| 585 return Of(*value, zone); | |
| 586 } | |
| 587 | |
| 588 static Type* For(i::Map* map) { | |
| 589 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(map))); | |
| 590 } | |
| 591 static Type* For(i::Handle<i::Map> map) { return For(*map); } | |
| 592 | |
| 593 // Extraction of components. | |
| 594 static Type* Representation(Type* t, Zone* zone); | |
| 595 static Type* Semantic(Type* t, Zone* zone); | |
| 596 | |
| 597 // Predicates. | |
| 598 bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); } | |
| 599 | |
| 600 bool Is(Type* that) { return this == that || this->SlowIs(that); } | |
| 601 bool Maybe(Type* that); | |
| 602 bool Equals(Type* that) { return this->Is(that) && that->Is(this); } | |
| 603 | |
| 604 // Equivalent to Constant(val)->Is(this), but avoiding allocation. | |
| 605 bool Contains(i::Object* val); | |
| 606 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | |
| 607 | |
| 608 // Inspection. | |
| 609 bool IsRange() { return IsKind(TypeBase::kRange); } | |
| 610 bool IsConstant() { return IsKind(TypeBase::kConstant); } | |
| 611 bool IsTuple() { return IsKind(TypeBase::kTuple); } | |
| 612 | |
| 613 ConstantType* AsConstant() { return ConstantType::cast(this); } | |
| 614 RangeType* AsRange() { return RangeType::cast(this); } | |
| 615 TupleType* AsTuple() { return TupleType::cast(this); } | |
| 616 | |
| 617 // Minimum and maximum of a numeric type. | |
| 618 // These functions do not distinguish between -0 and +0. If the type equals | |
| 619 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these | |
| 620 // functions on subtypes of Number. | |
| 621 double Min(); | |
| 622 double Max(); | |
| 623 | |
| 624 // Extracts a range from the type: if the type is a range or a union | |
| 625 // containing a range, that range is returned; otherwise, NULL is returned. | |
| 626 Type* GetRange(); | |
| 627 | |
| 628 static bool IsInteger(i::Object* x); | |
| 629 static bool IsInteger(double x) { | |
| 630 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. | |
| 631 } | |
| 632 | |
| 633 int NumConstants(); | |
| 634 | |
| 635 template <class T> | |
| 636 class Iterator { | |
| 637 public: | |
| 638 bool Done() const { return index_ < 0; } | |
| 639 i::Handle<T> Current(); | |
| 640 void Advance(); | |
| 641 | |
| 642 private: | |
| 643 friend class Type; | |
| 644 | |
| 645 Iterator() : index_(-1) {} | |
| 646 explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); } | |
| 647 | |
| 648 inline bool matches(Type* type); | |
| 649 inline Type* get_type(); | |
| 650 | |
| 651 Type* type_; | |
| 652 int index_; | |
| 653 }; | |
| 654 | |
| 655 Iterator<i::Object> Constants() { | |
| 656 if (this->IsBitset()) return Iterator<i::Object>(); | |
| 657 return Iterator<i::Object>(this); | |
| 658 } | |
| 659 | |
| 660 // Printing. | |
| 661 | |
| 662 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; | |
| 663 | |
| 664 void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT | |
| 665 | |
| 666 #ifdef DEBUG | |
| 667 void Print(); | |
| 668 #endif | |
| 669 | |
| 670 // Helpers for testing. | |
| 671 bool IsBitsetForTesting() { return IsBitset(); } | |
| 672 bool IsUnionForTesting() { return IsUnion(); } | |
| 673 bitset AsBitsetForTesting() { return AsBitset(); } | |
| 674 UnionType* AsUnionForTesting() { return AsUnion(); } | |
| 675 | |
| 676 private: | |
| 677 // Friends. | |
| 678 template <class> | |
| 679 friend class Iterator; | |
| 680 friend BitsetType; | |
| 681 friend UnionType; | |
| 682 | |
| 683 // Internal inspection. | |
| 684 bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); } | |
| 685 | |
| 686 bool IsNone() { return this == None(); } | |
| 687 bool IsAny() { return this == Any(); } | |
| 688 bool IsBitset() { return BitsetType::IsBitset(this); } | |
| 689 bool IsUnion() { return IsKind(TypeBase::kUnion); } | |
| 690 | |
| 691 bitset AsBitset() { | |
| 692 DCHECK(this->IsBitset()); | |
| 693 return reinterpret_cast<BitsetType*>(this)->Bitset(); | |
| 694 } | |
| 695 UnionType* AsUnion() { return UnionType::cast(this); } | |
| 696 | |
| 697 bitset Representation(); | |
| 698 | |
| 699 // Auxiliary functions. | |
| 700 bool SemanticMaybe(Type* that); | |
| 701 | |
| 702 bitset BitsetGlb() { return BitsetType::Glb(this); } | |
| 703 bitset BitsetLub() { return BitsetType::Lub(this); } | |
| 704 | |
| 705 bool SlowIs(Type* that); | |
| 706 bool SemanticIs(Type* that); | |
| 707 | |
| 708 static bool Overlap(RangeType* lhs, RangeType* rhs); | |
| 709 static bool Contains(RangeType* lhs, RangeType* rhs); | |
| 710 static bool Contains(RangeType* range, ConstantType* constant); | |
| 711 static bool Contains(RangeType* range, i::Object* val); | |
| 712 | |
| 713 static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone); | |
| 714 | |
| 715 static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits, | |
| 716 Zone* zone); | |
| 717 static RangeType::Limits ToLimits(bitset bits, Zone* zone); | |
| 718 | |
| 719 bool SimplyEquals(Type* that); | |
| 720 | |
| 721 static int AddToUnion(Type* type, UnionType* result, int size, Zone* zone); | |
| 722 static int IntersectAux(Type* type, Type* other, UnionType* result, int size, | |
| 723 RangeType::Limits* limits, Zone* zone); | |
| 724 static Type* NormalizeUnion(Type* unioned, int size, Zone* zone); | |
| 725 static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone); | |
| 726 }; | |
| 727 | |
| 728 // ----------------------------------------------------------------------------- | |
| 729 // Type bounds. A simple struct to represent a pair of lower/upper types. | |
| 730 | |
| 731 struct Bounds { | |
| 732 Type* lower; | |
| 733 Type* upper; | |
| 734 | |
| 735 Bounds() | |
| 736 : // Make sure accessing uninitialized bounds crashes big-time. | |
| 737 lower(nullptr), | |
| 738 upper(nullptr) {} | |
| 739 explicit Bounds(Type* t) : lower(t), upper(t) {} | |
| 740 Bounds(Type* l, Type* u) : lower(l), upper(u) { DCHECK(lower->Is(upper)); } | |
| 741 | |
| 742 // Unrestricted bounds. | |
| 743 static Bounds Unbounded() { return Bounds(Type::None(), Type::Any()); } | |
| 744 | |
| 745 // Meet: both b1 and b2 are known to hold. | |
| 746 static Bounds Both(Bounds b1, Bounds b2, Zone* zone) { | |
| 747 Type* lower = Type::Union(b1.lower, b2.lower, zone); | |
| 748 Type* upper = Type::Intersect(b1.upper, b2.upper, zone); | |
| 749 // Lower bounds are considered approximate, correct as necessary. | |
| 750 if (!lower->Is(upper)) lower = upper; | |
| 751 return Bounds(lower, upper); | |
| 752 } | |
| 753 | |
| 754 // Join: either b1 or b2 is known to hold. | |
| 755 static Bounds Either(Bounds b1, Bounds b2, Zone* zone) { | |
| 756 Type* lower = Type::Intersect(b1.lower, b2.lower, zone); | |
| 757 Type* upper = Type::Union(b1.upper, b2.upper, zone); | |
| 758 return Bounds(lower, upper); | |
| 759 } | |
| 760 | |
| 761 static Bounds NarrowLower(Bounds b, Type* t, Zone* zone) { | |
| 762 Type* lower = Type::Union(b.lower, t, zone); | |
| 763 // Lower bounds are considered approximate, correct as necessary. | |
| 764 if (!lower->Is(b.upper)) lower = b.upper; | |
| 765 return Bounds(lower, b.upper); | |
| 766 } | |
| 767 static Bounds NarrowUpper(Bounds b, Type* t, Zone* zone) { | |
| 768 Type* lower = b.lower; | |
| 769 Type* upper = Type::Intersect(b.upper, t, zone); | |
| 770 // Lower bounds are considered approximate, correct as necessary. | |
| 771 if (!lower->Is(upper)) lower = upper; | |
| 772 return Bounds(lower, upper); | |
| 773 } | |
| 774 | |
| 775 bool Narrows(Bounds that) { | |
| 776 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | |
| 777 } | |
| 778 }; | |
| 779 } // namespace internal | |
| 780 } // namespace v8 | |
| 781 | |
| 782 #endif // V8_TYPES_H_ | |
| OLD | NEW |