一缀雳、swift編譯簡介
IOS開發(fā)的語言不管是OC還是swift,后端都是通過LLVM進(jìn)行編譯的梢睛,如下:
可以看到OC是clang編譯器肥印,編譯IR,然后在生成可執(zhí)行文件.0(機器碼),Swift是通過swift編譯器绝葡,編譯成IR深碱,然后生成可執(zhí)行文件。
二藏畅、SIL
swift使用的編譯器為swiftc敷硅,OC使用的為Clang。
swiftc命令查詢:swiftc -h
參考視頻:鏈接
參考文檔:SIL參考文檔
編譯成SIL文件:
swiftc -emit-sil main.swift >> main.sil && open main.sil
//帶轉(zhuǎn)譯
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文件的入口函數(shù)
- @main 是main.swift的入口函數(shù)愉阎,SIL中標(biāo)識符名稱以@作為前綴绞蹦,入口函數(shù)有兩個參數(shù),一個32位Int榜旦,一個指針幽七,一個返回值。
- %0溅呢、%1......在SIL中叫做寄存器锉走,可以視為長量,賦值后不可更改藕届,在SIL中以累加數(shù)字的模式繼續(xù)使用挪蹭。這里所說的寄存器是虛擬的,最終運行到我們的機器上會使用真的寄存器休偶。
- alloc_global 創(chuàng)建一個全局變量
- global_addr 拿到全局變量的地址梁厉,賦值給%3
- metatype 拿到LJTest的Metadata賦值給%4
- 將__allocating_init 的函數(shù)地址賦值給%5
- apply 調(diào)用 __allocating_init,并賦值給%6
- 將%6的值存儲到%3
- 構(gòu)建Int踏兜, 并return返回
- Buildin LLVM指令格式
轉(zhuǎn)譯命令xcrun swift-demangle s4main2t1AA6LJTestCvp
寄存器讀却使恕:register read
register read x8
xcode添加符號斷點
三、HeapObject.cpp中alloc_Object方法
1碱妆、初始化調(diào)度
- 一個swift對象的內(nèi)存結(jié)構(gòu)HeapObject肉盹,默認(rèn)占用16字節(jié)大小,metadata疹尾,refCount
- swift內(nèi)存分配過程調(diào)用順序:__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骤肛、類結(jié)構(gòu)探索
- swift初始化函數(shù)swift_allocObject
函數(shù)3個參數(shù):
HeapMetadata const *metadata :元數(shù)據(jù)
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結(jié)構(gòu)體重包含一個屬性kind窍蓝,是一個存儲指針(isa)腋颠,是用來區(qū)分哪種類型的元數(shù)據(jù),在#include "MetadataKind.def"
文件中存儲了所有的元數(shù)據(jù)類型吓笙。
獲取當(dāng)前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結(jié)構(gòu)體:
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; // ...
};