Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this inline assembly calling release, retain, and autorelease in libobjc?

The snippet below is taken from Apple's ObjC runtime (libobjc) source code. I wonder what this means exactly. (Not very google-able, sorry)

// HACK -- the use of these functions must be after the @implementation
id bypass_msgSend_retain(NSObject *obj) asm("-[NSObject retain]");
void bypass_msgSend_release(NSObject *obj) asm("-[NSObject release]");
id bypass_msgSend_autorelease(NSObject *obj) asm("-[NSObject autorelease]");

Update:

Here is what a call to bypass_msgSend_release() generates:

movl    -4(%ebp), %eax
movl    %eax, (%esp)
calll   "-[NSObject release]"
like image 753
mojuba Avatar asked May 07 '14 19:05

mojuba


1 Answers

Here's the actual implementation of retain from later in the file:

__attribute__((aligned(16)))
id
objc_retain(id obj)
{
    if (!obj || OBJC_IS_TAGGED_PTR(obj)) {
        goto out_slow;
    }
#if __OBJC2__
    if (((class_t *)obj->isa)->hasCustomRR()) {
        return [obj retain];
    }
    return bypass_msgSend_retain(obj);
#else
    return [obj retain];
#endif
 out_slow:
    // clang really wants to reorder the "mov %rdi, %rax" early
    // force better code gen with a data barrier
    asm volatile("");
    return obj;
}

So if it's a tagged pointer, do nothing. Fair enough, that means it doesn't actually relate to anything on the heap and there is no retain count.

Otherwise in the old days they'd just message retain to the object. Now they message retain to the object if it has been noted to contain a custom retain (no doubt not something the old runtime would record, hence the version check) otherwise they use the bypass method.

The bypass appears to call directly into the known address of [NSObject retain].

So my guess? It's a speed optimisation. If you can tell that there's no custom retain and, in effect, jump straight to the IMP then you save the cost of the dynamic dispatch. Given that the compiler now throws in the C calls automatically under ARC (notably not the Objective-C calls) that means you never go into the more expensive stuff.

like image 148
Tommy Avatar answered Nov 15 '22 01:11

Tommy