Objective-C Tagged Pointer

2986 단어
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
}

위에서 배운 대로 태그MASK는 0x8000000000000000와 같아야 한다. 이것은 함수에 있다. _objc_isTaggedPointer에 설명이 있다.
현재 상기에서 언급한 6가지 대상만 TaggedPointer를 사용하고 있습니다.

참고 자료

  • http://stackoverflow.com/questions/20362406/tagged-pointers-in-objective-c
  • 좋은 웹페이지 즐겨찾기