强引用
Strong-RefCount
class Test{
var age: Int = 20
}
var t = Test()
var t1 = t
var t2= t
那么就有三个强引用指向当前的实例对象
InlineRefCountBits
引用计数里专门为了两个类型起了别名
typedef typename RefCountBitsInt<refcountIsInline, sizeof(void *)>::Type BitsType
typedef typename RefCountBitsInt<refcountIsInline, sizeof(void *)>::Type SingedType SignedBitsType
那么结构体里的是什么有价值的东西,值得swift另起别名
typedef uint64_t Type;
typedef int64_t SignedType;
//"Bitfield" accessors bit文件访问者
BiteType bits
那么bits就是一个64位整型的数据
在上一篇Swift文章中,列举过Swift对象初始化会传递的两个参数,一个是metadata,另一个是refCount
enum Initialized_t
// Refcount of a new object is 1 为新对象添加1引用计数
constexpr RefCounts(Initialized_t):refCounts(RefCountBits(0,1))
RefCountBits传入了0,1 这两个参数有什么作用?
RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)
RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)
:bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift) | (BitsType(unownedCount) << Offsets::UnownedRefCountShift))
可以发现,传入的两个参数0,1做了位操作
那么上面这步复杂的操作为了下面这张图的存放位置
在lldb上输入
po t
x/8g $0
那么第二段内存地址所表达的东西就很明显了,分别是UnownedRefCount,StrongExtraRefCount
increment
static HeapObject *_swift_retain_ (HeapObject *object){
object->refCounts.increment(1)
那么increment方法做了什么事情?
increment
oldbits = refCounts.load(memory_order_consume) //传入一个内存指定的消费对象
RefCountBits newbits
newbits = oldbits
fast = newbits.incrementStrongExtraRefCount(inc)
if oldbits.isImmortal(){ return }
if SWIFT_UNLIKEY(!fast){return incrementSlow(oldbits ,inc)
}while(!refCounts.compare_exchange_weak(oldbits,newbits,memory_order_relaxed))
绕了一大圈,回到了RefCounts,
incrementStrongExtraRefCount
bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift)
bt打印的堆栈0x0000020000002 说明了就是上诉两个函数调用,位操作的结果
弱引用
NativeInit
side = object ? object->refCount.formWeakReferenct : nullptr
formWeakReference
auto side = allocateSideTable()
side->incrementWeak()
创建一个散列表allocateSideTable
HeapObjectSideTableEntry *side= new HeapObjectSideTabelEntry()
auto newbits = InlineRefCountBits(side)
好家伙,把side传给了在强引用时看见的InlineRefCountBits
回到强引用
RefCountBitsT
bits((reinterpret_cast<BitsType>(side) >> Offsets::SideTableUnusedLowBits)
| (BitsType(1) << Offsets::UseSlowRCShift)
| (BitsType(1) << Offsets::SideTableMarkShift)
)
位域操作想表达什么?
把散列表存到64位的某个位置
发现一对同兄难弟
typedef RefCounts<InlineRefCountBits> InlineRefCounts
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts
强引用和弱应用一同指向了一个位置 RefCountBitsT 类型为uint64_t的bits
uint32_t weakBits
说明了RefCountBitsT存了强引用的bits也存储了弱引用计数
那么81e8存放的是对象,20087e02就是存放图1-2的地址
拿到该地址
把保留位63 62去掉
左移三位
拿到lldb里查看该地址信息
我们发现 43eff0 与对象地址是一样的
那么结果就出来了
0x10043f020 的前32位是强引用计数保存位置,后32位保存的是弱引用计数