bool Type::checkValid() const { static_assert(sizeof(m_arrayKind) == 1, "Type expects ArrayKind to be one byte"); if (m_extra) { assert((!(m_bits & kAnyObj) || !(m_bits & kAnyArr)) && "Conflicting specialization"); if (canSpecializeArrayKind() && hasArrayKind() && !m_hasConstVal) { assert(!(m_extra & 0xffffffffffff0000) && "Non-zero padding bits in Type with array kind"); } } return true; }
RuntimeType Type::toRuntimeType() const { assert(!isPtr()); auto const outer = isBoxed() ? KindOfRef : toDataType(); auto const inner = isBoxed() ? innerType().toDataType() : KindOfNone; auto rtt = RuntimeType{outer, inner}; if (isSpecialized()) { if (subtypeOf(Type::Arr)) { return hasArrayKind() ? rtt.setArrayKind(getArrayKind()) : rtt; } if (subtypeOf(Type::Obj)) { return rtt.setKnownClass(getClass()); } } return rtt; }
Type Type::combine(bits_t newBits, Type other) const { static_assert(std::is_same<Oper, Union>::value || std::is_same<Oper, Intersect>::value, "Type::combine given unsupported template argument"); // If neither type is specialized, the result is simple. if (LIKELY(!isSpecialized() && !other.isSpecialized())) { return Type(newBits); } // If one of the types can't be specialized while the other is specialized, // preserve the specialization. if (!canSpecializeAny() || !other.canSpecializeAny()) { auto const specType = isSpecialized() ? specializedType() : other.specializedType(); // If the specialized type doesn't exist in newBits, drop the // specialization. if (newBits & specType.m_bits) return Type(newBits, specType.m_extra); return Type(newBits); } // If both types are eligible for the same kind of specialization and at // least one is specialized, delegate to Oper::combineSame. if (canSpecializeClass() && other.canSpecializeClass()) { folly::Optional<const Class*> aClass, bClass; if (getClass()) aClass = getClass(); if (other.getClass()) bClass = other.getClass(); return Oper::template combineSame<ClassOps>(newBits, kAnyObj, aClass, bClass); } if (canSpecializeArrayKind() && other.canSpecializeArrayKind()) { folly::Optional<ArrayData::ArrayKind> aKind, bKind; if (hasArrayKind()) aKind = getArrayKind(); if (other.hasArrayKind()) bKind = other.getArrayKind(); return Oper::template combineSame<ArrayOps>(newBits, kAnyArr, aKind, bKind); } // The types are eligible for different kinds of specialization and at least // one is specialized, so delegate to Oper::combineDifferent. return Oper::combineDifferent(newBits, *this, other); }