2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_JIT_TYPE_H_
18 #define incl_HPHP_JIT_TYPE_H_
20 #include "hphp/runtime/base/repo-auth-type.h"
21 #include "hphp/runtime/base/repo-auth-type-array.h"
22 #include "hphp/runtime/base/string-data.h"
23 #include "hphp/runtime/base/type-array.h"
25 #include "hphp/runtime/vm/class.h"
26 #include "hphp/runtime/vm/jit/types.h"
28 #include "hphp/util/data-block.h"
30 #include "folly/Optional.h"
44 namespace constToBits_detail
{
46 struct needs_promotion
47 : std::integral_constant
<
49 std::is_integral
<T
>::value
||
50 std::is_same
<T
,bool>::value
||
51 std::is_enum
<T
>::value
56 typename
std::enable_if
<needs_promotion
<T
>::value
,uint64_t>::type
57 promoteIfNeeded(T t
) { return static_cast<uint64_t>(t
); }
60 typename
std::enable_if
<!needs_promotion
<T
>::value
,T
>::type
61 promoteIfNeeded(T t
) { return t
; }
64 #define IRT_BOXES(name, bits) \
66 IRT(Boxed##name, (bits) << kBoxShift) \
67 IRT(PtrTo##name, (bits) << kPtrShift) \
68 IRT(PtrToBoxed##name, (bits) << kPtrBoxShift)
70 #define IRT_BOXES_WITH_ANY(name, bits) \
71 IRT_BOXES(name, bits) \
72 IRT(Any##name, k##name | kBoxed##name | kPtrTo##name | \
77 c(Uninit, 1ULL << 0) \
78 c(InitNull, 1ULL << 1) \
82 c(StaticStr, 1ULL << 5) \
83 c(CountedStr, 1ULL << 6) \
84 c(StaticArr, 1ULL << 7) \
85 c(CountedArr, 1ULL << 8) \
92 // This list should be in non-decreasing order of specificity
93 #define IRT_PHP_UNIONS(c) \
94 c(Null, kUninit|kInitNull) \
95 c(Str, kStaticStr|kCountedStr) \
96 c(Arr, kStaticArr|kCountedArr) \
97 c(NullableObj, kObj|kInitNull|kUninit) \
98 c(UncountedInit, kInitNull|kBool|kInt|kDbl|kStaticStr|kStaticArr) \
99 c(Uncounted, kUncountedInit|kUninit) \
100 c(InitCell, kUncountedInit|kStr|kArr|kObj|kRes) \
101 c(Cell, kInitCell|kUninit)
103 #define IRT_RUNTIME \
104 IRT(Cls, 1ULL << 44) \
105 IRT(Func, 1ULL << 45) \
106 IRT(VarEnv, 1ULL << 46) \
107 IRT(NamedEntity, 1ULL << 47) \
108 IRT(Cctx, 1ULL << 48) /* Class* with the lowest bit set, */ \
109 /* as stored in ActRec.m_cls field */ \
110 IRT(RetAddr, 1ULL << 49) /* Return address */ \
111 IRT(StkPtr, 1ULL << 50) /* stack pointer */ \
112 IRT(FramePtr, 1ULL << 51) /* frame pointer */ \
113 IRT(TCA, 1ULL << 52) \
114 IRT(ActRec, 1ULL << 53) \
115 IRT(RDSHandle, 1ULL << 54) /* RDS::Handle */ \
116 IRT(Nullptr, 1ULL << 55)
118 // The definitions for these are in ir.cpp
120 IRT(Ctx, kObj|kCctx) \
122 // Gen, Counted, PtrToGen, and PtrToCounted are here instead of
123 // IRT_PHP_UNIONS because boxing them (e.g., BoxedGen, PtrToBoxedGen)
124 // would yield nonsense types.
125 #define IRT_SPECIAL \
127 IRT(Top, 0xffffffffffffffffULL) \
128 IRT(Counted, kCountedStr|kCountedArr|kObj|kRes|kBoxedCell) \
129 IRT(PtrToCounted, kCounted << kPtrShift) \
130 IRT(Gen, kCell|kBoxedCell) \
131 IRT(StackElem, kGen|kCls) \
132 IRT(Init, kGen & ~kUninit) \
133 IRT(PtrToGen, kGen << kPtrShift) \
134 IRT(PtrToInit, kInit << kPtrShift)
136 // All types (including union types) that represent program values,
137 // except Gen (which is special). Boxed*, PtrTo*, and PtrToBoxed* only
138 // exist for these types.
139 #define IRT_USERLAND(c) IRT_PHP(c) IRT_PHP_UNIONS(c)
141 // All types with just a single bit set
142 #define IRT_PRIMITIVE IRT_PHP(IRT_BOXES) IRT_RUNTIME
145 #define IR_TYPES IRT_USERLAND(IRT_BOXES_WITH_ANY) IRT_RUNTIME IRT_UNIONS \
149 * Type is used to represent the types of values in the jit. Every Type
150 * represents a set of types, with Type::Top being a superset of all Types and
151 * Type::Bottom being a subset of all Types. The elements forming these sets of
152 * types come from the types of PHP-visible values (Str, Obj, Int, ...) and
153 * runtime-internal types (Func, TCA, ActRec, ...).
155 * Types can be constructed from the predefined constants or by composing
156 * existing Types in various ways. Unions, intersections, and subtractions are
157 * all supported, though for implementation-specific reasons certain
158 * combinations of specialized types cannot be represented. A type is
159 * considered specialized if it refers to a specific Class or a
160 * ArrayData::ArrayKind. As an example, if A and B are unrelated Classes,
161 * Obj<A> | Obj<B> is impossible to represent. However, if B is a subclass of
162 * A, Obj<A> | Obj<B> == Obj<B>, which can be represented as a Type.
165 typedef uint64_t bits_t
;
167 static const size_t kBoxShift
= 11;
168 static const size_t kPtrShift
= kBoxShift
* 2;
169 static const size_t kPtrBoxShift
= kBoxShift
+ kPtrShift
;
172 #define IRT(name, bits) k##name = (bits),
177 // An ArrayKind in the top 16 bits, optional RepoAuthType::Array* in
178 // the lower 48 bits, and the low bit that says whether the kind is
180 enum class ArrayInfo
: uintptr_t {};
183 bool m_hasConstVal
:1;
188 // Constant values. Validity determined by m_hasConstVal and m_bits.
192 const StringData
* m_strVal
;
193 const ArrayData
* m_arrVal
;
194 const HPHP::Func
* m_funcVal
;
195 const Class
* m_clsVal
;
197 RDS::Handle m_rdsHandleVal
;
198 TypedValue
* m_ptrVal
;
200 // Specialization for object classes and arrays.
201 const Class
* m_class
;
202 ArrayInfo m_arrayInfo
;
205 static ArrayInfo
makeArrayInfo(folly::Optional
<ArrayData::ArrayKind
> kind
,
206 const RepoAuthType::Array
* arrTy
) {
207 auto ret
= reinterpret_cast<uintptr_t>(arrTy
);
208 if (kind
.hasValue()) {
210 ret
|= uintptr_t{*kind
} << 48;
212 return static_cast<ArrayInfo
>(ret
);
215 static bool arrayKindValid(ArrayInfo info
) {
216 return static_cast<uintptr_t>(info
) & 0x1;
219 static ArrayData::ArrayKind
kind(ArrayInfo info
) {
220 assert(arrayKindValid(info
));
221 return static_cast<ArrayData::ArrayKind
>(
222 static_cast<uintptr_t>(info
) >> 48
226 // May return nullptr if we have no specialized array type
228 static const RepoAuthType::Array
* arrayType(ArrayInfo info
) {
229 return reinterpret_cast<const RepoAuthType::Array
*>(
230 static_cast<uintptr_t>(info
) & (-1ull >> 16) & ~0x1
234 bool checkValid() const;
236 explicit Type(bits_t bits
, uintptr_t extra
= 0)
238 , m_hasConstVal(false)
241 assert(checkValid());
244 explicit Type(bits_t bits
, const Class
* klass
)
246 , m_hasConstVal(false)
249 assert(checkValid());
252 explicit Type(bits_t bits
, ArrayInfo arrayInfo
)
254 , m_hasConstVal(false)
255 , m_arrayInfo(arrayInfo
)
257 assert(checkValid());
260 explicit Type(bits_t bits
, ArrayData::ArrayKind
) = delete;
262 static bits_t
bitsFromDataType(DataType outer
, DataType inner
);
264 // combine, Union, and Intersect are used for operator| and operator&. See
266 template<typename Oper
>
267 static Type
combine(bits_t newBits
, Type a
, Type b
);
274 # define IRT(name, ...) static const Type name;
280 , m_hasConstVal(false)
284 explicit Type(DataType outerType
, DataType innerType
= KindOfInvalid
)
285 : m_bits(bitsFromDataType(outerType
, innerType
))
286 , m_hasConstVal(false)
290 explicit Type(const RuntimeType
& rtt
);
291 explicit Type(const DynLocation
* dl
);
293 size_t hash() const {
294 return hash_int64_pair(m_bits
| (bits_t(m_hasConstVal
) << 63), m_extra
);
297 Type
& operator=(Type b
) {
299 m_hasConstVal
= b
.m_hasConstVal
;
304 std::string
constValString() const;
305 std::string
toString() const;
306 static std::string
debugString(Type t
);
307 static Type
fromString(const std::string
& str
);
309 ////////// Support for constants //////////
312 // forConst returns the Type to use for a given C++ value. The only
313 // interesting case is int/bool disambiguation. Enums are treated as ints.
315 static typename
std::enable_if
<
316 std::is_integral
<T
>::value
|| std::is_enum
<T
>::value
,
318 >::type
forConst(T
) {
319 return std::is_same
<T
,bool>::value
? Type::Bool
: Type::Int
;
321 static Type
forConst(const HPHP::Func
*) { return Func
; }
322 static Type
forConst(const Class
*) { return Cls
; }
323 static Type
forConst(JIT::TCA
) { return TCA
; }
324 static Type
forConst(double) { return Dbl
; }
325 static Type
forConst(const StringData
* sd
) {
326 assert(sd
->isStatic());
329 static Type
forConst(const ArrayData
* ad
) {
330 assert(ad
->isStatic());
331 return StaticArr
.specialize(ad
->kind());
335 // Returns true iff this Type represents a known value.
336 bool isConst() const {
337 return m_hasConstVal
|| subtypeOfAny(Uninit
, InitNull
, Nullptr
);
340 // Returns true iff this Type is a constant value of type t.
341 bool isConst(Type t
) const {
342 return subtypeOf(t
) && isConst();
345 // Returns true iff this Type represents the constant val, using the same C++
346 // type -> Type mapping as Type::cns().
348 bool isConst(T val
) const {
349 return subtypeOf(cns(val
));
353 static Type
cns(T val
, Type ret
) {
354 assert(!ret
.m_hasConstVal
);
355 ret
.m_hasConstVal
= true;
357 static_assert(sizeof(T
) <= sizeof ret
,
358 "Constant data was larger than supported");
359 static_assert(std::is_pod
<T
>::value
,
360 "Constant data wasn't a pod");
361 const auto toCopy
= constToBits_detail::promoteIfNeeded(val
);
362 static_assert(sizeof toCopy
== 8,
363 "Unexpected size for toCopy");
364 std::memcpy(&ret
.m_extra
, &toCopy
, sizeof toCopy
);
369 static Type
cns(T val
) {
370 return cns(val
, forConst(val
));
373 static Type
cns(std::nullptr_t
) {
374 return Type::Nullptr
;
377 static Type
cns(const TypedValue tv
) {
378 if (tv
.m_type
== KindOfUninit
) return Type::Uninit
;
379 if (tv
.m_type
== KindOfNull
) return Type::InitNull
;
387 case KindOfStaticString
:
388 return Type(tv
.m_type
);
391 return forConst(tv
.m_data
.pstr
);
394 return forConst(tv
.m_data
.parr
);
397 always_assert(false && "Invalid KindOf for constant TypedValue");
400 ret
.m_hasConstVal
= true;
401 ret
.m_extra
= tv
.m_data
.num
;
405 // If this represents a constant value, return the most specific strict
406 // supertype of this we can represent. In most cases this just erases the
407 // constant value: Int<4> -> Int, Dbl<2.5> -> Dbl. Arrays are special since
408 // they can be both constant and specialized, so keep the array's kind in the
410 Type
dropConstVal() const {
411 if (!m_hasConstVal
) return *this;
414 if (subtypeOf(StaticArr
)) {
415 return Type::StaticArr
.specialize(arrVal()->kind());
420 // Relaxes the type to one that we can check in codegen
421 Type
relaxToGuardable() const;
423 bool hasRawVal() const {
424 return m_hasConstVal
;
427 uint64_t rawVal() const {
428 assert(m_hasConstVal
);
432 bool boolVal() const {
433 assert(subtypeOf(Bool
) && m_hasConstVal
);
434 assert(m_boolVal
<= 1);
438 int64_t intVal() const {
439 assert(subtypeOf(Int
) && m_hasConstVal
);
443 double dblVal() const {
444 assert(subtypeOf(Dbl
) && m_hasConstVal
);
448 const StringData
* strVal() const {
449 assert(subtypeOf(StaticStr
) && m_hasConstVal
);
453 const ArrayData
* arrVal() const {
454 assert(subtypeOf(StaticArr
) && m_hasConstVal
);
458 const HPHP::Func
* funcVal() const {
459 assert(subtypeOf(Func
) && m_hasConstVal
);
463 const Class
* clsVal() const {
464 assert(subtypeOf(Cls
) && m_hasConstVal
);
468 RDS::Handle
rdsHandleVal() const {
469 assert(subtypeOf(RDSHandle
) && m_hasConstVal
);
470 return m_rdsHandleVal
;
473 JIT::TCA
tcaVal() const {
474 assert(subtypeOf(TCA
) && m_hasConstVal
);
478 ////////// Methods to query properties of the type //////////
480 bool isBoxed() const {
481 return subtypeOf(BoxedCell
);
484 bool notBoxed() const {
485 assert(subtypeOf(Gen
));
486 return subtypeOf(Cell
);
489 bool maybeBoxed() const {
490 return maybe(BoxedCell
);
494 return subtypeOf(PtrToGen
);
497 bool notPtr() const {
498 return not(PtrToGen
);
501 bool isCounted() const {
502 return subtypeOf(Counted
);
505 bool maybeCounted() const {
506 return maybe(Counted
);
509 bool notCounted() const {
514 * Returns true iff this is a union type. Note that this is the plain old set
515 * definition of union, so Type::Str, Type::Arr, and Type::Null will all
518 bool isUnion() const {
519 // This will return true iff more than 1 bit is set in m_bits.
520 return (m_bits
& (m_bits
- 1)) != 0;
524 * Returns true if this value has a known constant DataType enum value. If
525 * the type is exactly Type::Str or Type::Null it returns true anyway, even
526 * though it could be either KindOfStaticString or KindOfString, or
527 * KindOfUninit or KindOfNull, respectively.
529 * TODO(#3390819): this function should return false for Str and Null.
531 * Pre: subtypeOf(StackElem)
533 bool isKnownDataType() const {
534 assert(subtypeOf(StackElem
));
536 // Some unions that correspond to single KindOfs. And Type::Str
537 // and Type::Null for now for historical reasons.
538 if (subtypeOfAny(Str
, Arr
, Null
, BoxedCell
)) {
546 * Similar to isKnownDataType, with the added restriction that the type not
549 bool isKnownUnboxedDataType() const {
550 return isKnownDataType() && notBoxed();
554 * Returns true if this requires a register to hold a DataType at runtime.
556 bool needsReg() const {
557 return subtypeOf(StackElem
) && !isKnownDataType();
560 bool needsValueReg() const {
561 return !subtypeOfAny(Uninit
, InitNull
, Nullptr
);
564 bool needsStaticBitCheck() const {
565 return maybe(StaticStr
| StaticArr
);
568 bool canRunDtor() const {
569 return maybe(CountedArr
| BoxedCountedArr
| Obj
| BoxedObj
|
573 // return true if this corresponds to a type that is passed by value in C++
574 bool isSimpleType() const {
575 return subtypeOfAny(Bool
, Int
, Dbl
, Null
);
578 // return true if this corresponds to a type that is passed by reference in
580 bool isReferenceType() const {
581 return subtypeOfAny(Str
, Arr
, Obj
, Res
);
584 int nativeSize() const {
585 if (subtypeOf(Type::Int
| Type::Func
)) return sz::qword
;
586 if (subtypeOf(Type::Bool
)) return sz::byte
;
590 ////////// Support for specialized types: Obj classes and Arr kinds //////////
593 * True if type can have a specialized class.
595 bool canSpecializeClass() const {
596 return (m_bits
& kAnyObj
) && !(m_bits
& kAnyArr
);
600 * True if type can have specialized array information.
602 bool canSpecializeArray() const {
603 return (m_bits
& kAnyArr
) && !(m_bits
& kAnyObj
);
606 bool canSpecializeAny() const {
607 return canSpecializeClass() || canSpecializeArray();
610 Type
specialize(const Class
* klass
) const {
611 assert(canSpecializeClass() && m_class
== nullptr);
612 return Type(m_bits
, klass
);
615 Type
specialize(ArrayData::ArrayKind arrayKind
) const {
616 assert(canSpecializeArray());
617 return Type(m_bits
, makeArrayInfo(arrayKind
, nullptr));
620 Type
specialize(const RepoAuthType::Array
* array
) const {
621 assert(canSpecializeArray());
622 return Type(m_bits
, makeArrayInfo(folly::none
, array
));
625 bool isSpecialized() const {
626 return (canSpecializeClass() && getClass()) ||
627 (canSpecializeArray() && (hasArrayKind() || getArrayType()));
630 Type
unspecialize() const {
634 const Class
* getClass() const {
635 assert(canSpecializeClass());
639 bool hasArrayKind() const {
640 assert(canSpecializeArray());
641 return m_hasConstVal
|| arrayKindValid(m_arrayInfo
);
644 ArrayData::ArrayKind
getArrayKind() const {
645 assert(hasArrayKind());
646 return m_hasConstVal
? m_arrVal
->kind() : kind(m_arrayInfo
);
649 folly::Optional
<ArrayData::ArrayKind
> getOptArrayKind() const {
650 if (hasArrayKind()) return getArrayKind();
654 const RepoAuthType::Array
* getArrayType() const {
655 assert(canSpecializeArray());
656 return m_hasConstVal
? nullptr : arrayType(m_arrayInfo
);
659 // Returns a subset of *this containing only the members relating to its
662 // {Int|Str|Obj<C>|BoxedObj<C>}.specializedType() == {Obj<C>|BoxedObj<C>}
663 Type
specializedType() const {
664 assert(isSpecialized());
665 if (canSpecializeClass()) return *this & AnyObj
;
666 if (canSpecializeArray()) return *this & AnyArr
;
670 ////////// Methods for comparing types //////////
673 * Returns true iff this represents a non-strict subset of t2.
675 bool subtypeOf(Type t2
) const;
677 template<typename
... Types
>
678 bool subtypeOfAny(Type t2
, Types
... ts
) const {
679 return subtypeOf(t2
) || subtypeOfAny(ts
...);
682 bool subtypeOfAny() const {
687 * Returns true if this is a strict subtype of t2.
689 bool strictSubtypeOf(Type t2
) const {
690 return *this != t2
&& subtypeOf(t2
);
694 * Returns true if any subtype of this is a subtype of t2.
696 bool maybe(Type t2
) const {
697 return (*this & t2
) != Bottom
;
701 * Returns true if no subtypes of this are subtypes of t2.
703 bool not(Type t2
) const {
708 * Returns true if this is exactly equal to t2. Be careful: you
709 * probably mean subtypeOf.
711 bool equals(Type t2
) const {
712 return m_bits
== t2
.m_bits
&& m_hasConstVal
== t2
.m_hasConstVal
&&
713 m_extra
== t2
.m_extra
;
716 bool operator==(Type t2
) const { return equals(t2
); }
717 bool operator!=(Type t2
) const { return !operator==(t2
); }
719 ////////// Methods for combining Types in various ways //////////
722 * Standard set operations: union, intersection, and difference.
724 Type
operator|(Type other
) const;
725 Type
& operator|=(Type other
) { return *this = *this | other
; }
727 Type
operator&(Type other
) const;
728 Type
& operator&=(Type other
) { return *this = *this & other
; }
730 Type
operator-(Type other
) const;
731 Type
& operator-=(Type other
) { return *this = *this - other
; }
734 * unionOf: return the least common predefined supertype of t1 and t2,
735 * i.e.. the most refined type t3 such that t1 <= t3 and t2 <= t3. Note that
736 * arbitrary union types are possible using operator| but this function
737 * always returns one of the predefined types.
739 static Type
unionOf(Type t1
, Type t2
);
741 ////////// Support for inner types of boxed and pointer types //////////
744 assert(subtypeOf(Cell
));
745 // Boxing Uninit returns InitNull but that logic doesn't belong
747 assert(not(Uninit
) || equals(Cell
));
748 return Type(m_bits
<< kBoxShift
,
749 isSpecialized() && !m_hasConstVal
? m_extra
: 0);
752 // This computes the type effects of the Unbox opcode.
754 assert(subtypeOf(Gen
));
755 return (*this & Cell
) | (*this & BoxedCell
).innerType();
758 Type
innerType() const {
759 assert(isBoxed() || equals(Bottom
));
760 return Type(m_bits
>> kBoxShift
, m_extra
);
765 return Type(m_bits
>> kPtrShift
, isSpecialized() ? m_extra
: 0);
768 Type
derefIfPtr() const {
769 assert(subtypeOf(Gen
| PtrToGen
));
770 return isPtr() ? deref() : *this;
773 // Returns the "stripped" version of this: dereferenced and unboxed,
776 return derefIfPtr().unbox();
781 assert(subtypeOf(Gen
));
782 return Type(m_bits
<< kPtrShift
,
783 isSpecialized() && !m_hasConstVal
? m_extra
: 0);
786 ////////// Methods for talking to other type systems in the VM //////////
789 * TODO(#3390819): this function does not exactly convert this type into a
790 * DataType in cases where a type does not exactly map to a DataType. For
791 * example, Null.toDataType() returns KindOfNull, even though it could be
794 * Try not to use this function in new code.
796 DataType
toDataType() const;
798 RuntimeType
toRuntimeType() const;
801 typedef folly::Optional
<Type
> OptType
;
803 inline bool operator<(Type a
, Type b
) { return a
.strictSubtypeOf(b
); }
804 inline bool operator>(Type a
, Type b
) { return b
.strictSubtypeOf(a
); }
805 inline bool operator<=(Type a
, Type b
) { return a
.subtypeOf(b
); }
806 inline bool operator>=(Type a
, Type b
) { return b
.subtypeOf(a
); }
809 * JIT::Type must be small enough for efficient pass-by-value.
811 static_assert(sizeof(Type
) <= 2 * sizeof(uint64_t),
812 "JIT::Type should fit in (2 * sizeof(uint64_t))");
815 * Return the most refined type that can be used to represent the type
816 * in a live TypedValue.
818 Type
liveTVType(const TypedValue
* tv
);
821 * Return the boxed version of the input type, taking into account php
822 * semantics and subtle implementation details.
827 * Create a Type from a RepoAuthType.
829 Type
convertToType(RepoAuthType ty
);
832 * Return the type resulting from refining oldType with the fact that it also
833 * belongs to newType. This essentially intersects the two types, except that
834 * it has special logic for boxed types.
836 Type
refineType(Type oldType
, Type newType
);
838 //////////////////////////////////////////////////////////////////////
840 struct TypeConstraint
{
841 /* implicit */ TypeConstraint(DataTypeCategory cat
= DataTypeGeneric
,
842 DataTypeCategory inner
= DataTypeGeneric
)
849 explicit TypeConstraint(const Class
* cls
)
850 : TypeConstraint(DataTypeSpecialized
)
852 setDesiredClass(cls
);
855 void applyConstraint(TypeConstraint newTc
);
857 std::string
toString() const;
859 TypeConstraint
& setWeak(bool w
= true) {
864 bool operator==(TypeConstraint tc2
) const {
865 return category
== tc2
.category
&& innerCat
== tc2
.innerCat
&&
866 weak
== tc2
.weak
&& m_specialized
== tc2
.m_specialized
;
868 bool operator!=(TypeConstraint tc2
) const { return !(*this == tc2
); }
871 return category
== DataTypeGeneric
&& innerCat
== DataTypeGeneric
&& !weak
;
874 static constexpr uint8_t kWantArrayKind
= 0x1;
876 TypeConstraint
& setWantArrayKind() {
877 assert(!wantClass());
878 assert(category
== DataTypeSpecialized
);
879 m_specialized
|= kWantArrayKind
;
883 bool wantArrayKind() const { return m_specialized
& kWantArrayKind
; }
885 TypeConstraint
& setDesiredClass(const Class
* cls
) {
886 assert(m_specialized
== 0 ||
887 desiredClass()->classof(cls
) || cls
->classof(desiredClass()));
888 assert(category
== DataTypeSpecialized
|| innerCat
== DataTypeSpecialized
);
889 m_specialized
= reinterpret_cast<uintptr_t>(cls
);
894 bool wantClass() const {
895 return m_specialized
!= 0 && !wantArrayKind();
898 const Class
* desiredClass() const {
900 return reinterpret_cast<const Class
*>(m_specialized
);
903 // Get the inner constraint, preserving m_specialized if appropriate.
904 TypeConstraint
inner() const {
905 auto tc
= TypeConstraint
{innerCat
}.setWeak(weak
);
906 if (tc
.category
== DataTypeSpecialized
) tc
.m_specialized
= m_specialized
;
910 // category starts as DataTypeGeneric and is refined to more specific values
911 // by consumers of the type.
912 DataTypeCategory category
;
914 // When a value is boxed, innerCat is used to determine how we can relax the
915 // inner type. innerCat is only meaningful when category is at least
916 // DataTypeCountness, since a category of DataTypeGeneric relaxes types all
917 // the way to Gen which has no meaningful inner type.
918 DataTypeCategory innerCat
;
920 // If weak is true, the consumer of the value being constrained doesn't
921 // actually want to constrain the guard (if found). Most often used to figure
922 // out if a type can be used without further constraining guards.
926 // m_specialized either holds a Class* or a 1 in its low bit, indicating that
927 // for a DataTypeSpecialized constraint, we require the specified class or an
928 // array kind, respectively.
929 uintptr_t m_specialized
;
932 const int kTypeWordOffset
= offsetof(TypedValue
, m_type
) % 8;
933 const int kTypeShiftBits
= kTypeWordOffset
* CHAR_BIT
;
935 // left shift an immediate DataType, for type, to the correct position
936 // within one of the registers used to pass a TypedValue by value.
937 inline uint64_t toDataTypeForCall(Type type
) {
938 return uint64_t(type
.toDataType()) << kTypeShiftBits
;