- method execute address is stored in function table
- 2 jumps when execute: (1) jumps to the function table, (2) access `vTable[method_name]` to get the execute access
4. message dispatch
- powered by Objective-C runtime , pure swift don’t have message dispatch
- using `objc_msgSend` to determine the implementation of a given `selector` ,
- complier search through class (NSObject subclass) hierarchy bottom up,
- each class can provide the implementation at runtime using several method level: `resolveInstanceMethod`, `forwardingTargetForSelector` , `forwardInvocation` (similar for class method)
Thanks for great writing, below is my understanding, pls let me know if I'm wrong 🙏
1. inline / precomputing (dispatch)
- execute directly, no jump
- well know info at compile time
- e.g: simple struct, enum definition
2. static dispatch:
- 1 jump to execute address
- execute memory address is knowable at compile time
3. dynamic dispatch (virtual table / witness table dispatch)
- inheritance / polymorphism (method override, protocol conforms …)
- method execute address is stored in function table
- 2 jumps when execute: (1) jumps to the function table, (2) access `vTable[method_name]` to get the execute access
4. message dispatch
- powered by Objective-C runtime , pure swift don’t have message dispatch
- using `objc_msgSend` to determine the implementation of a given `selector` ,
- complier search through class (NSObject subclass) hierarchy bottom up,
- each class can provide the implementation at runtime using several method level: `resolveInstanceMethod`, `forwardingTargetForSelector` , `forwardInvocation` (similar for class method)