在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
swift class的虚函数表、扩展、@objc修饰的研究
工具: swiftc -emit-sil BaseClass.swift | xcrun swift-demangle > ClassFunc.silgen cat ClassFunc.silgen
目标: 1、@objc和@objc dynamic修饰的函数是否进入虚函数表; 2、虚函数的的派发机制是什么?函数的调用在编译器层面最终转化为apply调用; 3、extension中的缺省修饰函数是否进入虚函数表; 4、extension中的@objc修饰函数的行为; 5、结构体是否允许@objc修饰: @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
https://www.cnblogs.com/feng9exe/p/9460336.html
class NSObjectBase: NSObject { func Msg_Normal(){ print("Msg_Normal") } func Msg_Second(){ print("Msg_Second") } func Msg_Third(){ print("Msg_Second") } @objc func Msg_ObjcX(){} @objc dynamic func Msg_Objc_Dynamic(){} func callTest(){self.Msg_Normal()} func callAgain(){self.Msg_Third()} }
extension NSObjectBase{ @objc func OcExtensionFunc(){print("OcExtensionFunc")} }
class DerivedOcClass:NSObjectBase{ override func OcExtensionFunc(){print("DerivedOcClass OcExtensionFunc")} }
// NSObjectBase.Msg_Objc_DynamicX() sil hidden @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () { // %0 // user: %1 bb0(%0 : $NSObjectBase): debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1 %2 = tuple () // user: %3 return %2 : $() // id: %3 } // end sil function 'NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'
// @objc NSObjectBase.Msg_Objc_DynamicX() sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(objc_method) (NSObjectBase) -> () { // %0 // users: %4, %3, %1 bb0(%0 : $NSObjectBase): strong_retain %0 : $NSObjectBase // id: %1 // function_ref NSObjectBase.Msg_Objc_DynamicX() %2 = function_ref @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3 %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5 strong_release %0 : $NSObjectBase // id: %4 return %3 : $() // id: %5 } // end sil function '@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'
// NSObjectBase.Msg_ObjcX() sil hidden @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () { // %0 // user: %1 bb0(%0 : $NSObjectBase): debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1 %2 = tuple () // user: %3 return %2 : $() // id: %3 } // end sil function 'NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'
// @objc NSObjectBase.Msg_ObjcX() sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(objc_method) (NSObjectBase) -> () { // %0 // users: %4, %3, %1 bb0(%0 : $NSObjectBase): strong_retain %0 : $NSObjectBase // id: %1 // function_ref NSObjectBase.Msg_ObjcX() %2 = function_ref @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3 %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5 strong_release %0 : $NSObjectBase // id: %4 return %3 : $() // id: %5 } // end sil function '@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'
sil hidden @NSObjectBase.NSObjectBase.callTest() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () { // %0 // users: %3, %2, %1 bb0(%0 : $NSObjectBase): debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1 %2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Normal!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3 %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function 'NSObjectBase.NSObjectBase.callTest() -> ()'
// NSObjectBase.callAgain() sil hidden @NSObjectBase.NSObjectBase.callAgain() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () { // %0 // users: %3, %2, %1 bb0(%0 : $NSObjectBase): debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1 %2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Third!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3 %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function 'NSObjectBase.NSObjectBase.callAgain() -> ()'
sil_vtable NSObjectBase { #NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () // NSObjectBase.Msg_Normal() #NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () // NSObjectBase.Msg_Second() #NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> ()// NSObjectBase.Msg_Third() #NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () // NSObjectBase.Msg_Objc() #NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () // NSObjectBase.callTest() #NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> ()// NSObjectBase.callAgain() }
sil_vtable DerivedOcClass { #NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () [inherited] // NSObjectBase.Msg_Normal() #NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () [inherited] // NSObjectBase.Msg_Second() #NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> () [inherited] // NSObjectBase.Msg_Third() #NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () [inherited] // NSObjectBase.Msg_Objc() #NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () [inherited] // NSObjectBase.callTest() #NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> () [inherited] // NSObjectBase.callAgain() } apply担任函数绑定和派发的职责 那么阅读就显得简单多了, 可以看到最终对应到 testFunc函数调用的指令有两条.
作者:MaizeJS 链接:https://www.jianshu.com/p/cfe7da01880d 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。 |
请发表评论