Swift编译流程及SIL分析
1、iOS开发的语⾔不管是 OC 还是 Swift 后端都是通过 LLVM 进⾏编译的:
- Object-C 通过 前端编译器 Clang + 后端编译器 LLVM --> .o
- Swift 通过 前端编译器 Swift + 后端编译器 LLVM --> .o
在此过程中:
-
- OC 通过 Clang 编译器编译成IR,然后再⽣成可执⾏⽂件.o(这⾥也就是我们的机器码) 。
- Swift 通过 Swift 编译器 编译成IR,然后再⽣成可执⾏⽂件 .o
再具体些:
- 在OC中文件的编译流程可以通过如下方式获得
$ clang -ccc-print-phases main.m
+- 0: input, "main.m", objective-c
+- 1: preprocessor, {0}, objective-c-cpp-output//预处理
+- 2: compiler, {1}, ir //编译生成IR
+- 3: backend, {2}, assembler //汇编器生成汇编代码
+- 4: assembler, {3}, object //生成机器码
+- 5: linker, {4}, image //链接
6: bind-arch, "x86_64", {5}, image //生成可执行文件
- 而 swift ⽂件的编译过程都经历了如下步骤:
- Parsing(解析器):Parsing是一个递归下降解析器在 lib / Parse中实现,带有集成的手动编码词法分析器。解析器负责生成没有任何语义或类型信息的抽象语法树(AST),并针对输入源的语法问题发出警告或错误。
- Semantic analysis: 语义分析(在 lib / Sema中实现)负责获取已解析的AST,并将其转换为格式正确的、经过类型检查的AST,并在源码中发出警告或错误提示。语义分析包括类型推断,如果成功,则表明生成的经过类型检查的AST代码是安全的。
- Clang importer:Clang导入器(在 lib / ClangImporter中实现)导入Clang模块 并将它们导出的C或者OC API映射到其相应的Swift API中。可以通过语义分析来引用生成的导入的AST。
- SIL Generation: Swift中间语言(SIL)是特定于Swift的高级中间语言,适用于Swift代码的进一步分析和优化。SIL生成阶段(在 lib / SILGen中实现)将经过类型检查的AST降低为所谓的 Raw SIL。SIL的设计在docs / SIL.rst中进行了描述 。
- SIL Optimizations:SIL优化(在 lib / Analysis,lib / ARC,lib / LoopTransforms和 lib / Transforms中实现)对程序执行了其他高级,特定于Swift的优化,包括(例如)自动引用计数优化,去虚拟化和通用专业化。
- Canonical SIL: SIL guaranteed transformations:(在 lib / SILOptimizer / Mandatory中实现)执行影响程序正确性的其他数据流诊断(例如,使用未初始化的变量)。这些转变的最终结果是Canonical SIL。
- IR Generation:在 lib / IRGen中实现)将SIL降低到LLVM IR,此时LLVM可以继续对其进行优化并生成机器代码。
- Executable:生成可执行文件 .o 、通过如下命令实现
xcrun -sdk macosx swiftc main.swift -o main
-
- 我们可以通过如下命令查看 swiftc 都能做什么样的事情: swiftc -h
2、Swift编译过程中的中间代码:SIL分析
- 使用Xcode创建 macOS --Command Line Tool - main.swift、书写
- 使用生成SIL语言的命令并打开sil文件、
swiftc -emit-sil main.swift >> main.sil && open main.sil
- 下面是对main.sil的分析
// @mian 标识为当前main.swift的入口函数,SIL中的标识符名称以@作为前缀
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
// %0、%1...在SIL也叫做寄存器,这里我们可以理解为我们日常开发中的常量,一旦赋值之后就不可以再更改,如果SIL中还要继续使用,那么就不断的累加数字。
//同时这里所说的寄存器是虚拟的,最终运行到我们的机器上, 会使用真的寄存器。
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
//alloc_global 创建一个全局变量
alloc_global @$s4main6personAA8HSPersonCvp // id: %2
//global_addr 拿到全局变量的地址,赋值给 %3
%3 = global_addr @$s4main6personAA8HSPersonCvp : $*HSPerson // user: %7
//metatype 拿到 HSPerson的Metadata赋值给 %4
%4 = metatype $@thick HSPerson.Type // user: %6
//将__allocating_init 的函数地址赋值给 %5 function_ref HSPerson.__allocating_init()
%5 = function_ref @$s4main8HSPersonCACycfC : $@convention(method) (@thick HSPerson.Type) -> @owned HSPerson // user: %6
//apply 调⽤__allocating_init , 并把返回值给 %6
%6 = apply %5(%4) : $@convention(method) (@thick HSPerson.Type) -> @owned HSPerson // user: %7
//将%6的值存储到%3(新建的全局变量的地址)
store %6 to %3 : $*HSPerson // id: %7
//integer_literal 创建整型变量 0
%8 = integer_literal $Builtin.Int32, 0 // user: %9
//构建Int赋值给 %9
%9 = struct $Int32 (%8 : $Builtin.Int32) // user: %10
//返回 0
return %9 : $Int32 // id: %10
} // end sil function 'main'
- 下面是对 HSPerson对象的创建过程
// HSPerson.__allocating_init()
sil hidden [exact_self_class] @$s4main8HSPersonCACycfC : $@convention(method) (@thick HSPerson.Type) -> @owned HSPerson {
// %0 "$metatype"
bb0(%0 : $@thick HSPerson.Type):
//alloc_ref :堆上分配空间、创建⼀个HSPerson 的实例对象,当前实例对象的默认引⽤计数为 1
%1 = alloc_ref $HSPerson // user: %3
// 调⽤ init ⽅法 ;function_ref HSPerson.init() 初始化当前变量
%2 = function_ref @$s4main8HSPersonCACycfc : $@convention(method) (@owned HSPerson) -> @owned HSPerson // user: %3
%3 = apply %2(%1) : $@convention(method) (@owned HSPerson) -> @owned HSPerson // user: %4
return %3 : $HSPerson // id: %4
} // end sil function '$s4main8HSPersonCACycfC'
Swift创建对象简要分析及实例对象占用内存大小
1、Xcode分析对象的创建过程 (Xcode -- Debug - Debug Workflow -- Always Show Disassembly)在Xcode 的main.swift
print(MemoryLayout<Int>.stride)//8
print(MemoryLayout<String>.stride)//16
print(class_getInstanceSize(HSPerson.self))//40。
上述获取的内存占用为什么等于40?
- 下断点得到创建过程调用函数为
- HSPerson.__allocating_init()
- 于是下符号断点 HSPerson.__allocating_init 得到调用函数 swift_allocObject
- 继续下符号断点 swift_allocObject 得到调用函数 swift_slowAlloc
2、采用VSCode分析Swift源码调用过程、运行源码整体项目、在终端控制台输入
(swift) class HSTeacher{
var age:Int = 20
var name:String = "Holo"
}
//此时在 swift_allocObject打上断点
(swift) let p = HSTeacher()
- 首先走的是 swift_allocObject函数
HeapObject *swift::swift_allocObject(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask) {
CALL_IMPL(swift_allocObject, (metadata, requiredSize, requiredAlignmentMask));
}
2.然后继续调用私有化 _swift_allocObject_ 创建实例对象方法
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
size_t requiredSize,//创建实例对象大小
size_t requiredAlignmentMask) {//字节对齐
assert(isAlignmentMask(requiredAlignmentMask));
auto object = reinterpret_cast<HeapObject *>(
swift_slowAlloc(requiredSize, requiredAlignmentMask));
new (object) HeapObject(metadata);//当前实例对象在内存中以metadata元类型(元数据)创建的HeapObject对象存储
SWIFT_LEAKS_START_TRACKING_OBJECT(object);
SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);
return object;
}
3.下一步走 swift_slowAlloc 方法:在堆空间上创建一个size大小的空间来存储当前的实例对象
void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
void *p;
// This check also forces "default" alignment to use AlignedAlloc.
if (alignMask <= MALLOC_ALIGN_MASK) {
p = malloc(size);//在当前堆空间、创建一个size大小的空间
} else {
size_t alignment = (alignMask == ~(size_t(0)))
? _swift_MinAllocationAlignment
: alignMask + 1;
p = AlignedAlloc(size, alignment);
}
if (!p) swift::crash("Could not allocate memory.");
return p;
}
4.此时分析私有创建实例化方法_swift_allocObject_的返回值 HeapObject 结构体内容
#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
InlineRefCounts refCounts
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;//指针类型的 metadata、占用8字节
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;//此处定义为 InlineRefCounts refCounts;refCounts 引用计数
#ifndef __swift__
HeapObject() = default;
//初始化方法HeapObject:需要metadata和refCounts; Initialize a HeapObject header as appropriate for a newly-allocated object.
constexpr HeapObject(HeapMetadata const *newMetadata)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Initialized)
{ }
// Initialize a HeapObject header for an immortal object
constexpr HeapObject(HeapMetadata const *newMetadata,
InlineRefCounts::Immortal_t immortal)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Immortal)
{ }
#ifndef NDEBUG
void dump() const LLVM_ATTRIBUTE_USED;
#endif
#endif // __swift__
};
5.HeapObject结构体中的引用计数 InlineRefCounts 类型为定义的RefCounts类、也是一种指针类型、占用8字节
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;
class RefCounts {
std::atomic<RefCountBits> refCounts;
......
}
class RefCountBitsT {
friend class RefCountBitsT<RefCountIsInline>;
friend class RefCountBitsT<RefCountNotInline>;
......
}
小结:
- OC中实例对象的本质 objc_object(class isa) 默认占用8字节。
- 而swift中创建的 p实例对象本质为HeapObject:结构为metadata和refCounts、默认占用16字节。所以上述占用40字节由此而来。
类的结构底层探索
1.由上述总结得:类的结构该从HeapObject结构开始分析;其中的metadata记录类当前类运行相关的信息。
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;//元数据、记录与当前类运行相关信息。
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
#ifndef __swift__
HeapObject() = default;
// Initialize a HeapObject header as appropriate for a newly-allocated object.
constexpr HeapObject(HeapMetadata const *newMetadata)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Initialized)
{ }
// Initialize a HeapObject header for an immortal object
constexpr HeapObject(HeapMetadata const *newMetadata,
InlineRefCounts::Immortal_t immortal)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Immortal)
{ }
#ifndef NDEBUG
void dump() const LLVM_ATTRIBUTE_USED;
#endif
#endif // __swift__
};
2.查看元数据metadata 类HeapMetadata结构、本质上为 TargetHeapMetadata起的别名、
namespace swift {
struct InProcess;
template <typename Target> struct TargetHeapMetadata;//模版类型
using HeapMetadata = TargetHeapMetadata<InProcess>;
#else
typedef struct HeapMetadata HeapMetadata;
typedef struct HeapObject HeapObject;
#endif
- 其中的 InProcess结构如下,其中的 StoredPointer 为uintptr_t类型; 其中 typedef unsigned long uintptr_t;
struct InProcess {
static constexpr size_t PointerSize = sizeof(uintptr_t);
using StoredPointer = uintptr_t;
using StoredSize = size_t;
using StoredPointerDifference = ptrdiff_t;
static_assert(sizeof(StoredSize) == sizeof(StoredPointerDifference),"target uses differently-sized size_t and ptrdiff_t");
template <typename T>
using Pointer = T*;
template <typename T, bool Nullable = false>
using FarRelativeDirectPointer = FarRelativeDirectPointer<T, Nullable>;
template <typename T, bool Nullable = false>
using RelativeIndirectablePointer =
RelativeIndirectablePointer<T, Nullable>;
template <typename T, bool Nullable = true>
using RelativeDirectPointer = RelativeDirectPointer<T, Nullable>;
};
3.重点看 TargetHeapMetadata结构、我们需要找到其中相关的属性进行分析;然而TargetHeapMetadata中并没有发现什么关键的属性、仅有一个关于TargetHeapMetadata的MetadataKind初始化方法;所以我们向其父类TargetMetadata探索。
struct TargetHeapMetadata : TargetMetadata<Runtime> {
using HeaderType = TargetHeapMetadataHeader<Runtime>;
TargetHeapMetadata() = default;
constexpr TargetHeapMetadata(MetadataKind kind)
: TargetMetadata<Runtime>(kind) {}
#if SWIFT_OBJC_INTEROP
constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
: TargetMetadata<Runtime>(isa) {}
#endif
};
4.TargetMetadata结构体的内容如下
- 其中的private属性中有个StoredPointer Kind; Kind为 unsigned long类型,用来区分哪种类型的元数据。
- 在public的方法中 使用 getKind()调用该Kind的值、获取元数据metadata的kind、getKind()的返回值为MetadataKind。
- 其中的getClassObject()方法用来获取当前类对象、其返回值类型为 TargetClassMetadata:用来匹配当前的Kind
/// 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(TargetAnyClassMetadata<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);
}
#if SWIFT_OBJC_INTEROP
protected:
const TargetAnyClassMetadata<Runtime> *getClassISA() const {
return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
}
void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
Kind = reinterpret_cast<StoredPointer>(isa);
}
#endif
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>::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;
/// 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: {
const auto cls = static_cast<const TargetClassMetadata<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 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;
#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>*>(
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;
};
5.MetadataKind用来记录Swift中的metadata:包括METADATAKIND和ABSTRACTMETADATAKIND
enum class MetadataKind : uint32_t {
#define METADATAKIND(name, value) name = value,
#define ABSTRACTMETADATAKIND(name, start, end) \
name##_Start = start, name##_End = end,
#include "MetadataKind.def"
LastEnumerated = 0x7FF,
};
- 其中MetadataKind的具体值、定义在MetadataKind.def文件中;我们对其进行总结得
name Value
Class 0x0
Struct 0x200
Enum 0x201
Optional 0x2027
ForeignClass 0x203
ForeignClass 0x203
Opaque 0x300
Tuple 0x301
Function 0x302
Existential 0x303
Metatype 0x304
ObjCClassWrapper 0x305
ExistentialMetatype 0x306
HeapLocalVariable 0x400
HeapGenericLocalVariable 0x500
ErrorObject 0x501
LastEnumerated 0x7FF
- getClassObject()方法用来匹配当前的Kind类型;this代表当前指针、也代表当前metadata指针、强转为ClassMetadata指针;
- 通过po metadata->getKind() 获取当前Kind类型; po metadata->getClassObject() 获取指针地址;TargetClassMetadata为TargetMetadata的子类
- ClassMetadata 返回 TargetClassMetadata(所有的属性) --> TargetAnyClassMetadata --> TargetHeapMetadata --> TargetMetadata(Kind)
template<> inline const ClassMetadata *
Metadata::getClassObject() const {
switch (getKind()) {
case MetadataKind::Class: {
// Native Swift class metadata is also the class object.
return static_cast<const ClassMetadata *>(this);
}
case MetadataKind::ObjCClassWrapper: {
// Objective-C class objects are referenced by their Swift metadata wrapper.
auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
return wrapper->Class;
}
// Other kinds of types don't have class objects.
default:
return nullptr;
}
}
6.其中涉及的ClassMentadata结构为
using ClassMetadata = TargetClassMetadata<InProcess>;
- 而TargetClassMetadata的结构内容为
template <typename Runtime>
struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
TargetClassMetadata() = default;
constexpr TargetClassMetadata(const TargetAnyClassMetadata<Runtime> &base,
ClassFlags flags,
ClassIVarDestroyer *ivarDestroyer,
StoredPointer size, StoredPointer addressPoint,
StoredPointer alignMask,
StoredPointer classSize, StoredPointer classAddressPoint)
: TargetAnyClassMetadata<Runtime>(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.
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor> Description;
......
}
7.因此我们总结得到当前的 metadata数据结构体如下:(大多在TargetClassMetadata中)
struct swift_class_t : NSObject{
void *kind; //isa,kind(unsigned long)
void *superclass;//TargetAnyClassMetadata中
void *CacheData; //TargetAnyClassMetadata中
void *Data; //TargetAnyClassMetadata中
uint32_t Flags;//4
uint32_t InstanceAddressPoint;//4
uint32_t InstanceSize;//4
uint16_t InstanceAlignMask;//2
uint16_t Reserved;//2 ;Reserved for runtime use
uint32_t ClassSize;//4
uint32_t ClassAddressPoint;//4
void *description;
.....
};