此文实际成于 2015/07/30
目前在 objc4/runtime/objc-internal.h
中描述以以下 Tagged pointer 对象。
{
OBJC_TAG_NSAtom = 0,
OBJC_TAG_1 = 1,
OBJC_TAG_NSString = 2,
OBJC_TAG_NSNumber = 3,
OBJC_TAG_NSIndexPath = 4,
OBJC_TAG_NSManagedObjectID = 5,
OBJC_TAG_NSDate = 6,
OBJC_TAG_7 = 7
};
Tagged pointer 的位分布
// Tagged pointer layout and usage is subject to change
// on different OS versions. The current layout is:
// (MSB)
// 60 bits payload
// 3 bits tag index
// 1 bit 1 for tagged pointer objects, 0 for ordinary objects
// (LSB)
下面是对应生成 Tagged Pointer 的函数:
static inline void *
_objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
{
// assert(_objc_taggedPointersEnabled());
// assert((unsigned int)tag < 8);
// assert(((value << 4) >> 4) == value);
// 0xf << 60: 1111000000000000000000000000000000000000000000000000000000000000
// ~(0xf << 60) 0000111111111111111111111111111111111111111111111111111111111111
// tag << 60: 0001000000000000000000000000000000000000000000000000000000000000
// 1 << 63 : 1000000000000000000000000000000000000000000000000000000000000000
// 假充 value: 0000000000000000000000000000000000000111101010111100001100000000
// tagged pointer: 1001000000000000000000000000000000000111101010111100001100000000
// ox80 1000000000000000000000000000000000000000000000000000000000000000
return (void*)((1UL << 63) | ((uintptr_t)tag << 60) | (value & ~(0xFUL << 60)));
}
判断的时候是将其先转成一个 int型来判断:
static inline bool
_objc_isTaggedPointer(const void *ptr)
{
return (intptr_t)ptr < 0; // a.k.a. ptr & 0x8000000000000000
}
获得 Tagged Pointer 在某一个指针上的Tag
static inline objc_tag_index_t
_objc_getTaggedPointerTag(const void *ptr)
{
// assert(_objc_isTaggedPointer(ptr));
return (objc_tag_index_t)(((uintptr_t)ptr >> 60) & 0x7);
}
获得 Tagged Pointer 实际用作指针的值。
static inline uintptr_t
_objc_getTaggedPointerValue(const void *ptr)
{
// assert(_objc_isTaggedPointer(ptr));
return (uintptr_t)ptr & 0x0fffffffffffffff;
}
是否是 Tagged Pointer 的判断。
经常的 objc4 开源代码看到对下面方法的调用:
inline bool
objc_object::isTaggedPointer()
{
#if SUPPORT_TAGGED_POINTERS
return ((uintptr_t)this & TAG_MASK);
#else
return false;
#endif
}
根据上面的学习 TAG_MASK 应该等于 0x8000000000000000
这在函数: _objc_isTaggedPointer
中有说明。
目前只有上面提到的6种类的对象是使用的 TaggedPointer