iOS底层探索 之 cache分析

356 阅读1分钟

今天我们继续来探究类的原理分析

image.png

断点打印P指令 image.png

image.png

cache_t jump进入 image.png

bucket_t jump进入 image.png

下面通过LLDB去验证方法的存储

几次失败的尝试 image.png

再看下源码 image.png

继续尝试 image.png

为什么会是空的值呢? 因为我用的是模拟器,所以走的是下面的代码 image.png

image.png

继续看源码 image.png

使用sel输出 image.png

image.png

(lldb) p $13.imp(nil,pClass)
(IMP) $15 = 0x0000000100003c80 (HLObjcBuild`-[HLPerson saySomething])
接下来我们根据源代码

image.png

可以自己定义

image.png

image.png

image.png

此处为互斥结构 image.png

buckets image.png

数组取值 image.png

p 5.sel()>(SEL)5.sel()->(SEL) 6 = xxxxx -> p $3+1 指针内存平移取值

_bucketsAndMaybeMask的使用 image.png

不同架构选择 image.png

内存地址打印 image.png

0b0000000000000000000000000000000100000000011100001001100110110000

左边为高地址,右边为低地址

(lldb) x p ->内存

0x100744a80: c9 84 00 00 01 80 1d 01 00 00 00 00 00 00 00 00 ................

0x100744a90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

大端模式从左往右 读取8个字节 0x

00 00 84 c9

小短模式从右到左 读取8个字节 0x c9 84 00 00

3/4 扩容 -> 负载因子为0.75

1、空间利用率最高

2、能有效避免哈希冲突碰撞(底层的链表及红黑树频率)

insert image.png

bt-查看整个的堆栈 image.png

frame #1: 0x000000010031374a libobjc.A.dyliblog_and_fill_cache(cls=OS_dispatch_data, imp=(libdispatch.dylib-[OS_dispatch_data dealloc]), sel="dealloc", receiver=0x00000001007171c0, implementer=OS_dispatch_data)(), objc_selector*, objc_object*, objc_class*) at objc-runtime-new.mm:6305:16

image.png

补充

image.png

image.png

Value 为什么等于7呢?

3->7 是因为发生了类似的扩容

insert函数 image.png

image.png

添加打印语句

printf("=== %s - %p - %p \n",(char*)sel,imp,receiver);

image.png

跟踪HLPerson image.png

image.png

当sel=say1时,oldCapacity=3,(Capacity是内存)
1、打印 p [p say1]->po (SEL)地址
2、打印 p class_getMethodImlementaton([HlPerson class],$1)