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_COMPILER_TYPES_H_ 6 #define V8_COMPILER_TYPES_H_ 7 8 #include "src/base/compiler-specific.h" 9 #include "src/compiler/js-heap-broker.h" 10 #include "src/conversions.h" 11 #include "src/globals.h" 12 #include "src/handles.h" 13 #include "src/objects.h" 14 #include "src/ostreams.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 // SUMMARY 21 // 22 // A simple type system for compiler-internal use. It is based entirely on 23 // union types, and all subtyping hence amounts to set inclusion. Besides the 24 // obvious primitive types and some predefined unions, the type language also 25 // can express class types (a.k.a. specific maps) and singleton types (i.e., 26 // concrete constants). 27 // 28 // The following equations and inequations hold: 29 // 30 // None <= T 31 // T <= Any 32 // 33 // Number = Signed32 \/ Unsigned32 \/ Double 34 // Smi <= Signed32 35 // Name = String \/ Symbol 36 // UniqueName = InternalizedString \/ Symbol 37 // InternalizedString < String 38 // 39 // Receiver = Object \/ Proxy 40 // OtherUndetectable < Object 41 // DetectableReceiver = Receiver - OtherUndetectable 42 // 43 // Constant(x) < T iff instance_type(map(x)) < T 44 // 45 // 46 // RANGE TYPES 47 // 48 // A range type represents a continuous integer interval by its minimum and 49 // maximum value. Either value may be an infinity, in which case that infinity 50 // itself is also included in the range. A range never contains NaN or -0. 51 // 52 // If a value v happens to be an integer n, then Constant(v) is considered a 53 // subtype of Range(n, n) (and therefore also a subtype of any larger range). 54 // In order to avoid large unions, however, it is usually a good idea to use 55 // Range rather than Constant. 56 // 57 // 58 // PREDICATES 59 // 60 // There are two main functions for testing types: 61 // 62 // T1.Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) 63 // T1.Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) 64 // 65 // Typically, the former is to be used to select representations (e.g., via 66 // T.Is(SignedSmall())), and the latter to check whether a specific case needs 67 // handling (e.g., via T.Maybe(Number())). 68 // 69 // There is no functionality to discover whether a type is a leaf in the 70 // lattice. That is intentional. It should always be possible to refine the 71 // lattice (e.g., splitting up number types further) without invalidating any 72 // existing assumptions or tests. 73 // Consequently, do not normally use Equals for type tests, always use Is! 74 // 75 // The NowIs operator implements state-sensitive subtying, as described above. 76 // Any compilation decision based on such temporary properties requires runtime 77 // guarding! 78 // 79 // 80 // PROPERTIES 81 // 82 // Various formal properties hold for constructors, operators, and predicates 83 // over types. For example, constructors are injective and subtyping is a 84 // complete partial order. 85 // 86 // See test/cctest/test-types.cc for a comprehensive executable specification, 87 // especially with respect to the properties of the more exotic 'temporal' 88 // constructors and predicates (those prefixed 'Now'). 89 // 90 // 91 // IMPLEMENTATION 92 // 93 // Internally, all 'primitive' types, and their unions, are represented as 94 // bitsets. Bit 0 is reserved for tagging. Only structured types require 95 // allocation. 96 97 // ----------------------------------------------------------------------------- 98 // Values for bitset types 99 100 // clang-format off 101 102 #define INTERNAL_BITSET_TYPE_LIST(V) \ 103 V(OtherUnsigned31, 1u << 1) \ 104 V(OtherUnsigned32, 1u << 2) \ 105 V(OtherSigned32, 1u << 3) \ 106 V(OtherNumber, 1u << 4) \ 107 V(OtherString, 1u << 5) \ 108 109 #define PROPER_BITSET_TYPE_LIST(V) \ 110 V(None, 0u) \ 111 V(Negative31, 1u << 6) \ 112 V(Null, 1u << 7) \ 113 V(Undefined, 1u << 8) \ 114 V(Boolean, 1u << 9) \ 115 V(Unsigned30, 1u << 10) \ 116 V(MinusZero, 1u << 11) \ 117 V(NaN, 1u << 12) \ 118 V(Symbol, 1u << 13) \ 119 V(InternalizedString, 1u << 14) \ 120 V(OtherCallable, 1u << 16) \ 121 V(OtherObject, 1u << 17) \ 122 V(OtherUndetectable, 1u << 18) \ 123 V(CallableProxy, 1u << 19) \ 124 V(OtherProxy, 1u << 20) \ 125 V(Function, 1u << 21) \ 126 V(BoundFunction, 1u << 22) \ 127 V(Hole, 1u << 23) \ 128 V(OtherInternal, 1u << 24) \ 129 V(ExternalPointer, 1u << 25) \ 130 V(Array, 1u << 26) \ 131 V(BigInt, 1u << 27) \ 132 \ 133 V(Signed31, kUnsigned30 | kNegative31) \ 134 V(Signed32, kSigned31 | kOtherUnsigned31 | \ 135 kOtherSigned32) \ 136 V(Signed32OrMinusZero, kSigned32 | kMinusZero) \ 137 V(Signed32OrMinusZeroOrNaN, kSigned32 | kMinusZero | kNaN) \ 138 V(Negative32, kNegative31 | kOtherSigned32) \ 139 V(Unsigned31, kUnsigned30 | kOtherUnsigned31) \ 140 V(Unsigned32, kUnsigned30 | kOtherUnsigned31 | \ 141 kOtherUnsigned32) \ 142 V(Unsigned32OrMinusZero, kUnsigned32 | kMinusZero) \ 143 V(Unsigned32OrMinusZeroOrNaN, kUnsigned32 | kMinusZero | kNaN) \ 144 V(Integral32, kSigned32 | kUnsigned32) \ 145 V(Integral32OrMinusZero, kIntegral32 | kMinusZero) \ 146 V(Integral32OrMinusZeroOrNaN, kIntegral32OrMinusZero | kNaN) \ 147 V(PlainNumber, kIntegral32 | kOtherNumber) \ 148 V(OrderedNumber, kPlainNumber | kMinusZero) \ 149 V(MinusZeroOrNaN, kMinusZero | kNaN) \ 150 V(Number, kOrderedNumber | kNaN) \ 151 V(Numeric, kNumber | kBigInt) \ 152 V(String, kInternalizedString | kOtherString) \ 153 V(UniqueName, kSymbol | kInternalizedString) \ 154 V(Name, kSymbol | kString) \ 155 V(InternalizedStringOrNull, kInternalizedString | kNull) \ 156 V(BooleanOrNumber, kBoolean | kNumber) \ 157 V(BooleanOrNullOrNumber, kBooleanOrNumber | kNull) \ 158 V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \ 159 V(Oddball, kBooleanOrNullOrUndefined | kHole) \ 160 V(NullOrNumber, kNull | kNumber) \ 161 V(NullOrUndefined, kNull | kUndefined) \ 162 V(Undetectable, kNullOrUndefined | kOtherUndetectable) \ 163 V(NumberOrHole, kNumber | kHole) \ 164 V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | \ 165 kHole) \ 166 V(NumericOrString, kNumeric | kString) \ 167 V(NumberOrUndefined, kNumber | kUndefined) \ 168 V(NumberOrUndefinedOrNullOrBoolean, \ 169 kNumber | kNullOrUndefined | kBoolean) \ 170 V(PlainPrimitive, kNumber | kString | kBoolean | \ 171 kNullOrUndefined) \ 172 V(Primitive, kSymbol | kBigInt | kPlainPrimitive) \ 173 V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \ 174 V(Proxy, kCallableProxy | kOtherProxy) \ 175 V(ArrayOrOtherObject, kArray | kOtherObject) \ 176 V(ArrayOrProxy, kArray | kProxy) \ 177 V(DetectableCallable, kFunction | kBoundFunction | \ 178 kOtherCallable | kCallableProxy) \ 179 V(Callable, kDetectableCallable | kOtherUndetectable) \ 180 V(NonCallable, kArray | kOtherObject | kOtherProxy) \ 181 V(NonCallableOrNull, kNonCallable | kNull) \ 182 V(DetectableObject, kArray | kFunction | kBoundFunction | \ 183 kOtherCallable | kOtherObject) \ 184 V(DetectableReceiver, kDetectableObject | kProxy) \ 185 V(DetectableReceiverOrNull, kDetectableReceiver | kNull) \ 186 V(Object, kDetectableObject | kOtherUndetectable) \ 187 V(Receiver, kObject | kProxy) \ 188 V(ReceiverOrUndefined, kReceiver | kUndefined) \ 189 V(ReceiverOrNullOrUndefined, kReceiver | kNull | kUndefined) \ 190 V(SymbolOrReceiver, kSymbol | kReceiver) \ 191 V(StringOrReceiver, kString | kReceiver) \ 192 V(Unique, kBoolean | kUniqueName | kNull | \ 193 kUndefined | kReceiver) \ 194 V(Internal, kHole | kExternalPointer | kOtherInternal) \ 195 V(NonInternal, kPrimitive | kReceiver) \ 196 V(NonNumber, kUnique | kString | kInternal) \ 197 V(Any, 0xfffffffeu) 198 199 // clang-format on 200 201 /* 202 * The following diagrams show how integers (in the mathematical sense) are 203 * divided among the different atomic numerical types. 204 * 205 * ON OS32 N31 U30 OU31 OU32 ON 206 * ______[_______[_______[_______[_______[_______[_______ 207 * -2^31 -2^30 0 2^30 2^31 2^32 208 * 209 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. 210 * 211 * Some of the atomic numerical bitsets are internal only (see 212 * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in 213 * union with certain other bitsets. For instance, OtherNumber should only 214 * occur as part of PlainNumber. 215 */ 216 217 #define BITSET_TYPE_LIST(V) \ 218 INTERNAL_BITSET_TYPE_LIST(V) \ 219 PROPER_BITSET_TYPE_LIST(V) 220 221 class HeapConstantType; 222 class OtherNumberConstantType; 223 class TupleType; 224 class Type; 225 class UnionType; 226 227 // ----------------------------------------------------------------------------- 228 // Bitset types (internal). 229 230 class V8_EXPORT_PRIVATE BitsetType { 231 public: 232 typedef uint32_t bitset; // Internal 233 234 enum : uint32_t { 235 #define DECLARE_TYPE(type, value) k##type = (value), 236 BITSET_TYPE_LIST(DECLARE_TYPE) 237 #undef DECLARE_TYPE 238 kUnusedEOL = 0 239 }; 240 241 static bitset SignedSmall(); 242 static bitset UnsignedSmall(); 243 244 static bool IsNone(bitset bits) { return bits == kNone; } 245 246 static bool Is(bitset bits1, bitset bits2) { 247 return (bits1 | bits2) == bits2; 248 } 249 250 static double Min(bitset); 251 static double Max(bitset); 252 253 static bitset Glb(double min, double max); 254 static bitset Lub(HeapObjectType const& type); 255 static bitset Lub(double value); 256 static bitset Lub(double min, double max); 257 static bitset ExpandInternals(bitset bits); 258 259 static const char* Name(bitset); 260 static void Print(std::ostream& os, bitset); // NOLINT 261 #ifdef DEBUG 262 static void Print(bitset); 263 #endif 264 265 static bitset NumberBits(bitset bits); 266 267 private: 268 struct Boundary { 269 bitset internal; 270 bitset external; 271 double min; 272 }; 273 static const Boundary BoundariesArray[]; 274 static inline const Boundary* Boundaries(); 275 static inline size_t BoundariesSize(); 276 }; 277 278 // ----------------------------------------------------------------------------- 279 // Superclass for non-bitset types (internal). 280 class TypeBase { 281 protected: 282 friend class Type; 283 284 enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange }; 285 286 Kind kind() const { return kind_; } 287 explicit TypeBase(Kind kind) : kind_(kind) {} 288 289 static bool IsKind(Type type, Kind kind); 290 291 private: 292 Kind kind_; 293 }; 294 295 // ----------------------------------------------------------------------------- 296 // Range types. 297 298 class RangeType : public TypeBase { 299 public: 300 struct Limits { 301 double min; 302 double max; 303 Limits(double min, double max) : min(min), max(max) {} 304 explicit Limits(const RangeType* range) 305 : min(range->Min()), max(range->Max()) {} 306 bool IsEmpty(); 307 static Limits Empty() { return Limits(1, 0); } 308 static Limits Intersect(Limits lhs, Limits rhs); 309 static Limits Union(Limits lhs, Limits rhs); 310 }; 311 312 double Min() const { return limits_.min; } 313 double Max() const { return limits_.max; } 314 315 static bool IsInteger(double x) { 316 return nearbyint(x) == x && !IsMinusZero(x); // Allows for infinities. 317 } 318 319 private: 320 friend class Type; 321 friend class BitsetType; 322 friend class UnionType; 323 324 static RangeType* New(double min, double max, Zone* zone) { 325 return New(Limits(min, max), zone); 326 } 327 328 static RangeType* New(Limits lim, Zone* zone) { 329 DCHECK(IsInteger(lim.min) && IsInteger(lim.max)); 330 DCHECK(lim.min <= lim.max); 331 BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max); 332 333 return new (zone->New(sizeof(RangeType))) RangeType(bits, lim); 334 } 335 336 RangeType(BitsetType::bitset bitset, Limits limits) 337 : TypeBase(kRange), bitset_(bitset), limits_(limits) {} 338 339 BitsetType::bitset Lub() const { return bitset_; } 340 341 BitsetType::bitset bitset_; 342 Limits limits_; 343 }; 344 345 // ----------------------------------------------------------------------------- 346 // The actual type. 347 348 class V8_EXPORT_PRIVATE Type { 349 public: 350 typedef BitsetType::bitset bitset; // Internal 351 352 // Constructors. 353 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ 354 static Type type() { return NewBitset(BitsetType::k##type); } 355 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) 356 #undef DEFINE_TYPE_CONSTRUCTOR 357 358 Type() : payload_(0) {} 359 360 static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); } 361 static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); } 362 363 static Type OtherNumberConstant(double value, Zone* zone); 364 static Type HeapConstant(JSHeapBroker* js_heap_broker, 365 Handle<i::Object> value, Zone* zone); 366 static Type HeapConstant(const HeapObjectRef& value, Zone* zone); 367 static Type Range(double min, double max, Zone* zone); 368 static Type Range(RangeType::Limits lims, Zone* zone); 369 static Type Tuple(Type first, Type second, Type third, Zone* zone); 370 static Type Union(int length, Zone* zone); 371 372 // NewConstant is a factory that returns Constant, Range or Number. 373 static Type NewConstant(JSHeapBroker* js_heap_broker, Handle<i::Object> value, 374 Zone* zone); 375 static Type NewConstant(double value, Zone* zone); 376 377 static Type Union(Type type1, Type type2, Zone* zone); 378 static Type Intersect(Type type1, Type type2, Zone* zone); 379 380 static Type For(JSHeapBroker* js_heap_broker, Handle<i::Map> map) { 381 HeapObjectType type = js_heap_broker->HeapObjectTypeFromMap(map); 382 return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type))); 383 } 384 385 // Predicates. 386 bool IsNone() const { return payload_ == None().payload_; } 387 bool IsInvalid() const { return payload_ == 0u; } 388 389 bool Is(Type that) const { 390 return payload_ == that.payload_ || this->SlowIs(that); 391 } 392 bool Maybe(Type that) const; 393 bool Equals(Type that) const { return this->Is(that) && that.Is(*this); } 394 395 // Inspection. 396 bool IsBitset() const { return payload_ & 1; } 397 bool IsRange() const { return IsKind(TypeBase::kRange); } 398 bool IsHeapConstant() const { return IsKind(TypeBase::kHeapConstant); } 399 bool IsOtherNumberConstant() const { 400 return IsKind(TypeBase::kOtherNumberConstant); 401 } 402 bool IsTuple() const { return IsKind(TypeBase::kTuple); } 403 404 const HeapConstantType* AsHeapConstant() const; 405 const OtherNumberConstantType* AsOtherNumberConstant() const; 406 const RangeType* AsRange() const; 407 const TupleType* AsTuple() const; 408 409 // Minimum and maximum of a numeric type. 410 // These functions do not distinguish between -0 and +0. NaN is ignored. 411 // Only call them on subtypes of Number whose intersection with OrderedNumber 412 // is not empty. 413 double Min() const; 414 double Max() const; 415 416 // Extracts a range from the type: if the type is a range or a union 417 // containing a range, that range is returned; otherwise, nullptr is returned. 418 Type GetRange() const; 419 420 int NumConstants() const; 421 422 static Type Invalid() { return Type(); } 423 424 bool operator==(Type other) const { return payload_ == other.payload_; } 425 bool operator!=(Type other) const { return payload_ != other.payload_; } 426 427 // Printing. 428 429 void PrintTo(std::ostream& os) const; 430 431 #ifdef DEBUG 432 void Print() const; 433 #endif 434 435 // Helpers for testing. 436 bool IsUnionForTesting() { return IsUnion(); } 437 bitset AsBitsetForTesting() { return AsBitset(); } 438 const UnionType* AsUnionForTesting() { return AsUnion(); } 439 Type BitsetGlbForTesting() { return NewBitset(BitsetGlb()); } 440 Type BitsetLubForTesting() { return NewBitset(BitsetLub()); } 441 442 private: 443 // Friends. 444 template <class> 445 friend class Iterator; 446 friend BitsetType; 447 friend UnionType; 448 friend size_t hash_value(Type type); 449 450 Type(bitset bits) : payload_(bits | 1u) {} 451 Type(TypeBase* type_base) 452 : payload_(reinterpret_cast<uintptr_t>(type_base)) {} 453 454 // Internal inspection. 455 bool IsKind(TypeBase::Kind kind) const { 456 if (IsBitset()) return false; 457 const TypeBase* base = ToTypeBase(); 458 return base->kind() == kind; 459 } 460 461 const TypeBase* ToTypeBase() const { 462 return reinterpret_cast<TypeBase*>(payload_); 463 } 464 static Type FromTypeBase(TypeBase* type) { return Type(type); } 465 466 bool IsAny() const { return payload_ == Any().payload_; } 467 bool IsUnion() const { return IsKind(TypeBase::kUnion); } 468 469 bitset AsBitset() const { 470 DCHECK(IsBitset()); 471 return static_cast<bitset>(payload_) ^ 1u; 472 } 473 474 const UnionType* AsUnion() const; 475 476 bitset BitsetGlb() const; // greatest lower bound that's a bitset 477 bitset BitsetLub() const; // least upper bound that's a bitset 478 479 bool SlowIs(Type that) const; 480 481 static Type NewBitset(bitset bits) { return Type(bits); } 482 483 static bool Overlap(const RangeType* lhs, const RangeType* rhs); 484 static bool Contains(const RangeType* lhs, const RangeType* rhs); 485 486 static int UpdateRange(Type type, UnionType* result, int size, Zone* zone); 487 488 static RangeType::Limits IntersectRangeAndBitset(Type range, Type bits, 489 Zone* zone); 490 static RangeType::Limits ToLimits(bitset bits, Zone* zone); 491 492 bool SimplyEquals(Type that) const; 493 494 static int AddToUnion(Type type, UnionType* result, int size, Zone* zone); 495 static int IntersectAux(Type type, Type other, UnionType* result, int size, 496 RangeType::Limits* limits, Zone* zone); 497 static Type NormalizeUnion(UnionType* unioned, int size, Zone* zone); 498 static Type NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone); 499 500 // If LSB is set, the payload is a bitset; if LSB is clear, the payload is 501 // a pointer to a subtype of the TypeBase class. 502 uintptr_t payload_; 503 }; 504 505 inline size_t hash_value(Type type) { return type.payload_; } 506 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type); 507 508 // ----------------------------------------------------------------------------- 509 // Constant types. 510 511 class OtherNumberConstantType : public TypeBase { 512 public: 513 double Value() const { return value_; } 514 515 static bool IsOtherNumberConstant(double value); 516 517 private: 518 friend class Type; 519 friend class BitsetType; 520 521 static OtherNumberConstantType* New(double value, Zone* zone) { 522 return new (zone->New(sizeof(OtherNumberConstantType))) 523 OtherNumberConstantType(value); // NOLINT 524 } 525 526 explicit OtherNumberConstantType(double value) 527 : TypeBase(kOtherNumberConstant), value_(value) { 528 CHECK(IsOtherNumberConstant(value)); 529 } 530 531 BitsetType::bitset Lub() const { return BitsetType::kOtherNumber; } 532 533 double value_; 534 }; 535 536 class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) { 537 public: 538 Handle<HeapObject> Value() const; 539 const HeapObjectRef& Ref() const { return heap_ref_; } 540 541 private: 542 friend class Type; 543 friend class BitsetType; 544 545 static HeapConstantType* New(const HeapObjectRef& heap_ref, Zone* zone) { 546 DCHECK(!heap_ref.IsHeapNumber()); 547 DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString()); 548 BitsetType::bitset bitset = BitsetType::Lub(heap_ref.type()); 549 return new (zone->New(sizeof(HeapConstantType))) 550 HeapConstantType(bitset, heap_ref); 551 } 552 553 HeapConstantType(BitsetType::bitset bitset, const HeapObjectRef& heap_ref); 554 555 BitsetType::bitset Lub() const { return bitset_; } 556 557 BitsetType::bitset bitset_; 558 HeapObjectRef heap_ref_; 559 }; 560 561 // ----------------------------------------------------------------------------- 562 // Superclass for types with variable number of type fields. 563 class StructuralType : public TypeBase { 564 public: 565 int LengthForTesting() const { return Length(); } 566 567 protected: 568 friend class Type; 569 570 int Length() const { return length_; } 571 572 Type Get(int i) const { 573 DCHECK(0 <= i && i < this->Length()); 574 return elements_[i]; 575 } 576 577 void Set(int i, Type type) { 578 DCHECK(0 <= i && i < this->Length()); 579 elements_[i] = type; 580 } 581 582 void Shrink(int length) { 583 DCHECK(2 <= length && length <= this->Length()); 584 length_ = length; 585 } 586 587 StructuralType(Kind kind, int length, Zone* zone) 588 : TypeBase(kind), length_(length) { 589 elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length)); 590 } 591 592 private: 593 int length_; 594 Type* elements_; 595 }; 596 597 // ----------------------------------------------------------------------------- 598 // Tuple types. 599 600 class TupleType : public StructuralType { 601 public: 602 int Arity() const { return this->Length(); } 603 Type Element(int i) const { return this->Get(i); } 604 605 void InitElement(int i, Type type) { this->Set(i, type); } 606 607 private: 608 friend class Type; 609 610 TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {} 611 612 static TupleType* New(int length, Zone* zone) { 613 return new (zone->New(sizeof(TupleType))) TupleType(length, zone); 614 } 615 }; 616 617 // ----------------------------------------------------------------------------- 618 // Union types (internal). 619 // A union is a structured type with the following invariants: 620 // - its length is at least 2 621 // - at most one field is a bitset, and it must go into index 0 622 // - no field is a union 623 // - no field is a subtype of any other field 624 class UnionType : public StructuralType { 625 private: 626 friend Type; 627 friend BitsetType; 628 629 UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {} 630 631 static UnionType* New(int length, Zone* zone) { 632 return new (zone->New(sizeof(UnionType))) UnionType(length, zone); 633 } 634 635 bool Wellformed() const; 636 }; 637 638 } // namespace compiler 639 } // namespace internal 640 } // namespace v8 641 642 #endif // V8_COMPILER_TYPES_H_ 643