接上篇:编译过程补充
语法分析 Parse --> 语义分析 Sema --> SILGen --> IRGen --> 汇编 --> MachO
网上找到一张图片:
具体命令:
-dump—parse --> -dump—ast --> -emit-silgen --> -emit-sil --> -emit-ir
Swift 对象创建过程 —— allocating_init()
创建一个swift对象会调用类的__allocating_init()
方法,然后调用私有方法_swift_allocObject_()
方法
这个方法实现在 HeapObject.cpp
中:
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask) {
assert(isAlignmentMask(requiredAlignmentMask));
auto object = reinterpret_cast(
swift_slowAlloc(requiredSize, requiredAlignmentMask));
// NOTE: this relies on the C++17 guaranteed semantics of no null-pointer
// check on the placement new allocator which we have observed on Windows,
// Linux, and macOS.
new (object) HeapObject(metadata);
// If leak tracking is enabled, start tracking this object.
SWIFT_LEAKS_START_TRACKING_OBJECT(object);
SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);
return object;
}
swift_slowAlloc()
首先使用 assert
检查了传递的参数的内存对齐规范,然后调用了 swift_slowAlloc(requiredSize, requiredAlignmentMask)
,方法如下,在Heap.cpp中
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) {
#if defined(__APPLE__)
p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
p = malloc(size);
#endif
} 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;
}
这里看到了熟悉的 malloc(size)
,OC也是调用的这个。
HeapObject
然后回到_swift_allocObject_()
方法,继续调用了
new (object) HeapObject(metadata);
使用入参 metadata 调用 HeapObject 的初始化方法,创建了一个 HeapObject。
HeapObject 是一个结构体,声明在 HeapObject.h 文件中
/// The Swift heap-object header.
/// This must match RefCountedStructTy in IRGen.
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__
};
可以看到成员变量:
-
metadata
指针 SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS
所以一个 HeapObject
对象什么属性都不声明,就默认占用16字节的大小。
Swift 对象是一个 HeapObject,默认占用16字节。
OC 对象是一个结构体 objc_object,默认只有 isa 指针,占用8字节。
isa指针具体解释如下图,更多详情参考 footnote 第一个链接。
类结构
上面创建实例对象的方法有一个入参,叫做metadata,也叫元数据,这个就好像OC的class一样,类是创建实例对象的模板,就是这个metadata。
HeapMetadata const *metadata;
点击可以查看到 HeapMetadata 的定义:
using HeapMetadata = TargetHeapMetadata;
TargetHeapMetadata
struct TargetHeapMetadata : TargetMetadata {
using HeaderType = TargetHeapMetadataHeader;
TargetHeapMetadata() = default;
constexpr TargetHeapMetadata(MetadataKind kind)
: TargetMetadata(kind) {}
#if SWIFT_OBJC_INTEROP
constexpr TargetHeapMetadata(TargetAnyClassMetadata *isa)
: TargetMetadata(isa) {}
#endif
};
TargetHeapMetadata 继承自 TargetMetadata。
class的类型其实是TargetMetadata
的 kind 传入 class 的 kind,具体的类是TargetAnyCkassMetadata
,这里不是特别确定,但是看到这个类确实是如此的。
类相关的继承关系是这样的:
TargetClassMetadata → TargetAnyClassMetadata → TargetHeapMetadata → TargetMetadata
UML
如果 swift 的类继承了 OC 的类,那么这个 kind 就会指向 objc_class。
如上图,OC class 结构为:objc_class → objc_object。
objc_class 结构如下:
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
}
这里先后存储的东西分四个:
- 继承来的
isa
结构的指针,占8字节 - superClass 的 Class 指针,占8字节
- cache类型,本篇跳过。
- class_data_bits_t类型的bits。
关于 class_data_bits_t
、class_rw_t
、class_ro_t
、class_rwe_t
,请参考Footnote第一个链接。
Footnote
OC Runtime 底层类结构2020最新
官方SIL语法文档
官方SIL编程手册
Swift进阶
Swift之源码编译的环境搭建和编译流程