探索swift可以通过:
源码调试
,Sil文件
,xcode断点调试
这些方式来进行探索,除Sil文件
这种方式其他的都会在本文中出现。OC底层探索01-找到底层探索的钥匙会有解释。
探索路径同样是参考oc的探索路径,先从类开始。
类初始化
1. 使用Xcodel断点调试
- 创建一个简单的类,开启汇编断点
-
1步骤
就是__allocation_init
是swift对象初始化入口
- 通过
2步骤
可以进入下一步(下断点,按住control+↓
)
-
swift_allocObject
是初始化第二步 -
下断点,按住control+↓
进入下一步
-
swift_slowAlloc
是初始化第三步 -
下断点,按住control+↓
进入下一步
-
malloc_zone_malloc
是初始化第四步,在这一步完成内存的分配,最终完成alloc步骤
。
2. 使用源码调试
现在通过源码调试来验证一下之前的论点。源码编译方式Swift-5.3.1 源码编译.
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask) {
assert(isAlignmentMask(requiredAlignmentMask));
//swift慢速创建流程
auto object = reinterpret_cast<HeapObject *>(
swift_slowAlloc(requiredSize, requiredAlignmentMask));
//为创建好的内存赋值
new (object) HeapObject(metadata);
SWIFT_LEAKS_START_TRACKING_OBJECT(object);
SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);
return object;
}
void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
void *p;
//一般使用 8字节对齐
//# define MALLOC_ALIGN_MASK 15
if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__)
//apple的类会进入这里
p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
p = malloc(size);
#endif
} else {
//大于16字节对齐的情况,比较少见
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;
}
- 根据源码也可以跟到具体的流程
-
alignMask <= MALLOC_ALIGN_MASK
进入这个判断可以看出swift类一般使用的是8字节对齐
#define malloc_zone_malloc(zone,size) malloc(size)
-
malloc_zone_malloc
只是一个宏定义,最终调用malloc
3. 初始化流程图
类结构 - HeapObject结构
1. 编译器断点
- 在进行类创建,源码调试的时候发现swift的类结构是这样的。和
oc
比起来是有一些不同的。我们换种方式看看.
2. lldb
- 相比于OC不同的是,除了第一位之外,还将引用计数当做第二个参数保存到对象中
3. 源码查看
swift对象继承自HeapObject
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
//#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
InlineRefCounts refCounts
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
...
}
swift-类的结构图
HeapMetadata结构
如果说metaData
相比于oc对象中的isa
的而言的话,应该要包含isa
,superclass
,cache_t
,date
等类的信息。我们就来看看HeapMetadata结构都有些什么呢~
//相当于宏定义
using HeapMetadata = TargetHeapMetadata<InProcess>
//template 模板类
struct TargetHeapMetadata : TargetMetadata<InProcess>{
。。。
}
struct TargetMetadata<InProcess>{
StoredPointer Kind; //用来区分是什么类型的原数据
//一个相关的方法
getObjCClassObject() const {
return reinterpret_cast<Class>(
const_cast<TargetClassMetadata<InProcess>*>(
getClassObject()));
}
}
-
TargetHeapMetadata
是一个模板类,想要了解内部结构需要继续向下查看 -
<InProcess>
类似于泛型,限制泛型的具体类型 - 没有看到其他相关定义,只能借助其他方式来查看
getClassObject
。
借助getClassObject方法查看HeapMetadata结构
//获取类对象
Metadata::getClassObject() const {
switch (getKind()) {
case MetadataKind::Class: {
return static_cast<const ClassMetadata *>(this);
}
//如果是类,指针强转为ClassMetadata
case MetadataKind::ObjCClassWrapper: {
auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
return wrapper->Class;
}
return nullptr;
}
}
- 我们发现将当前指针强转为
ClassMetadata
。指针可以强转则表示内部结构是相同的,我们可以转换角度去查看ClassMetadata
.
ClassMetadata
using ClassMetadata = TargetClassMetadata<InProcess>;
struct TargetClassMetadata : TargetAnyClassMetadata<Runtime> {
ClassFlags Flags;
uint32_t InstanceAddressPoint;
uint32_t InstanceSize;
...
}
struct TargetAnyClassMetadata : TargetHeapMetadata
{
ConstTargetMetadataPointer Superclass;
TargetPointer CacheData[2];
StoredSize Data;
...
}
- 看到这部分应该是明白了,结构和OC底层探索08-基于objc4-781类结构分析是相同的。
- 只有
kind
有点不一致,其实也可以看做是isa
,都是指向元类
网友评论