一、swift编译简介
IOS开发的语言不管是OC还是swift,后端都是通过LLVM进行编译的,如下:
image.png
可以看到OC是clang编译器,编译IR,然后在生成可执行文件.0(机器码),Swift是通过swift编译器,编译成IR,然后生成可执行文件。
image.png
二、SIL
swift使用的编译器为swiftc,OC使用的为Clang。
swiftc命令查询:swiftc -h
参考视频:链接
参考文档:SIL参考文档
编译成SIL文件:
swiftc -emit-sil main.swift >> main.sil && open main.sil
//带转译
swiftc -emit-sil main.swift | xcrun swift-demangle >> main.sil && open main.sil
//IR
swiftc -emit-ir main.swift | xcrun swift-demangle >> main.ll && open main.ll
//UIKit
swiftc -emit-sil -target x86_64-apple-ios13.5-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift > ViewController.sil
swift文件的入口函数
image.png
- @main 是main.swift的入口函数,SIL中标识符名称以@作为前缀,入口函数有两个参数,一个32位Int,一个指针,一个返回值。
- %0、%1......在SIL中叫做寄存器,可以视为长量,赋值后不可更改,在SIL中以累加数字的模式继续使用。这里所说的寄存器是虚拟的,最终运行到我们的机器上会使用真的寄存器。
- alloc_global 创建一个全局变量
- global_addr 拿到全局变量的地址,赋值给%3
- metatype 拿到LJTest的Metadata赋值给%4
- 将__allocating_init 的函数地址赋值给%5
- apply 调用 __allocating_init,并赋值给%6
- 将%6的值存储到%3
- 构建Int, 并return返回
- Buildin LLVM指令格式
转译命令xcrun swift-demangle s4main2t1AA6LJTestCvp
寄存器读取:register read
register read x8
xcode添加符号断点
image.png
三、HeapObject.cpp中alloc_Object方法
image.png1、初始化调度
- 一个swift对象的内存结构HeapObject,默认占用16字节大小,metadata,refCount
- swift内存分配过程调用顺序:__allocating_init ---> swift_allocObject ---> swift_allocObject ---> swift_slowAlloc ---> Malloc
2、打印占用空间大小
import Foundation
class LJTest{
var age = 18
var name: String = "swift"
}
var t1 = LJTest()
print(MemoryLayout<String>.stride) //步长
print(MemoryLayout<String>.size) //大小
print(class_getInstanceSize(LJTest.self)) //大小
3、类结构探索
- swift初始化函数swift_allocObject
函数3个参数:
HeapMetadata const *metadata :元数据
size_t requiredSize :大小
size_t requiredAlignmentMask :对齐格式,
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));
// 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;
}
- Matedata
TargetMetadata结构体重包含一个属性kind,是一个存储指针(isa),是用来区分哪种类型的元数据,在#include "MetadataKind.def"
文件中存储了所有的元数据类型。
image.png
获取当前kind
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
获取类对象
const TargetClassMetadata<Runtime> *getClassObject() const;
getClassObject()方法获取的就是kind类型,通过getKind()方法获取类型(MetadataKind::Class),
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;
}
}
- Matedata::Class
TargetClassMetadata(ClassMetadata一样,所有的属性) --> TargetAnyClassMetadata(kind, superclass, cacheData) --> TargetHeapMetadata(HeapMetadata) --> TargetMetadata(kind)
Metadata结构体:
struct swift_class_t: NSObject{
void *kind; //isa, kind(unsigned long)
void *superClass;
void *cacheData
void *data
uint32_t flags; //4
uint32_t instanceAddressOffset; //4
uint32_t instanceSize;//4
uint16_t instanceAlignMask; //2
uint16_t reserved; //2
uint32_t classSize; //4
uint32_t classAddressOffset; //4
void *description; // ...
};
网友评论