Swift进阶-类与结构体
Swift-函数派发
Swift进阶-属性
Swift进阶-指针
Swift进阶-内存管理
Swift进阶-TargetClassMetadata和TargetStructMetadata数据结构源码分析
Swift进阶-Mirror解析
Swift进阶-闭包
Swift进阶-协议
Swift进阶-泛型
Swift进阶-String源码解析
Swift进阶-Array源码解析
前言
首先我们从官方上下载Swift源码。然后我们从头开始分析,从哪儿?万物皆初始化函数开始,在类与结构体章节我就分析出:
Swift 对象内存分配:
__allocating_init
->swift_allocObject
->_swift_allocObject_
->swift_slowAlloc
->malloc
从而在源码中找到_swift_allocObject_
就是我们对象初始化的入口函数:
点击进去找到创建HeapObject
入口:
HeapMetadata
其实是TargetHeapMetadata
取的别名:
TargetHeapMetadata
声明了俩初始化函数,但它本身继承于TargetMetadata
TargetHeapMetadata
的源码声明:
/// The common structure of all metadata for heap-allocated types. A
/// pointer to one of these can be retrieved by loading the 'isa'
/// field of any heap object, whether it was managed by Swift or by
/// Objective-C. However, when loading from an Objective-C object,
/// this metadata may not have the heap-metadata header, and it may
/// not be the Swift type metadata for the object's dynamic type.
template <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
using HeaderType = TargetHeapMetadataHeader<Runtime>;
TargetHeapMetadata() = default;
constexpr TargetHeapMetadata(MetadataKind kind)
: TargetMetadata<Runtime>(kind) {}
constexpr TargetHeapMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
: TargetMetadata<Runtime>(isa) {}
};
using HeapMetadata = TargetHeapMetadata<InProcess>;
TargetMetadata
的源码声明:
/// The common structure of all type metadata.
template <typename Runtime>
struct TargetMetadata {
using StoredPointer = typename Runtime::StoredPointer;
/// The basic header type.
typedef TargetTypeMetadataHeader<Runtime> HeaderType;
constexpr TargetMetadata()
: Kind(static_cast<StoredPointer>(MetadataKind::Class)) {}
constexpr TargetMetadata(MetadataKind Kind)
: Kind(static_cast<StoredPointer>(Kind)) {}
#if SWIFT_OBJC_INTEROP
protected:
constexpr TargetMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
: Kind(reinterpret_cast<StoredPointer>(isa)) {}
#endif
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
/// the kind value.
StoredPointer Kind;
public:
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
/// Set the metadata kind.
void setKind(MetadataKind kind) {
Kind = static_cast<StoredPointer>(kind);
}
protected:
const TargetAnyClassMetadata<Runtime> *getClassISA() const {
return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
}
void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
Kind = reinterpret_cast<StoredPointer>(isa);
}
public:
/// Is this a class object--the metadata record for a Swift class (which also
/// serves as the class object), or the class object for an ObjC class (which
/// is not metadata)?
bool isClassObject() const {
return static_cast<MetadataKind>(getKind()) == MetadataKind::Class;
}
/// Does the given metadata kind represent metadata for some kind of class?
static bool isAnyKindOfClass(MetadataKind k) {
switch (k) {
case MetadataKind::Class:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
return true;
default:
return false;
}
}
/// Is this metadata for an existential type?
bool isAnyExistentialType() const {
switch (getKind()) {
case MetadataKind::ExistentialMetatype:
case MetadataKind::Existential:
return true;
default:
return false;
}
}
/// Is this either type metadata or a class object for any kind of class?
bool isAnyClass() const {
return isAnyKindOfClass(getKind());
}
const ValueWitnessTable *getValueWitnesses() const {
return asFullMetadata(this)->ValueWitnesses;
}
const TypeLayout *getTypeLayout() const {
return getValueWitnesses()->getTypeLayout();
}
void setValueWitnesses(const ValueWitnessTable *table) {
asFullMetadata(this)->ValueWitnesses = table;
}
// Define forwarders for value witnesses. These invoke this metadata's value
// witness table with itself as the 'self' parameter.
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \
template<typename...A> \
_ResultOf<ValueWitnessTypes::WITNESS ## Unsigned>::type \
vw_##WITNESS(A &&...args) const { \
return getValueWitnesses()->WITNESS(std::forward<A>(args)..., this); \
}
#define DATA_VALUE_WITNESS(LOWER, UPPER, TYPE)
#include "swift/ABI/ValueWitness.def"
unsigned vw_getEnumTag(const OpaqueValue *value) const {
return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast<OpaqueValue*>(value), this);
}
void vw_destructiveProjectEnumData(OpaqueValue *value) const {
getValueWitnesses()->_asEVWT()->destructiveProjectEnumData(value, this);
}
void vw_destructiveInjectEnumTag(OpaqueValue *value, unsigned tag) const {
getValueWitnesses()->_asEVWT()->destructiveInjectEnumTag(value, tag, this);
}
size_t vw_size() const {
return getValueWitnesses()->getSize();
}
size_t vw_alignment() const {
return getValueWitnesses()->getAlignment();
}
size_t vw_stride() const {
return getValueWitnesses()->getStride();
}
unsigned vw_getNumExtraInhabitants() const {
return getValueWitnesses()->getNumExtraInhabitants();
}
/// Allocate an out-of-line buffer if values of this type don't fit in the
/// ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *allocateBufferIn(ValueBuffer *buffer) const;
/// Get the address of the memory previously allocated in the ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *projectBufferFrom(ValueBuffer *buffer) const;
/// Deallocate an out-of-line buffer stored in 'buffer' if values of this type
/// are not stored inline in the ValueBuffer.
void deallocateBufferIn(ValueBuffer *buffer) const;
// Allocate an out-of-line buffer box (reference counted) if values of this
// type don't fit in the ValueBuffer.
// NOTE: This *is* a box for copy-on-write existentials.
OpaqueValue *allocateBoxForExistentialIn(ValueBuffer *Buffer) const;
// Deallocate an out-of-line buffer box if one is present.
void deallocateBoxForExistentialIn(ValueBuffer *Buffer) const;
/// Get the nominal type descriptor if this metadata describes a nominal type,
/// or return null if it does not.
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>
getTypeContextDescriptor() const {
switch (getKind()) {
case MetadataKind::Class: {
if (Runtime::ObjCInterop) {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadataObjCInterop<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
} else {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadata<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
}
}
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
return static_cast<const TargetValueMetadata<Runtime> *>(this)
->Description;
case MetadataKind::ForeignClass:
return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)
->Description;
default:
return nullptr;
}
}
/// Get the class object for this type if it has one, or return null if the
/// type is not a class (or not a class with a class object).
const typename Runtime::template TargetClassMetadata<Runtime> *
getClassObject() const;
/// Retrieve the generic arguments of this type, if it has any.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *
getGenericArgs() const {
auto description = getTypeContextDescriptor();
if (!description)
return nullptr;
auto generics = description->getGenericContext();
if (!generics)
return nullptr;
auto asWords = reinterpret_cast<
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
return asWords + description->getGenericArgumentOffset();
}
bool satisfiesClassConstraint() const;
const TypeContextDescriptor *getDescription() const;
bool isStaticallySpecializedGenericMetadata() const;
bool isCanonicalStaticallySpecializedGenericMetadata() const;
#if SWIFT_OBJC_INTEROP
/// Get the ObjC class object for this type if it has one, or return null if
/// the type is not a class (or not a class with a class object).
/// This is allowed for InProcess values only.
template <typename R = Runtime>
typename std::enable_if<std::is_same<R, InProcess>::value, Class>::type
getObjCClassObject() const {
return reinterpret_cast<Class>(
const_cast<TargetClassMetadata<
InProcess, TargetAnyClassMetadataObjCInterop<InProcess>> *>(
getClassObject()));
}
#endif
#ifndef NDEBUG
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
"Only meant for use in the debugger");
#endif
protected:
friend struct TargetOpaqueMetadata<Runtime>;
/// Metadata should not be publicly copied or moved.
constexpr TargetMetadata(const TargetMetadata &) = default;
TargetMetadata &operator=(const TargetMetadata &) = default;
constexpr TargetMetadata(TargetMetadata &&) = default;
TargetMetadata &operator=(TargetMetadata &&) = default;
};
TargetMatedata中只有一个属性
Kind
来看一个重点函数getTypeContextDescriptor()
可以看到这个函数的作用是根据Kind
的不同类型,去获取描述器Description
。所以可以分析出:
对于class
来说它的Metadata
是TargetClassMetadata
;
对于struct、enum、optional
来说它的Metadata
是TargetValueMetadata
,但是它们都有自己类型的Metadata
去继承于TargetValueMetadata
。
一、TargetClassMetadata
1、TargetClassMetadata源码分析
1.1 从源码分析出TargetClassMetadata
的数据结构
ClassMetadata
其实是TargetClassMetadata
取的别名:
#if SWIFT_OBJC_INTEROP
// 如果是继承自NSObject,TargetClassMetadata的父类是TargetAnyClassMetadataObjCInterop
using ClassMetadata =
TargetClassMetadata<InProcess,
TargetAnyClassMetadataObjCInterop<InProcess>>; TargetAnyClassMetadataObjCInterop
#else
// 如果是纯swift类,TargetClassMetadata的父类是TargetAnyClassMetadata
using ClassMetadata =
TargetClassMetadata<InProcess, TargetAnyClassMetadata<InProcess>>;
#endif
TargetClassMetadata
的源码声明:
/// The structure of all class metadata. This structure is embedded
/// directly within the class's heap metadata structure and therefore
/// cannot be extended without an ABI break.
///
/// Note that the layout of this type is compatible with the layout of
/// an Objective-C class.
///
/// If the Runtime supports Objective-C interoperability, this class inherits
/// from TargetAnyClassMetadataObjCInterop, otherwise it inherits from
/// TargetAnyClassMetadata.
template <typename Runtime, typename TargetAnyClassMetadataVariant>
struct TargetClassMetadata : public TargetAnyClassMetadataVariant {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
TargetClassMetadata() = default;
constexpr TargetClassMetadata(const TargetAnyClassMetadataVariant &base,
ClassFlags flags,
ClassIVarDestroyer *ivarDestroyer,
StoredPointer size, StoredPointer addressPoint,
StoredPointer alignMask,
StoredPointer classSize,
StoredPointer classAddressPoint)
: TargetAnyClassMetadataVariant(base), Flags(flags),
InstanceAddressPoint(addressPoint), InstanceSize(size),
InstanceAlignMask(alignMask), Reserved(0), ClassSize(classSize),
ClassAddressPoint(classAddressPoint), Description(nullptr),
IVarDestroyer(ivarDestroyer) {}
// The remaining fields are valid only when isTypeMetadata().
// The Objective-C runtime knows the offsets to some of these fields.
// Be careful when accessing them.
/// Swift-specific class flags.
ClassFlags Flags;
/// The address point of instances of this type.
uint32_t InstanceAddressPoint;
/// The required size of instances of this type.
/// 'InstanceAddressPoint' bytes go before the address point;
/// 'InstanceSize - InstanceAddressPoint' bytes go after it.
uint32_t InstanceSize;
/// The alignment mask of the address point of instances of this type.
uint16_t InstanceAlignMask;
/// Reserved for runtime use.
uint16_t Reserved;
/// The total size of the class object, including prefix and suffix
/// extents.
uint32_t ClassSize;
/// The offset of the address point within the class object.
uint32_t ClassAddressPoint;
// Description is by far the most likely field for a client to try
// to access directly, so we force access to go through accessors.
private:
/// An out-of-line Swift-specific description of the type, or null
/// if this is an artificial subclass. We currently provide no
/// supported mechanism for making a non-artificial subclass
/// dynamically.
TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
public:
/// A function for destroying instance variables, used to clean up after an
/// early return from a constructor. If null, no clean up will be performed
/// and all ivars must be trivial.
TargetSignedPointer<Runtime, ClassIVarDestroyer * __ptrauth_swift_heap_object_destructor> IVarDestroyer;
// After this come the class members, laid out as follows:
// - class members for the superclass (recursively)
// - metadata reference for the parent, if applicable
// - generic parameters for this class
// - class variables (if we choose to support these)
// - "tabulated" virtual methods
using TargetAnyClassMetadataVariant::isTypeMetadata;
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
getDescription() const {
assert(isTypeMetadata());
return Description;
}
typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
assert(isTypeMetadata());
return Description;
}
void setDescription(const TargetClassDescriptor<Runtime> *description) {
Description = description;
}
// [NOTE: Dynamic-subclass-KVO]
//
// Using Objective-C runtime, KVO can modify object behavior without needing
// to modify the object's code. This is done by dynamically creating an
// artificial subclass of the the object's type.
//
// The isa pointer of the observed object is swapped out to point to
// the artificial subclass, which has the following properties:
// - Setters for observed keys are overridden to additionally post
// notifications.
// - The `-class` method is overridden to return the original class type
// instead of the artificial subclass type.
//
// For more details, see:
// https://www.mikeash.com/pyblog/friday-qa-2009-01-23.html
/// Is this class an artificial subclass, such as one dynamically
/// created for various dynamic purposes like KVO?
/// See [NOTE: Dynamic-subclass-KVO]
bool isArtificialSubclass() const {
assert(isTypeMetadata());
return Description == nullptr;
}
void setArtificialSubclass() {
assert(isTypeMetadata());
Description = nullptr;
}
ClassFlags getFlags() const {
assert(isTypeMetadata());
return Flags;
}
void setFlags(ClassFlags flags) {
assert(isTypeMetadata());
Flags = flags;
}
StoredSize getInstanceSize() const {
assert(isTypeMetadata());
return InstanceSize;
}
void setInstanceSize(StoredSize size) {
assert(isTypeMetadata());
InstanceSize = size;
}
StoredPointer getInstanceAddressPoint() const {
assert(isTypeMetadata());
return InstanceAddressPoint;
}
void setInstanceAddressPoint(StoredSize size) {
assert(isTypeMetadata());
InstanceAddressPoint = size;
}
StoredPointer getInstanceAlignMask() const {
assert(isTypeMetadata());
return InstanceAlignMask;
}
void setInstanceAlignMask(StoredSize mask) {
assert(isTypeMetadata());
InstanceAlignMask = mask;
}
StoredPointer getClassSize() const {
assert(isTypeMetadata());
return ClassSize;
}
void setClassSize(StoredSize size) {
assert(isTypeMetadata());
ClassSize = size;
}
StoredPointer getClassAddressPoint() const {
assert(isTypeMetadata());
return ClassAddressPoint;
}
void setClassAddressPoint(StoredSize offset) {
assert(isTypeMetadata());
ClassAddressPoint = offset;
}
uint16_t getRuntimeReservedData() const {
assert(isTypeMetadata());
return Reserved;
}
void setRuntimeReservedData(uint16_t data) {
assert(isTypeMetadata());
Reserved = data;
}
/// Get a pointer to the field offset vector, if present, or null.
const StoredPointer *getFieldOffsets() const {
assert(isTypeMetadata());
auto offset = getDescription()->getFieldOffsetVectorOffset();
if (offset == 0)
return nullptr;
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const StoredPointer *>(asWords + offset);
}
uint32_t getSizeInWords() const {
assert(isTypeMetadata());
uint32_t size = getClassSize() - getClassAddressPoint();
assert(size % sizeof(StoredPointer) == 0);
return size / sizeof(StoredPointer);
}
/// Given that this class is serving as the superclass of a Swift class,
/// return its bounds as metadata.
///
/// Note that the ImmediateMembersOffset member will not be meaningful.
TargetClassMetadataBounds<Runtime>
getClassBoundsAsSwiftSuperclass() const {
using Bounds = TargetClassMetadataBounds<Runtime>;
auto rootBounds = Bounds::forSwiftRootClass();
// If the class is not type metadata, just use the root-class bounds.
if (!isTypeMetadata())
return rootBounds;
// Otherwise, pull out the bounds from the metadata.
auto bounds = Bounds::forAddressPointAndSize(getClassAddressPoint(),
getClassSize());
// Round the bounds up to the required dimensions.
if (bounds.NegativeSizeInWords < rootBounds.NegativeSizeInWords)
bounds.NegativeSizeInWords = rootBounds.NegativeSizeInWords;
if (bounds.PositiveSizeInWords < rootBounds.PositiveSizeInWords)
bounds.PositiveSizeInWords = rootBounds.PositiveSizeInWords;
return bounds;
}
#if SWIFT_OBJC_INTEROP
/// Given a statically-emitted metadata template, this sets the correct
/// "is Swift" bit for the current runtime. Depending on the deployment
/// target a binary was compiled for, statically emitted metadata templates
/// may have a different bit set from the one that this runtime canonically
/// considers the "is Swift" bit.
void setAsTypeMetadata() {
// If the wrong "is Swift" bit is set, set the correct one.
//
// Note that the only time we should see the "new" bit set while
// expecting the "old" one is when running a binary built for a
// new OS on an old OS, which is not supported, however we do
// have tests that exercise this scenario.
auto otherSwiftBit = (3ULL - SWIFT_CLASS_IS_SWIFT_MASK);
assert(otherSwiftBit == 1ULL || otherSwiftBit == 2ULL);
if ((this->Data & 3) == otherSwiftBit) {
this->Data ^= 3;
}
// Otherwise there should be nothing to do, since only the old "is
// Swift" bit is used for backward-deployed runtimes.
assert(isTypeMetadata());
}
#endif
bool isStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
return this->Flags & ClassFlags::IsStaticSpecialization;
}
bool isCanonicalStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
return this->Flags & ClassFlags::IsCanonicalStaticSpecialization;
}
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Class;
}
};
TargetClassMetadata中的属性:
ClassFlags Flags;
// swift特有的标志
uint32_t InstanceAddressPoint;
// 实例独享内存首地址
uint32_t InstanceSize;
// 实例对象内存大小
uint16_t InstanceAlignMask;
// 实例对象内存对齐方式
uint16_t Reserved;
// 运行时保留字段
uint32_t ClassSize;
// 类的内存大小
uint32_t ClassAddressPoint;
// 类的内存首地址
TargetClassDescriptor * Description;
// 类的描述器
ClassIVarDestroyer * IVarDestroyer
// 实例销毁器
其中TargetClassDescriptor
记录着类的很多信息,包括类名、属性、函数表等等
来看看官方对于TargetClassMetadata
的注释:
所有类元数据的结构。这个结构直接嵌入到类的堆元数据结构中,因此在没有ABI中断的情况下不能扩展。
注意,这种类型的布局与Objective-C类的布局是兼容的。
如果运行时支持Objective-C互操作性,这个类继承自TargetAnyClassMetadataObjCInterop,否则继承自TargetAnyClassMetadata。
而实际上TargetAnyClassMetadataObjCInterop
的父类就是TargetAnyClassMetadata
了!
我们先不研究class在运行时支持Objective-C互操作性(即继承自NSObject),所以TargetClassMetadata
继承自TargetAnyClassMetadata
。
TargetAnyClassMetadata
的源码声明:
/// The portion of a class metadata object that is compatible with
/// all classes, even non-Swift ones.
template <typename Runtime>
struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
using TargetClassMetadata =
typename Runtime::template TargetClassMetadata<Runtime>;
protected:
constexpr TargetAnyClassMetadata(
TargetAnyClassMetadataObjCInterop<Runtime> *isa,
TargetClassMetadata *superclass)
: TargetHeapMetadata<Runtime>(isa), Superclass(superclass) {}
public:
constexpr TargetAnyClassMetadata(TargetClassMetadata *superclass)
: TargetHeapMetadata<Runtime>(MetadataKind::Class),
Superclass(superclass) {}
// Note that ObjC classes do not have a metadata header.
/// The metadata for the superclass. This is null for the root class.
TargetSignedPointer<Runtime, const TargetClassMetadata *
__ptrauth_swift_objc_superclass>
Superclass;
/// Is this object a valid swift type metadata? That is, can it be
/// safely downcast to ClassMetadata?
bool isTypeMetadata() const {
return true;
}
/// A different perspective on the same bit.
bool isPureObjC() const {
return !isTypeMetadata();
}
};
TargetAnyClassClassMetadata有4个属性:
Kind、Superclass、CacheData、Data
TargetClassMetadata的总结:
a.TargetClassMetadata
继承链关系:
TargetClassMetadata
--> TargetAnyClassMetadata
--> TargetHeapMatadata
-->TargetMetadata
b.TargetClassMetadata
的数据结构:
// 类 Metadata
struct TargetClassMetadata {
var kind: Int
var superClass: Any.Type
var cacheData: (Int, Int)
var data: Int
var classFlags: Int32 // swift特有的标志
var instanceAddressPoint: UInt32 // 实例独享内存首地址
var instanceSize: UInt32 // 实例对象内存大小
var instanceAlignmentMask: UInt16 // 实例对象内存对齐方式
var reserved: UInt16 // 运行时保留字段
var classSize: UInt32 // 类的内存大小
var classAddressPoint: UInt32 //类的内存首地址
var typeDescriptor: UnsafeMutablePointer<TargetClassDescriptor> // 类型描述器
var iVarDestroyer: UnsafeRawPointer // 实例销毁器
}
一幅图来描述 Person(name: "安老师", age: 18)
的内存结构:
1.2 分析出完善的TargetClassMetadata
数据结构
在1.1章节的内容中就提到TargetClassDescriptor
中就记录着类的许多信息,我们就从这里深入了解TargetClassMetadata
的数据结构。
TargetClassDescriptor
的源码分析:
template <typename Runtime>
class TargetClassDescriptor final
: public TargetTypeContextDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
/*additional trailing objects:*/
TargetResilientSuperclass<Runtime>,
TargetForeignMetadataInitialization<Runtime>,
TargetSingletonMetadataInitialization<Runtime>,
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>,
TargetOverrideTableHeader<Runtime>,
TargetMethodOverrideDescriptor<Runtime>,
TargetObjCResilientClassStubInfo<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>> {
private:
using TrailingGenericContextObjects =
swift::TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
TargetResilientSuperclass<Runtime>,
TargetForeignMetadataInitialization<Runtime>,
TargetSingletonMetadataInitialization<Runtime>,
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>,
TargetOverrideTableHeader<Runtime>,
TargetMethodOverrideDescriptor<Runtime>,
TargetObjCResilientClassStubInfo<Runtime>,
TargetCanonicalSpecializedMetadatasListCount<Runtime>,
TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>>;
using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
friend TrailingObjects;
public:
using MethodDescriptor = TargetMethodDescriptor<Runtime>;
using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
using OverrideTableHeader = TargetOverrideTableHeader<Runtime>;
using MethodOverrideDescriptor = TargetMethodOverrideDescriptor<Runtime>;
using ResilientSuperclass = TargetResilientSuperclass<Runtime>;
using ForeignMetadataInitialization =
TargetForeignMetadataInitialization<Runtime>;
using SingletonMetadataInitialization =
TargetSingletonMetadataInitialization<Runtime>;
using ObjCResilientClassStubInfo =
TargetObjCResilientClassStubInfo<Runtime>;
using Metadata =
TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>;
using MetadataListCount =
TargetCanonicalSpecializedMetadatasListCount<Runtime>;
using MetadataListEntry =
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
using MetadataAccessor =
TargetRelativeDirectPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false>;
using MetadataAccessorListEntry =
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>;
using MetadataCachingOnceToken =
TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>;
using StoredPointer = typename Runtime::StoredPointer;
using StoredPointerDifference = typename Runtime::StoredPointerDifference;
using StoredSize = typename Runtime::StoredSize;
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
using TrailingGenericContextObjects::getFullGenericContextHeader;
using TrailingGenericContextObjects::getGenericParams;
using TargetTypeContextDescriptor<Runtime>::getTypeContextDescriptorFlags;
TypeReferenceKind getResilientSuperclassReferenceKind() const {
return getTypeContextDescriptorFlags()
.class_getResilientSuperclassReferenceKind();
}
/// The type of the superclass, expressed as a mangled type name that can
/// refer to the generic arguments of the subclass type.
TargetRelativeDirectPointer<Runtime, const char> SuperclassType;
union {
/// If this descriptor does not have a resilient superclass, this is the
/// negative size of metadata objects of this class (in words).
uint32_t MetadataNegativeSizeInWords;
/// If this descriptor has a resilient superclass, this is a reference
/// to a cache holding the metadata's extents.
TargetRelativeDirectPointer<Runtime,
TargetStoredClassMetadataBounds<Runtime>>
ResilientMetadataBounds;
};
union {
/// If this descriptor does not have a resilient superclass, this is the
/// positive size of metadata objects of this class (in words).
uint32_t MetadataPositiveSizeInWords;
/// Otherwise, these flags are used to do things like indicating
/// the presence of an Objective-C resilient class stub.
ExtraClassDescriptorFlags ExtraClassFlags;
};
/// The number of additional members added by this class to the class
/// metadata. This data is opaque by default to the runtime, other than
/// as exposed in other members; it's really just
/// NumImmediateMembers * sizeof(void*) bytes of data.
///
/// Whether those bytes are added before or after the address point
/// depends on areImmediateMembersNegative().
uint32_t NumImmediateMembers; // ABI: could be uint16_t?
StoredSize getImmediateMembersSize() const {
return StoredSize(NumImmediateMembers) * sizeof(StoredPointer);
}
/// Are the immediate members of the class metadata allocated at negative
/// offsets instead of positive?
bool areImmediateMembersNegative() const {
return getTypeContextDescriptorFlags().class_areImmediateMembersNegative();
}
/// The number of stored properties in the class, not including its
/// superclasses. If there is a field offset vector, this is its length.
uint32_t NumFields;
private:
/// The offset of the field offset vector for this class's stored
/// properties in its metadata, in words. 0 means there is no field offset
/// vector.
///
/// If this class has a resilient superclass, this offset is relative to
/// the size of the resilient superclass metadata. Otherwise, it is
/// absolute.
uint32_t FieldOffsetVectorOffset;
template<typename T>
using OverloadToken =
typename TrailingGenericContextObjects::template OverloadToken<T>;
using TrailingGenericContextObjects::numTrailingObjects;
size_t numTrailingObjects(OverloadToken<ResilientSuperclass>) const {
return this->hasResilientSuperclass() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
return this->hasForeignMetadataInitialization() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<SingletonMetadataInitialization>) const{
return this->hasSingletonMetadataInitialization() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
return hasVTable() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<MethodDescriptor>) const {
if (!hasVTable())
return 0;
return getVTableDescriptor()->VTableSize;
}
size_t numTrailingObjects(OverloadToken<OverrideTableHeader>) const {
return hasOverrideTable() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<MethodOverrideDescriptor>) const {
if (!hasOverrideTable())
return 0;
return getOverrideTable()->NumEntries;
}
size_t numTrailingObjects(OverloadToken<ObjCResilientClassStubInfo>) const {
return hasObjCResilientClassStub() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<MetadataListCount>) const {
return this->hasCanonicicalMetadataPrespecializations() ?
1
: 0;
}
size_t numTrailingObjects(OverloadToken<MetadataListEntry>) const {
return this->hasCanonicicalMetadataPrespecializations() ?
this->template getTrailingObjects<MetadataListCount>()->count
: 0;
}
size_t numTrailingObjects(OverloadToken<MetadataAccessorListEntry>) const {
return this->hasCanonicicalMetadataPrespecializations() ?
this->template getTrailingObjects<MetadataListCount>()->count
: 0;
}
size_t numTrailingObjects(OverloadToken<MetadataCachingOnceToken>) const {
return this->hasCanonicicalMetadataPrespecializations() ? 1 : 0;
}
public:
const TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> &
getResilientSuperclass() const {
assert(this->hasResilientSuperclass());
return this->template getTrailingObjects<ResilientSuperclass>()->Superclass;
}
const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
assert(this->hasForeignMetadataInitialization());
return *this->template getTrailingObjects<ForeignMetadataInitialization>();
}
const SingletonMetadataInitialization &getSingletonMetadataInitialization() const{
assert(this->hasSingletonMetadataInitialization());
return *this->template getTrailingObjects<SingletonMetadataInitialization>();
}
/// True if metadata records for this type have a field offset vector for
/// its stored properties.
bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
unsigned getFieldOffsetVectorOffset() const {
if (hasResilientSuperclass()) {
auto bounds = getMetadataBounds();
return (bounds.ImmediateMembersOffset / sizeof(StoredPointer)
+ FieldOffsetVectorOffset);
}
return FieldOffsetVectorOffset;
}
bool isActor() const {
return this->getTypeContextDescriptorFlags().class_isActor();
}
bool isDefaultActor() const {
return this->getTypeContextDescriptorFlags().class_isDefaultActor();
}
bool hasVTable() const {
return this->getTypeContextDescriptorFlags().class_hasVTable();
}
bool hasOverrideTable() const {
return this->getTypeContextDescriptorFlags().class_hasOverrideTable();
}
bool hasResilientSuperclass() const {
return this->getTypeContextDescriptorFlags().class_hasResilientSuperclass();
}
const VTableDescriptorHeader *getVTableDescriptor() const {
if (!hasVTable())
return nullptr;
return this->template getTrailingObjects<VTableDescriptorHeader>();
}
llvm::ArrayRef<MethodDescriptor> getMethodDescriptors() const {
if (!hasVTable())
return {};
return {this->template getTrailingObjects<MethodDescriptor>(),
numTrailingObjects(OverloadToken<MethodDescriptor>{})};
}
const OverrideTableHeader *getOverrideTable() const {
if (!hasOverrideTable())
return nullptr;
return this->template getTrailingObjects<OverrideTableHeader>();
}
llvm::ArrayRef<MethodOverrideDescriptor> getMethodOverrideDescriptors() const {
if (!hasOverrideTable())
return {};
return {this->template getTrailingObjects<MethodOverrideDescriptor>(),
numTrailingObjects(OverloadToken<MethodOverrideDescriptor>{})};
}
/// Return the bounds of this class's metadata.
TargetClassMetadataBounds<Runtime> getMetadataBounds() const {
if (!hasResilientSuperclass())
return getNonResilientMetadataBounds();
// This lookup works by ADL and will intentionally fail for
// non-InProcess instantiations.
return getResilientMetadataBounds(this);
}
/// Given that this class is known to not have a resilient superclass
/// return its metadata bounds.
TargetClassMetadataBounds<Runtime> getNonResilientMetadataBounds() const {
return { getNonResilientImmediateMembersOffset()
* StoredPointerDifference(sizeof(void*)),
MetadataNegativeSizeInWords,
MetadataPositiveSizeInWords };
}
/// Return the offset of the start of generic arguments in the nominal
/// type's metadata. The returned value is measured in words.
int32_t getGenericArgumentOffset() const {
if (!hasResilientSuperclass())
return getNonResilientGenericArgumentOffset();
// This lookup works by ADL and will intentionally fail for
// non-InProcess instantiations.
return getResilientImmediateMembersOffset(this);
}
/// Given that this class is known to not have a resilient superclass,
/// return the offset of its generic arguments in words.
int32_t getNonResilientGenericArgumentOffset() const {
return getNonResilientImmediateMembersOffset();
}
/// Given that this class is known to not have a resilient superclass,
/// return the offset of its immediate members in words.
int32_t getNonResilientImmediateMembersOffset() const {
assert(!hasResilientSuperclass());
return areImmediateMembersNegative()
? -int32_t(MetadataNegativeSizeInWords)
: int32_t(MetadataPositiveSizeInWords - NumImmediateMembers);
}
void *getMethod(unsigned i) const {
assert(hasVTable()
&& i < numTrailingObjects(OverloadToken<MethodDescriptor>{}));
return getMethodDescriptors()[i].Impl.get();
}
/// Whether this context descriptor references an Objective-C resilient
/// class stub. See the above description of TargetObjCResilientClassStubInfo
/// for details.
bool hasObjCResilientClassStub() const {
if (!hasResilientSuperclass())
return false;
return ExtraClassFlags.hasObjCResilientClassStub();
}
const void *getObjCResilientClassStub() const {
if (!hasObjCResilientClassStub())
return nullptr;
return this->template getTrailingObjects<ObjCResilientClassStubInfo>()
->Stub.get();
}
llvm::ArrayRef<Metadata> getCanonicicalMetadataPrespecializations() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return {};
}
auto *listCount = this->template getTrailingObjects<MetadataListCount>();
auto *list = this->template getTrailingObjects<MetadataListEntry>();
return llvm::ArrayRef<Metadata>(
reinterpret_cast<const Metadata *>(list),
listCount->count
);
}
llvm::ArrayRef<MetadataAccessor> getCanonicalMetadataPrespecializationAccessors() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return {};
}
auto *listCount = this->template getTrailingObjects<MetadataListCount>();
auto *list = this->template getTrailingObjects<MetadataAccessorListEntry>();
return llvm::ArrayRef<MetadataAccessor>(
reinterpret_cast<const MetadataAccessor *>(list),
listCount->count
);
}
swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const {
if (!this->hasCanonicicalMetadataPrespecializations()) {
return nullptr;
}
auto box = this->template getTrailingObjects<MetadataCachingOnceToken>();
return box->token.get();
}
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Class;
}
};
using ClassDescriptor = TargetClassDescriptor<InProcess>;
TargetClassDescriptor中的属性:
var superClassType: TargetRelativeDirectPointer<Runtime, const char>;
// 父类类型
var metadataNegativeSizeInWords: UInt32;
var metadataPositiveSizeInWords: UInt32;
var numImmediateMembers: UInt32;
var numFields: UInt32;
var fieldOffsetVectorOffset: UInt32;
// 每一个属性值距离当前实例对象地址的偏移量
注意:TargetRelativeDirectPointer<Runtime, const char>
到底是什么?
它是一个相对地址信息,并且存储的是偏移量。(ps: swift中在数据结构存储数据都是通过偏移量去访问内存地址)
TargetRelativeDirectPointer
的源码声明:
// TargetRelativeDirectPointer其实是RelativeDirectPointer的别名
template <typename Runtime, typename Pointee, bool Nullable = true>
using TargetRelativeDirectPointer
= typename Runtime::template RelativeDirectPointer<Pointee, Nullable>;
/// A direct relative reference to an object that is not a function pointer.
template <typename T, bool Nullable, typename Offset>
class RelativeDirectPointer<T, Nullable, Offset,
typename std::enable_if<!std::is_function<T>::value>::type>
: private RelativeDirectPointerImpl<T, Nullable, Offset>
{
using super = RelativeDirectPointerImpl<T, Nullable, Offset>;
public:
using super::get;
using super::super;
RelativeDirectPointer &operator=(T *absolute) & {
super::operator=(absolute);
return *this;
}
operator typename super::PointerTy() const & {
return this->get();
}
const typename super::ValueTy *operator->() const & {
return this->get();
}
const typename super::ValueTy* getRelative(void *base) const & {
return this->super::getRelative(base);
}
using super::isNull;
};
这个类的定义还是⽐较简洁的,其中 T
就是我们进来的类型, Offset
就是 int32_t
的类型,这⾥的源码我就不带着⼤家⼀点点分析了,在 Swift 中引⽤⼀个 Object 有两种情况:
a.当前 Object
的引⽤是⼀个 absolute
指针,就像我们的对象⼀样:
b.当前指针存储的是相对引⽤,相对引⽤指的是当前引⽤的内存地址到当前对象的内存地址的距离:
以上,我仿照这个思路把当前TargetRelativeDirectPointer
数据结构还原出来:
// 相对地址信息 - 存储的是偏移量
struct TargetRelativeDirectPointer<Pointee> {
var offset: Int32
mutating func getmeasureRelativeOffset() -> UnsafeMutablePointer<Pointee>{
let offset = self.offset
return withUnsafePointer(to: &self) { p in
/*
获得self,变为raw,然后+offset
- UnsafeRawPointer(p) 表示this
- advanced(by: numericCast(offset) 表示移动的步长,即offset
- assumingMemoryBound(to: T.self) 表示假定类型是T,即自己指定的类型
- UnsafeMutablePointer(mutating:) 表示返回的指针类型
*/
return UnsafeMutablePointer(mutating: UnsafeRawPointer(p).advanced(by: numericCast(offset)).assumingMemoryBound(to: Pointee.self))
}
}
}
再回头看TargetClassDescriptor
是继承自TargetTypeContextDescriptor
的。
TargetTypeContextDescriptor
的源码声明:
template <typename Runtime>
class TargetTypeContextDescriptor
: public TargetContextDescriptor<Runtime> {
public:
/// The name of the type.
TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
/// A pointer to the metadata access function for this type.
///
/// The function type here is a stand-in. You should use getAccessFunction()
/// to wrap the function pointer in an accessor that uses the proper calling
/// convention for a given number of arguments.
TargetRelativeDirectPointer<Runtime, MetadataResponse(...),
/*Nullable*/ true> AccessFunctionPtr;
/// A pointer to the field descriptor for the type, if any.
TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor,
/*nullable*/ true> Fields;
bool isReflectable() const { return (bool)Fields; }
MetadataAccessFunction getAccessFunction() const {
return MetadataAccessFunction(AccessFunctionPtr.get());
}
TypeContextDescriptorFlags getTypeContextDescriptorFlags() const {
return TypeContextDescriptorFlags(this->Flags.getKindSpecificFlags());
}
/// Return the kind of metadata initialization required by this type.
/// Note that this is only meaningful for non-generic types.
TypeContextDescriptorFlags::MetadataInitializationKind
getMetadataInitialization() const {
return getTypeContextDescriptorFlags().getMetadataInitialization();
}
/// Does this type have non-trivial "singleton" metadata initialization?
///
/// The type of the initialization-control structure differs by subclass,
/// so it doesn't appear here.
bool hasSingletonMetadataInitialization() const {
return getTypeContextDescriptorFlags().hasSingletonMetadataInitialization();
}
/// Does this type have "foreign" metadata initialiation?
bool hasForeignMetadataInitialization() const {
return getTypeContextDescriptorFlags().hasForeignMetadataInitialization();
}
bool hasCanonicicalMetadataPrespecializations() const {
return getTypeContextDescriptorFlags().hasCanonicalMetadataPrespecializations();
}
/// Given that this type has foreign metadata initialization, return the
/// control structure for it.
const TargetForeignMetadataInitialization<Runtime> &
getForeignMetadataInitialization() const;
const TargetSingletonMetadataInitialization<Runtime> &
getSingletonMetadataInitialization() const;
const TargetTypeGenericContextDescriptorHeader<Runtime> &
getFullGenericContextHeader() const;
const TargetGenericContextDescriptorHeader<Runtime> &
getGenericContextHeader() const {
return getFullGenericContextHeader();
}
llvm::ArrayRef<GenericParamDescriptor> getGenericParams() const;
/// Return the offset of the start of generic arguments in the nominal
/// type's metadata. The returned value is measured in sizeof(StoredPointer).
int32_t getGenericArgumentOffset() const;
constexpr inline auto
getNameOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
}
/// Return the start of the generic arguments array in the nominal
/// type's metadata. The returned value is measured in sizeof(StoredPointer).
const TargetMetadata<Runtime> * const *getGenericArguments(
const TargetMetadata<Runtime> *metadata) const {
auto offset = getGenericArgumentOffset();
auto words =
reinterpret_cast<const TargetMetadata<Runtime> * const *>(metadata);
return words + offset;
}
const llvm::ArrayRef<TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>, /*Nullable*/ false>>
getCanonicicalMetadataPrespecializations() const;
swift_once_t *getCanonicalMetadataPrespecializationCachingOnceToken() const;
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() >= ContextDescriptorKind::Type_First
&& cd->getKind() <= ContextDescriptorKind::Type_Last;
}
};
TargetTypeContextDescriptor中的属性:
var name: TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false>;
// class/struct/enum 的名称
var accessFunctionPointer: TargetRelativeDirectPointer<Runtime, MetadataResponse(...), /*Nullable*/ true>;
var fieldDescriptor: TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor, /*nullable*/ true>;
// 属性描述器
这三个属性都是TargetRelativeDirectPointer类型的
TargetTypeContextDescriptor
是继承自TargetContextDescriptor
。
TargetContextDescriptor
的源码声明:
// Base class for all context descriptors.
template<typename Runtime>
struct TargetContextDescriptor {
/// Flags describing the context, including its kind and format version.
ContextDescriptorFlags Flags;
/// The parent context, or null if this is a top-level context.
TargetRelativeContextPointer<Runtime> Parent;
bool isGeneric() const { return Flags.isGeneric(); }
bool isUnique() const { return Flags.isUnique(); }
ContextDescriptorKind getKind() const { return Flags.getKind(); }
/// Get the generic context information for this context, or null if the
/// context is not generic.
const TargetGenericContext<Runtime> *getGenericContext() const;
/// Get the module context for this context.
const TargetModuleContextDescriptor<Runtime> *getModuleContext() const;
/// Is this context part of a C-imported module?
bool isCImportedContext() const;
unsigned getNumGenericParams() const {
auto *genericContext = getGenericContext();
return genericContext
? genericContext->getGenericContextHeader().NumParams
: 0;
}
constexpr inline auto
getParentOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Parent);
}
#ifndef NDEBUG
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
"only for use in the debugger");
#endif
private:
TargetContextDescriptor(const TargetContextDescriptor &) = delete;
TargetContextDescriptor(TargetContextDescriptor &&) = delete;
TargetContextDescriptor &operator=(const TargetContextDescriptor &) = delete;
TargetContextDescriptor &operator=(TargetContextDescriptor &&) = delete;
};
TargetContextDescriptor中的属性:
var flags: UInt32
var parent: TargetRelativeContextPointer<Runtime>
TargetClassDescriptor的总结:
a.TargetClassDescriptor
继承链关系:
TargetClassDescriptor
-->TargetTypeContextDescriptor
--> TargetContextDescriptor
b.TargetClassDescriptor的数据结构:
// 类描述器
struct TargetClassDescriptor{
var flags: UInt32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar> // class/struct/enum 的名称
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor> // 属性描述器
var superClassType: TargetRelativeDirectPointer<CChar> // 父类类型
var metadataNegativeSizeInWords: UInt32
var metadataPositiveSizeInWords: UInt32
var numImmediateMembers: UInt32
var numFields: UInt32
var fieldOffsetVectorOffset: UInt32 // 每一个属性值距离当前实例对象地址的偏移量
//var Offset: UInt32
// var size: UInt32
// V-Table (methods)
}
1.3 FieldDescriptor属性描述器(包含了属性信息)
FieldDescriptor
的源码声明:
// Field descriptors contain a collection of field records for a single
// class, struct or enum declaration.
class FieldDescriptor {
const FieldRecord *getFieldRecordBuffer() const {
return reinterpret_cast<const FieldRecord *>(this + 1);
}
public:
const RelativeDirectPointer<const char> MangledTypeName;
const RelativeDirectPointer<const char> Superclass;
FieldDescriptor() = delete;
const FieldDescriptorKind Kind;
const uint16_t FieldRecordSize;
const uint32_t NumFields;
using const_iterator = FieldRecordIterator;
bool isEnum() const {
return (Kind == FieldDescriptorKind::Enum ||
Kind == FieldDescriptorKind::MultiPayloadEnum);
}
bool isClass() const {
return (Kind == FieldDescriptorKind::Class ||
Kind == FieldDescriptorKind::ObjCClass);
}
bool isProtocol() const {
return (Kind == FieldDescriptorKind::Protocol ||
Kind == FieldDescriptorKind::ClassProtocol ||
Kind == FieldDescriptorKind::ObjCProtocol);
}
bool isStruct() const {
return Kind == FieldDescriptorKind::Struct;
}
const_iterator begin() const {
auto Begin = getFieldRecordBuffer();
auto End = Begin + NumFields;
return const_iterator { Begin, End };
}
const_iterator end() const {
auto Begin = getFieldRecordBuffer();
auto End = Begin + NumFields;
return const_iterator { End, End };
}
llvm::ArrayRef<FieldRecord> getFields() const {
return {getFieldRecordBuffer(), NumFields};
}
bool hasMangledTypeName() const {
return MangledTypeName;
}
StringRef getMangledTypeName() const {
return Demangle::makeSymbolicMangledNameStringRef(MangledTypeName.get());
}
bool hasSuperclass() const {
return Superclass;
}
StringRef getSuperclass() const {
return Demangle::makeSymbolicMangledNameStringRef(Superclass.get());
}
};
FieldDescriptor包含的属性:
var mangledTypeName: TargetRelativeDirectPointer<CChar>;
// 混写类型名称
var superclass: TargetRelativeDirectPointer<CChar>;
var kind: UInt16;
var fieldRecordSize: UInt16;
// 属性的size
var numFields: UInt32;
// 属性个数
但其实FieldDescriptor的属性是包含了一个属性列表的,因为源码声明里面可以看出:
FieldDescriptor
数据结构可以还原成下面这样:
// 属性描述器
struct FieldDescriptor {
var mangledTypeName: TargetRelativeDirectPointer<CChar>
var superclass: TargetRelativeDirectPointer<CChar>
var kind: UInt16
var fieldRecordSize: UInt16
var numFields: UInt32 // 属性个数
var fields: FiledRecordBuffer<FieldRecord> // 属性列表
}
struct FiledRecordBuffer<Element>{
var element: Element
mutating func buffer(n: Int) -> UnsafeBufferPointer<Element> {
return withUnsafePointer(to: &self) {
let ptr = $0.withMemoryRebound(to: Element.self, capacity: 1) { start in
return start
}
return UnsafeBufferPointer(start: ptr, count: n)
}
}
mutating func index(of i: Int) -> UnsafeMutablePointer<Element> {
return withUnsafePointer(to: &self) {
return UnsafeMutablePointer(mutating: UnsafeRawPointer($0).assumingMemoryBound(to: Element.self).advanced(by: i))
}
}
}
接下来还需要还原FieldRecord
的数据结构,先来看看
FieldRecord
的源码声明:
class FieldRecord {
const FieldRecordFlags Flags;
public:
const RelativeDirectPointer<const char> MangledTypeName;
const RelativeDirectPointer<const char> FieldName;
FieldRecord() = delete;
bool hasMangledTypeName() const {
return MangledTypeName;
}
StringRef getMangledTypeName() const {
return Demangle::makeSymbolicMangledNameStringRef(MangledTypeName.get());
}
StringRef getFieldName() const {
return FieldName.get();
}
bool isIndirectCase() const {
return Flags.isIndirectCase();
}
bool isVar() const {
return Flags.isVar();
}
};
很简单地就能还原出,FieldRecord
的数据结构:
// 属性
struct FieldRecord {
var flags: Int32
var mangledTypeName: TargetRelativeDirectPointer<CChar> // 属性的类型
var fieldName: TargetRelativeDirectPointer<UInt8> // 属性的名称
}
2、列出TargetClassMetadata的完整数据结构
2.1 类 Metadata
// 类 Metadata
struct TargetClassMetadata {
var kind: Int
var superClass: Any.Type
var cacheData: (Int, Int)
var data: Int
var classFlags: Int32 // swift特有的标志
var instanceAddressPoint: UInt32 // 实例独享内存首地址
var instanceSize: UInt32 // 实例对象内存大小
var instanceAlignmentMask: UInt16 // 实例对象内存对齐方式
var reserved: UInt16 // 运行时保留字段
var classSize: UInt32 // 类的内存大小
var classAddressPoint: UInt32 //类的内存首地址
var typeDescriptor: UnsafeMutablePointer<TargetClassDescriptor> // 类型描述器
var iVarDestroyer: UnsafeRawPointer // 实例销毁器
}
// 类描述器
struct TargetClassDescriptor{
var flags: UInt32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar> // class/struct/enum 的名称
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor> // 属性描述器
var superClassType: TargetRelativeDirectPointer<CChar> // 父类类型
var metadataNegativeSizeInWords: UInt32
var metadataPositiveSizeInWords: UInt32
var numImmediateMembers: UInt32
var numFields: UInt32
var fieldOffsetVectorOffset: UInt32 // 每一个属性值距离当前实例对象地址的偏移量
//var Offset: UInt32
// var size: UInt32
// V-Table (methods)
func getFieldOffsets(_ metadata: UnsafeRawPointer) -> UnsafePointer<Int> {
return metadata.assumingMemoryBound(to: Int.self).advanced(by: numericCast(self.fieldOffsetVectorOffset))
}
// 泛型参数的偏移量 - 源码里是经过一系列计算 而HandyJSON直接给2
var genericArgumentOffset: Int { return 2 }
}
2.2 通用class/struct/enum类-相对地址信息
// 相对地址信息 - 存储的是偏移量
struct TargetRelativeDirectPointer<Pointee> {
var offset: Int32
mutating func getmeasureRelativeOffset() -> UnsafeMutablePointer<Pointee>{
let offset = self.offset
return withUnsafePointer(to: &self) { p in
/*
获得self,变为raw,然后+offset
- UnsafeRawPointer(p) 表示this
- advanced(by: numericCast(offset) 表示移动的步长,即offset
- assumingMemoryBound(to: T.self) 表示假定类型是T,即自己指定的类型
- UnsafeMutablePointer(mutating:) 表示返回的指针类型
*/
return UnsafeMutablePointer(mutating: UnsafeRawPointer(p).advanced(by: numericCast(offset)).assumingMemoryBound(to: Pointee.self))
}
}
}
2.3 通用class/struct/enum类 - 属性信息
// 属性描述器
struct FieldDescriptor {
var mangledTypeName: TargetRelativeDirectPointer<CChar>
var superclass: TargetRelativeDirectPointer<CChar>
var kind: UInt16
var fieldRecordSize: UInt16
var numFields: UInt32 // 属性个数
var fields: FiledRecordBuffer<FieldRecord> // 属性列表
}
// 属性
struct FieldRecord {
var flags: Int32
var mangledTypeName: TargetRelativeDirectPointer<CChar> // 属性的类型
var fieldName: TargetRelativeDirectPointer<UInt8> // 属性的名称
}
struct FiledRecordBuffer<Element>{
var element: Element
mutating func buffer(n: Int) -> UnsafeBufferPointer<Element> {
return withUnsafePointer(to: &self) {
let ptr = $0.withMemoryRebound(to: Element.self, capacity: 1) { start in
return start
}
return UnsafeBufferPointer(start: ptr, count: n)
}
}
mutating func index(of i: Int) -> UnsafeMutablePointer<Element> {
return withUnsafePointer(to: &self) {
return UnsafeMutablePointer(mutating: UnsafeRawPointer($0).assumingMemoryBound(to: Element.self).advanced(by: i))
}
}
}
3、验证TargetClassMetadata数据结构
class Person {
var name = "安老师"
var age = 18
}
let person = Person() // 创建一个Person实例
var pClazz = Person.self // 拿到类对象
// 拿到ClassMetadata指针
let classMetadata_ptr = unsafeBitCast(pClazz as Any.Type, to: UnsafeMutablePointer<TargetClassMetadata>.self)
unsafeBitCast
的作用:按位转换成指针 UnsafeMutablePointer<TargetClassMetadata>
,就可以对指针进行操作。
// 取出类描述器里的name的相对偏移量
let name_ptr = classMetadata_ptr.pointee.typeDescriptor.pointee.name.getmeasureRelativeOffset()
print(String(cString: name_ptr)) // Person
ps:classMetadata_ptr.pointee.typeDescriptor.pointee.name
的类型是这个相对地址信息,上面说过它存储的是偏移量。
// 属性个数
let numFileds = classMetadata_ptr.pointee.typeDescriptor.pointee.numFields
print(numFileds) // 2
下面我要输出person实例里的所有属性值:
// 拿到首个属性偏移地址信息
let offsets = classMetadata_ptr.pointee.typeDescriptor.pointee.getFieldOffsets(UnsafeRawPointer(classMetadata_ptr).assumingMemoryBound(to: Int.self))
ps: 在TargetClassDescriptor
里有一个属性叫fieldOffsetVectorOffset
,它存储的是每一个属性值距离当前实例对象地址的偏移量;从classMetadata_ptr
指针偏移fieldOffsetVectorOffset
。
for i in 0..<numFileds {
// 获取属性名
let fieldName = classMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee.fieldName.getmeasureRelativeOffset()
print("fieldName:\(String(cString: fieldName))")
// 混写过的类型名称
let mangledTypeName = classMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee.mangledTypeName.getmeasureRelativeOffset()
print("mangledTypeName:\(String(cString: mangledTypeName))")
// 泛型向量
let genericVector = UnsafeRawPointer(classMetadata_ptr).advanced(by: classMetadata_ptr.pointee.typeDescriptor.pointee.genericArgumentOffset * MemoryLayout<UnsafeRawPointer>.size).assumingMemoryBound(to: Any.Type.self)
// 获取属性类型:
// 新建C文件,声明这个函数 (CAPI.h)
let fieldType = swift_getTypeByMangledNameInContext(mangledTypeName,
256,
UnsafeRawPointer(classMetadata_ptr.pointee.typeDescriptor),
UnsafeRawPointer(genericVector)?.assumingMemoryBound(to: Optional<UnsafeRawPointer>.self))
let realType = unsafeBitCast(fieldType, to: Any.Type.self)
print("fieldType: \(realType)")
// 狡猾地把真实类型信息,保存到protocol的metadata,再通过Self.self获取真实类型
let protocolType = getBitCast(type: realType)
// 对象的起始地址
let instanceAddress = Unmanaged.passUnretained(person).toOpaque() // Teacher()的起始地址
// 每个属性的偏移量
let fieldOffset = offsets[Int(i)]
// 获取属性的值
let value = protocolType.get(from: instanceAddress.advanced(by: fieldOffset))
print("fieldValue: \(value)")
/*
// HandyJSON 的方式 通过函数映射 (CApi.swift)
let fieldType = _getTypeByMangledNameInContext(mangledTypeName,
256,
genericContext: UnsafeRawPointer(classMetadata_ptr.pointee.typeDescriptor),
genericArguments: UnsafeRawPointer(genericVector)?.assumingMemoryBound(to: Optional<UnsafeRawPointer>.self))
print(fieldType as Any)
*/
print("==================")
}
for...in打印结果:
上面还有一部分代码没粘贴上来,后面会粘出来的,先一步步分析。
分析一:获取属性名
// 获取属性名
let fieldName = classMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee.fieldName.getmeasureRelativeOffset()
1.classMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee
在TargetClassDescriptor中的fieldDescriptor是相对地址信息类型,通过调用getmeasureRelativeOffset()来做地址偏移,才能获取到真正的fieldDescriptor对象
2.classMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee
拿到真正的fieldDescriptor对象后,可以找到fields属性列表,可以发现它是一个FiledRecordBuffer<FieldRecord>
类型,通过源码可知属性列表是一片连续的内存空间,需要逐个拿出对应地址的field指针;再.pointee得到FieldRecord
实例对象,才能继续对FieldRecord
实例的属性进行访问。
分析二:获取属性类型
-
swift_getTypeByMangledNameInContext
和_getTypeByMangledNameInContext
的作用是讲混写后的属性类型名还原,调用的是同一个C标准库里的函数,只是可以通过两种方式去调用:
// 新建C文件,声明这个函数 (CAPI.h)
let fieldType = swift_getTypeByMangledNameInContext(mangledTypeName,
256,
UnsafeRawPointer(classMetadata_ptr.pointee.typeDescriptor),
UnsafeRawPointer(genericVector)?.assumingMemoryBound(to: Optional<UnsafeRawPointer>.self))
/*
// HandyJSON 的方式 通过函数映射 (CApi.swift)
let fieldType = _getTypeByMangledNameInContext(mangledTypeName,
256,
genericContext: UnsafeRawPointer(classMetadata_ptr.pointee.typeDescriptor),
genericArguments: UnsafeRawPointer(genericVector)?.assumingMemoryBound(to: Optional<UnsafeRawPointer>.self))
print(fieldType as Any)
*/
let realType = unsafeBitCast(fieldType, to: Any.Type.self)
print("fieldType: \(realType)")
方式一:创建C文件,在.h文件下声明这个函数即可:
方式二:通过swift函数映射的方式@_silgen_name
:
2.注意fieldType的类型依然是不确定类型UnsafeRawPointer
,但我们程序依旧不知道它是什么类型,所以只能转换成 Any.Type
类型
let realType = unsafeBitCast(fieldType, to: Any.Type.self)
3.getBitCast
其实是上面代码缺失部分之一
// 狡猾地把真实类型信息,保存到protocol的metadata,再通过Self.self获取真实类型
let protocolType = getBitCast(type: realType)
getBitCast
函数的实现:(狡猾地把真实类型信息,保存到protocol的metadata
,再通过Self.self
获取真实类型)
// 将一个Any.Type转换成BrigeProtocol
func getBitCast(type: Any.Type) -> BrigeProtocol.Type {
let container = ProtocolMetadata(type: type, witness: 0)
let bitCast = unsafeBitCast(container, to: BrigeProtocol.Type.self) // 将struct保存到Protocol的Metadata
return bitCast
}
BrigeProtocol
的声明:
protocol BrigeProtocol {}
extension BrigeProtocol {
// 获取真实类型信息的值
static func get(from pointer: UnsafeRawPointer) -> Any {
return pointer.assumingMemoryBound(to: Self.self).pointee
}
}
// 协议的Metadata
// 协议见证表
struct ProtocolMetadata { // TargetWitnessTable
let type: Any.Type // 真实类型
let witness: Int
}
关于协议相关的在往后的章节会讲到,不在本章节过多细说了。
分析三:获取属性的值
// 对象的起始地址
let instanceAddress = Unmanaged.passUnretained(person).toOpaque() // Teacher()的起始地址
// 每个属性的偏移量
let fieldOffset = offsets[Int(i)]
// 获取属性的值
let value = protocolType.get(from: instanceAddress.advanced(by: fieldOffset))
print("fieldValue: \(value)")
为什么protocolType.get(from: instanceAddress.advanced(by: fieldOffset))
能获取到属性的值呢?
首先获取某个对象的属性值,需要拿到对象的首地址和属性对应的偏移量,然后在首地址的基础上偏移,再对其真实类型的绑定。
其中Self.self
就是通过获取真实类型的过程。
以上就是TargetClassMetadata
数据结构的全部内容。
二、TargetStructMetadata
1、TargetStructMetadata源码分析
1.1 从源码分析出TargetStructMetadata的数据结构
TargetStructMetadata
的源码声明:
/// The structure of type metadata for structs.
template <typename Runtime>
struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using TargetValueMetadata<Runtime>::TargetValueMetadata;
const TargetStructDescriptor<Runtime> *getDescription() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this->Description);
}
// The first trailing field of struct metadata is always the generic
// argument array.
/// Get a pointer to the field offset vector, if present, or null.
const uint32_t *getFieldOffsets() const {
auto offset = getDescription()->FieldOffsetVectorOffset;
if (offset == 0)
return nullptr;
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const uint32_t *>(asWords + offset);
}
bool isStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isStaticSpecialization();
}
bool isCanonicalStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isCanonicalStaticSpecialization();
}
const MetadataTrailingFlags *getTrailingFlags() const {
auto description = getDescription();
auto flags = description->getFullGenericContextHeader()
.DefaultInstantiationPattern->PatternFlags;
if (!flags.hasTrailingFlags())
return nullptr;
auto fieldOffset = description->FieldOffsetVectorOffset;
auto offset =
fieldOffset +
// Pad to the nearest pointer.
((description->NumFields * sizeof(uint32_t) + sizeof(void *) - 1) /
sizeof(void *));
auto asWords = reinterpret_cast<const void *const *>(this);
return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
}
static constexpr int32_t getGenericArgumentOffset() {
return sizeof(TargetStructMetadata<Runtime>) / sizeof(StoredPointer);
}
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct;
}
};
using StructMetadata = TargetStructMetadata<InProcess>;
TargetStructMetadata
没有啥的属性,看看它父类TargetValueMetadata
。
TargetValueMetadata
的源码声明:
/// The common structure of metadata for structs and enums.
template <typename Runtime>
struct TargetValueMetadata : public TargetMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
TargetValueMetadata(MetadataKind Kind,
const TargetTypeContextDescriptor<Runtime> *description)
: TargetMetadata<Runtime>(Kind), Description(description) {}
/// An out-of-line description of the type.
TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
|| metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
}
ConstTargetMetadataPointer<Runtime, TargetValueTypeDescriptor>
getDescription() const {
return Description;
}
typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
return Description;
}
};
using ValueMetadata = TargetValueMetadata<InProcess>;
TargetValueMetadata
有一个Description
的属性;
/// An out-of-line description of the type.
TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
TargetValueMetadata
继承自TargetMetadata
,上面我已经粘贴过了它的源码,它只有一个 Kind
属性。
TargetStructMetadata
的数据结构:
struct TargetStructMetadata {
var Kind: Int
// 结构体描述器 (TargetStructDescriptor是解析后的自定义的,它可以替代TargetValueTypeDescriptor)
var typeDescriptor: UnsafeMutablePointer<TargetStructDescriptor>
}
接下来看看结构体描述器TargetValueTypeDescriptor
到底是什么
1.2 从源码分析出TargetStructDescriptor(自定义)的数据结构
TargetValueTypeDescriptor
的源码分析:
template <typename Runtime>
class TargetValueTypeDescriptor
: public TargetTypeContextDescriptor<Runtime> {
public:
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Struct ||
cd->getKind() == ContextDescriptorKind::Enum;
}
};
using ValueTypeDescriptor = TargetValueTypeDescriptor<InProcess>;
TargetValueTypeDescriptor
继承自TargetTypeContextDescriptor
; TargetTypeContextDescriptor和FieldDescriptor的源码在第一部分就有自行看看。
得出TargetStructDescriptor
的数据结构:
struct TargetStructDescriptor {
var flags: UInt32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar> // 类名
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor> // 属性描述器
var numFields: UInt32
var fieldOffsetVectorOffset: UInt32 // 每一个属性值距离当前实例对象地址的偏移量
// 泛型参数的偏移量 - 源码里是经过一系列计算 而HandyJSON直接给2
var genericArgumentOffset: Int { return 2 }
}
2、验证TargetStructMetadata数据结构
struct Person {
var age:Int = 18
let name:String = "安安"
let sex = false
var address = "ZH-1201"
var birthday = ("1995", "12", "26")
}
var person = Person()
/**
var personType = Person.self
let person_ptr = withUnsafePointer(to: &personType) { ptr in
UnsafeRawPointer(ptr).bindMemory(to: UnsafeMutablePointer<TargetStructMetadata>.self, capacity: 1)
}.pointee
print(person_ptr.pointee.typeDescriptor.pointee.numFields)
*/
let pointer = unsafeBitCast(Person.self as Any.Type, to: UnsafeMutablePointer<TargetStructMetadata>.self)
let numFileds = pointer.pointee.typeDescriptor.pointee.numFields
print("numFileds: \(numFileds)")
var bufferPtr = UnsafeBufferPointer(start: UnsafeRawPointer(UnsafeRawPointer(pointer).assumingMemoryBound(to: Int.self).advanced(by: numericCast(pointer.pointee.typeDescriptor.pointee.fieldOffsetVectorOffset))).assumingMemoryBound(to: Int32.self), count: Int(pointer.pointee.typeDescriptor.pointee.numFields))
for i in 0..<numFileds {
let filedName = pointer.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee.fieldName.getmeasureRelativeOffset()
print("filedName: \(String(cString: filedName))")
// 混写过的mangleTypeName
let mangledTypeName = pointer.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset().pointee.fields.index(of: Int(i)).pointee.mangledTypeName.getmeasureRelativeOffset()
// 泛型向量
let genericVector = UnsafeRawPointer(pointer).advanced(by: pointer.pointee.typeDescriptor.pointee.genericArgumentOffset * MemoryLayout<UnsafeRawPointer>.size).assumingMemoryBound(to: Any.Type.self)
// 获取属性类型:
// 新建C文件,声明这个函数 (CAPI.h)
let fieldType = swift_getTypeByMangledNameInContext(mangledTypeName, 256, UnsafeRawPointer(pointer.pointee.typeDescriptor), UnsafeRawPointer(genericVector)?.assumingMemoryBound(to: Optional<UnsafeRawPointer>.self))
// 属性类型 (Any包裹了真实类型)
let type = unsafeBitCast(fieldType, to: Any.Type.self)
print("filedType: \(type)")
// 对象的起始地址
let instanceAddress = withUnsafeMutablePointer(to: &person){$0} // Person()的起始地址
// 每个属性的偏移量
let fieldOffset = bufferPtr[Int(i)]
// 真实属性类型
let realType = getBitCast(type: type) // 狡猾地把真实类型信息,保存到protocol的metadata,再通过Self.self获取真实类型
let value = realType.get(from: UnsafeRawPointer(UnsafeRawPointer(instanceAddress).advanced(by: numericCast(fieldOffset))))
print("filedValue: \(value)")
print("========================================")
}
来看看打印结果:
上面在分析类的时候就分析过了,就不分析了。
在文章的最后给出TargetEnumMetadata
的数据结构:
// 枚举Metadata
struct TargetEnumMetadata {
var kind: Int
var typeDescriptor: UnsafeMutablePointer<TargetEnumDescriptor>
}
// 枚举描述器
struct TargetEnumDescriptor {
var flags: UInt32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar>
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor>
var NumPayloadCasesAndPayloadSizeOffset: UInt32
var NumEmptyCases: UInt32
}