objc4源码解析&alloc

objc4源码基于779.1版本。文章纯属个人学习见解,谬误之处,望指正。

alloc

方法调用栈

    • (id)alloc
      • _objc_rootAlloc()
        • callAlloc()
          • _objc_rootAllocWithZone()
            • _class_createInstanceFromZone()
              • cls->instanceSize()
              • malloc_zone_calloc | calloc
              • obj->initInstanceIsa()
              • obj->initIsa()
              • object_cxxConstructFromClass()

源代码详注

  1. NSObject.mm - line:2317
+ (id)alloc {
    return _objc_rootAlloc(self);
}
复制代码
  1. NSObject.mm - line:1718
id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
复制代码
  1. NSObject.mm - line:1697
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
// Objective-C 2.0
#if __OBJC2__
    // 判空
    if (slowpath(checkNil && !cls)) return nil;
    // 本类或超类是否实现alloc/allocWithZone,没有则默认调用元类
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
复制代码
  1. objc-runtime-new.mm - line:7440
NEVER_INLINE
id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
    // allocWithZone under __OBJC2__ ignores the zone parameter
    return _class_createInstanceFromZone(cls, 0, nil,
                                         OBJECT_CONSTRUCT_CALL_BADALLOC);
}
复制代码
  1. objc-runtime-new.mm - line:7386
static ALWAYS_INLINE id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
                              int construct_flags = OBJECT_CONSTRUCT_NONE,
                              bool cxxConstruct = true,
                              size_t *outAllocatedSize = nil)
{
    // 类对象本身没有被实现,则终止程序
    ASSERT(cls->isRealized());

    // Read class's info bits all at once for performance
    // 是否有C++构造器
    bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
    // 是否有C++析构器
    bool hasCxxDtor = cls->hasCxxDtor();
    // 是否可分配优化指针
    bool fast = cls->canAllocNonpointer();
    size_t size;

    // 初始化大小计算
    size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    // 分配内存空间
    if (zone) {
        // 根据给定的 zone 和 size 分配内存
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        // 分配为0的内存
        obj = (id)calloc(1, size);
    }
    
    // 分配失败
    if (slowpath(!obj)) {
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            // 处理程序内部分配失败
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }

    // 初始化isa_t
    if (!zone && fast) {
        // 初始化优化指针
        obj->initInstanceIsa(cls, hasCxxDtor);
    } else {
        // Use raw pointer isa on the assumption that they might be
        // doing something weird with the zone or RR.
        // 初始化普通指针
        obj->initIsa(cls);
    }

    // 没有构造器,则返回对象
    if (fastpath(!hasCxxCtor)) {
        return obj;
    }

    construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
    // 从子类到超类的递归地调用对象C++构造方法
    return object_cxxConstructFromClass(obj, cls, construct_flags);
}
复制代码
  1. objc-runtime-new.h - line:1497
size_t instanceSize(size_t extraBytes) const {
        if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
            return cache.fastInstanceSize(extraBytes);
        }
        
        // 字节对齐 + 额外字节
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        // 最小16字节
        if (size < 16) size = 16;
        return size;
    }
复制代码
  1. objc-object.h - line:215
inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    ASSERT(!cls->instancesRequireRawIsa());
    ASSERT(hasCxxDtor == cls->hasCxxDtor());
    // 初始化isa指针
    initIsa(cls, true, hasCxxDtor);
}
复制代码
  1. objc-object.h - line:224
inline void 
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{ 
    ASSERT(!isTaggedPointer()); 
    
    // nonpointer false:普通指针 true:优化指针
    if (!nonpointer) {
        // 初始化普通指针
        isa = isa_t((uintptr_t)cls);
    } else {
        ASSERT(!DisableNonpointerIsa);
        ASSERT(!cls->instancesRequireRawIsa());

        // 初始化优化指针
        isa_t newisa(0);

#if SUPPORT_INDEXED_ISA
        // 支持类表索引
        ASSERT(cls->classArrayIndex() > 0);
        newisa.bits = ISA_INDEX_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.indexcls = (uintptr_t)cls->classArrayIndex();
#else
        newisa.bits = ISA_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.shiftcls = (uintptr_t)cls >> 3;
#endif

        // This write must be performed in a single store in some cases
        // (for example when realizing a class because other threads
        // may simultaneously try to use the class).
        // fixme use atomics here to guarantee single-store and to
        // guarantee memory order w.r.t. the class index table
        // ...but not too atomic because we don't want to hurt instantiation
        isa = newisa;
    }
}
复制代码
  1. objc-class.mm - line:487
id 
object_cxxConstructFromClass(id obj, Class cls, int flags)
{
    ASSERT(cls->hasCxxCtor());  // required for performance, not correctness

    id (*ctor)(id);
    Class supercls;

    supercls = cls->superclass;

    // Call superclasses' ctors first, if any.
    // 父类是否有C++构造方法
    if (supercls  &&  supercls->hasCxxCtor()) {
        // 递归调用父类构造方法
        bool ok = object_cxxConstructFromClass(obj, supercls, flags);
        // 失败返回 nil
        if (slowpath(!ok)) return nil;  // some superclass's ctor failed - give up
    }

    // Find this class's ctor, if any.
    // 调用当前类的SEL_cxx_construct方法
    ctor = (id(*)(id))lookupMethodInClassAndLoadCache(cls, SEL_cxx_construct);
    // 构造方法为转发方法,则返回
    if (ctor == (id(*)(id))_objc_msgForward_impcache) return obj;  // no ctor - ok
    
    // Call this class's ctor.
    if (PrintCxxCtors) {
        _objc_inform("CXX: calling C++ constructors for class %s", 
                     cls->nameForLogging());
    }
    
    // 调用C++构造方法且成功则返回对象
    if (fastpath((*ctor)(obj))) return obj;  // ctor called and succeeded - ok

    supercls = cls->superclass; // this reload avoids a spill on the stack

    // This class's ctor was called and failed.
    // Call superclasses's dtors to clean up.
    // 调用失败处理
    if (supercls) object_cxxDestructFromClass(obj, supercls);
    if (flags & OBJECT_CONSTRUCT_FREE_ONFAILURE) free(obj);
    if (flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
        return _objc_callBadAllocHandler(cls);
    }
    return nil;
}
复制代码

init

  1. NSObject.mm line:2331
- (id)init {
    return _objc_rootInit(self);
}
复制代码
  1. NSObject.mm line:1830
id
_objc_rootInit(id obj)
{
    // In practice, it will be hard to rely on this function.
    // Many classes do not properly chain -init calls.
    // 没有其他操作行为,就返回参数对象
    return obj;
}
复制代码

new

  1. NSObject.mm line:2245
+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}
复制代码

new方式和alloc+init方式在本质上并没有什么不同

源代码会常见到两个宏定义

#define fastpath(x) (__builtin_expect(bool(x), 1))
#define slowpath(x) (__builtin_expect(bool(x), 0))
复制代码

__builtin_expect(EXP,N)是gcc提供的指令。意思是说fastpath中x的值大概率为真,slowpath中x的值大概率为假。

通过此指令优化编译器在编译时的代码布局,减少指令跳转带来的性能消耗。

malloc与calloc区别

两者都是动态分配内存。主要的不同是malloc不初始化分配的内存,已分配的内存中可以是任意的值。calloc 初始化已分配的内存为0。

猜你喜欢

转载自juejin.im/post/7034815978374594596