闭包尽量选择非逃逸闭包
函数是引用类型
? func addTwoInts(_ a: Double, _ b: Double) -> Double {
?? ? ? return a + b
?? }
var a = addTwoInts
var?b = a
函数的内存结构
1. 函数类型?type(of: a)
2.unsafeBitCast 指针转换
struct TargetFunctionTypeMetadata{
? ? var kind: Int
? ? var flags: Int
? ? func numberArguments() -> Int{
? ? ? ? return self.flags & 0x0000FFFF
? ? }
}
let type = type(of: a)
let functionType = unsafeBitCast(type as Any.Type, to: UnsafeMutablePointer<TargetFunctionTypeMetadata>.self)?print(functionType.pointee.numberArguments()) // 2
闭包
闭包的本质
{ i8*, %swift.refcounted* }
闭包的执行地址? + 捕获变量堆空间的地址
1.?Box<T> 代表一个实例对象
2.?HeapObject实例对象的metadata 和引用计数
3.Box<T> 中的value?捕获的值
struct ClosureData{
? ? var ptr: UnsafeRawPointer //?闭包的执行地址
? ? var capatureValue: UnsafePointer<Box<T>> //??捕获变量堆空间的地址
}
struct HeapObject{? ?
????var metadata: UnsafeRawPointer? ?
????var refcount1: Int32? ?
????var refcount2: Int32
}
struct Box<T>{? ?
????var object: HeapObject? ?
????var value: T
}
1.?NoMeanStruct的内存地址和结构体第一个属性的内存地址是一样的,所以结构体NoMeanStruct的地址就是闭包的地址
struct NoMeanStruct{
?? var f: () -> Int
}
? ??var a = 10
? ? ? var f = NoMeanStruct {
?? ? ? ? a+= 30
?? ? ? ? return a
? ? ? }
? ? ? var ptr = UnsafeMutablePointer<NoMeanStruct>.allocate(capacity: 1)
? ? ? ptr.initialize(to: f)
//? ? ? ptr[0] = f
? ? ? defer {
?? ? ? ? ptr.deinitialize(count: 1)
?? ? ? ? ptr.deallocate()
? ? ? }
? ? ? var ctx = ptr.withMemoryRebound(to: ClosureData<Box<Int>>.self, capacity: 1) {
?? ? ? ? return $0.pointee
? ? ? }
print(ctx)
1. 第一个打印出结果,?闭包的本质是闭包的执行地址? + 捕获变量堆空间的地址
2.第二个 lldb,看出ptr 是闭包的执行地址
3.第三个lldb,看出object是个堆地址
.ll 文件简单语法
<type> *指针类型
[<elementnumber> x <elementtype>?] 数组
{..., ...} 结构体
局部变量??var?runningTotal =?10?
func makeIncrementer() -> () -> Int {
? ? var runningTotal = 10 ?//局部变量
? ? func incrementer() -> Int {
? ? ? ? runningTotal+= 1
? ? ? ? return runningTotal
? ? }
? ? return incrementer
}
let incr = makeIncrementer()
解析成.ll 文件
define i32 @main(i32 %0, i8** %1) #0 {
entry:
...
? %3 = call swiftcc { i8*, %swift.refcounted* } @"$s4main15makeIncrementerSiycyF"()
? ...
}
makeIncrementer() 返回??{ i8*, %swift.refcounted* } ?一个结构体,里面2个指针
%swift.refcounted = type { %swift.type*, i64 }
%swift.type = type { i64 }
推断出闭包是一个{?i8*,??type { type { i64 }, i64 }}
逃逸闭包
延长闭包的生命周期
逃逸闭包在函数内部异步执行或者被属性存储
非逃逸闭包
不会产生循环引用,函数作用域内释放??
编译器更多性能优化 (retain, relsase)?
上下文的内存保存再栈上,不是堆上?