Objective-C Tagged Pointer

此文实际成于 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

参考

  1. http://stackoverflow.com/questions/20362406/tagged-pointers-in-objective-c
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容