Runtime之IMP指针,isa指针

要了解 isa 指针先了解下类的定义
在xcode中用快捷键Shift+Cmd+O 搜索objc.h 能看到类的定义:
了解html


Paste_Image.png

能够看出:
objc_object:Objective-C对对象的定义, 其质上是结构体对象,其中 isa是它惟一的私有成员变量,即全部对象都有isa指针
Class 是一个 objc_class 结构类型的指针
id是一个 objc_object 结构类型的指针,这也是id能够指向任何对象的缘由
SEL(方法选择器)是一个objc_selector结构类型的指针
IMP 先不提ios

再搜runtime.h数组


Paste_Image.png

每一个对象结构体的首个成员是Class类的变量,该变量定义了对象所属的类,一般称为isa指针xcode

super_class:父类,若是该类已是最顶层的根类,那么它为NULL。
version:类的版本信息,默认为0
info:供运行期使用的一些位标识。
instance_size:该类的实例变量大小
ivars:成员变量的数组
struct objc_method_list **methodLists OBJC2_UNAVAILABLE : 方法列表,类目就是经过它添加方法的缓存

struct objc_cache *cache OBJC2_UNAVAILABLE : 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在methodLists中遍历,若是cache了,经常使用的方法调用时就可以提升调用的效率。架构

struct objc_protocol_list *protocols OBJC2_UNAVAILABLE : 协议链表ide

 

isa 指针优化(NONPOINTER_ISA)

用 64 bit 存储一个内存地址显然是种浪费,毕竟不多有那么大内存的设备。因而能够优化存储方案,用一部分额外空间存储其余内容。isa 指针第一位为 1 即表示使用优化的 isa 指针,这里列出不一样架构下的 64 位环境中 isa 指针结构:函数

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bits; #if SUPPORT_NONPOINTER_ISA # if __arm64__ # define ISA_MASK 0x00000001fffffff8ULL # define ISA_MAGIC_MASK 0x000003fe00000001ULL # define ISA_MAGIC_VALUE 0x000001a400000001ULL struct { uintptr_t indexed : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000 uintptr_t magic : 9; uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 19; # define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18) }; # elif __x86_64__ # define ISA_MASK 0x00007ffffffffff8ULL # define ISA_MAGIC_MASK 0x0000000000000001ULL # define ISA_MAGIC_VALUE 0x0000000000000001ULL struct { uintptr_t indexed : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000 uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 14; # define RC_ONE (1ULL<<50) # define RC_HALF (1ULL<<13) }; # else // Available bits in isa field are architecture-specific. # error unknown architecture # endif // SUPPORT_NONPOINTER_ISA #endif };

SUPPORT_NONPOINTER_ISA 用于标记是否支持优化的 isa 指针,其字面含义意思是 isa 的内容再也不是类的指针了,而是包含了更多信息,好比引用计数,析构状态,被其余 weak 变量引用状况。判断方法也是根据设备类型:优化

#if !__LP64__ || TARGET_OS_WIN32 || TARGET_IPHONE_SIMULATOR || __x86_64__ # define SUPPORT_NONPOINTER_ISA 0 #else # define SUPPORT_NONPOINTER_ISA 1 #endif

isa指针会判断是否支持 TaggedPointer 支持会直接将其指针值做为引用计数返回ui

TaggedPointer 就是一种优化方式,当承载内容小于8字节时,指针直接储存承载内容

关于Tagged Pointer 这里有详细介绍
http://www.infoq.com/cn/articles/deep-understanding-of-tagged-pointer/

若是当前设备是 64 位环境而且使用 Objective-C 2.0(5s以后就都是64位),那么“一些”对象会使用其 isa 指针的一部分空间来存储它的引用计数;不然 Runtime 会使用一张散列表来管理引用计数

64位中isa 指针中变量对应的含义:


Paste_Image.png

associate object : 关联对象

 

IMP 指针


Paste_Image.png

SEL会依据方法名生成惟一的表示做为key ,便于查找

IMP指针是指向实现函数的指针,经过SEL取得IMP,objc_msgSend来执行实现方法

objc_msgSend函数在执行方法时不会直接在 isa 指针指向的类的方法列表中遍历查找可以响应的方法,由于每次都要查找效率过低了,而是优先在缓存(方法列表)中查找,如果找不到再沿着继承体向上查找。每次匹配到的结果会缓存在"快速映射表"里,来提升效率,同时objc_msgSend函数用到了"尾调用优化技术",来节约资源,感兴趣能够了解下
https://en.wikipedia.org/wiki/Tail_call
http://kb.cnblogs.com/page/518771/


//引用文章
http://www.cocoachina.com/ios/20151209/14636.html
http://www.cocoachina.com/ios/20150717/12623.html
http://www.cnblogs.com/ioshe/p/5489086.html

相关文章
相关标签/搜索