• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

swiftclass的虚函数表、扩展、@objc修饰、虚函数的派发方式研究 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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函数调用的指令有两条.

%4 = class_method %2 : $MyClass, #MyClass.testFunc!1 : (MyClass) -> () -> (), $@convention(method) (@guaranteed MyClass) -> () // user: %5
%5 = apply %4(%2) : $@convention(method) (@guaranteed MyClass) -> ()
  1. class_method: 该指令通过类的函数表来查找函数, 基于类的实际类型.
  2. apply: 传递参数并执行函数.


作者:MaizeJS
链接:https://www.jianshu.com/p/cfe7da01880d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Swift实战-豆瓣电台(六)视图跳转,传参及回跳发布时间:2022-07-13
下一篇:
swift-导航栏添加自定义返回按钮发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap