objc_autoreleaseReturnValue是什么意思? [英] What does objc_autoreleaseReturnValue mean?

查看:61
本文介绍了objc_autoreleaseReturnValue是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法createATestObject.顾名思义,它创建一个对象并返回它.该代码非常简单,位于ARC中.

I have a method createATestObject. As its name indicates, it create an object and return it. The code is very simple and it is under ARC.

- (TestObj *)createATestObj
{
    return [[TestObj alloc] init] ;
}

我汇编文件并在下面获取汇编代码.

I assembly the file and get the assembly code below.

Lfunc_begin4:
    .cfi_startproc
@ BB#0:
    push    {r7, lr}
    mov r7, sp
    sub sp, #8
    @DEBUG_VALUE: -[ViewController createATestObj]:self <- undef
    @DEBUG_VALUE: -[ViewController createATestObj]:_cmd <- undef
    str r0, [sp, #4]
    str r1, [sp]
    movw    r0, :lower16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC4_0+4))
    movt    r0, :upper16:(L_OBJC_CLASSLIST_REFERENCES_$_-(LPC4_0+4))
LPC4_0:
    add r0, pc
    ldr r0, [r0]
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_10-(LPC4_1+4))
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_10-(LPC4_1+4))
LPC4_1:
    add r1, pc
    ldr r1, [r1]
    blx _objc_msgSend
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC4_2+4))
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC4_2+4))
LPC4_2:
    add r1, pc
    ldr r1, [r1]
    blx _objc_msgSend
    add sp, #8
    pop.w   {r7, lr}
    b.w _objc_autoreleaseReturnValue
Ltmp13:
Lfunc_end4:
    .cfi_endproc

我注意到了函数_objc_autoreleaseReturnValue,并从

I noticed the function _objc_autoreleaseReturnValue and get the reference about it from here. But I didn't know what it means. Can anyone elaborate it ? Thanks very much.

id objc_autoreleaseReturnValue(id值);

id objc_autoreleaseReturnValue(id value);

前提条件:value为null或指向有效对象的指针.

Precondition: value is null or a pointer to a valid object.

如果value为null,则此调用无效.否则,它是最好的 努力移交对呼叫对象的保留计数的所有权 到同一对象中的objc_retainAutoreleasedReturnValue 封闭呼叫框.如果这不可能,则该对象为 如上所述自动发布.

If value is null, this call has no effect. Otherwise, it makes a best effort to hand off ownership of a retain count on the object to a call to objc_retainAutoreleasedReturnValue for the same object in an enclosing call frame. If this is not possible, the object is autoreleased as above.

总是返回值.

推荐答案

首先感谢@Darren,感谢您的链接.

Thanks to @Darren first, thanks for your link.

我在链接中引用了一段.

ARC有一个技巧,可以使返回的对象不进入自动释放池 如果呼叫者和被呼叫者都是ARC.

ARC has a trick that keeps returned objects out of autorelease pools if both the caller and callee are ARC.

但是那是怎么工作的呢?之一 ARC的功能是旧的ARC之前编译代码(MRC代码) 可以调用ARC代码,反之亦然.但是,如果ARC代码没有将 MRC代码期望的自动释放池中返回的对象, 那么物体就会泄漏.

But how does that work? One of the features of ARC is that old compiled-before-ARC code (MRC code) can call ARC code and vice-versa. But if ARC code doesn’t put a returned object in an autorelease pool that MRC code is expecting, then the object would just leak.

因此ARC认证的clang代码发出了这个 返回对象时的函数调用: objc_autoreleaseReturnValue(id).

So ARC-ified clang code emits this function call when returning an object: objc_autoreleaseReturnValue(id).

如果你看 objc_autoreleaseReturnValue的实现,它调用 callerAcceptsFastAutorelease().即使您不阅读x86_64或ARM 汇编,代码的注释很简单:

If you look at objc_autoreleaseReturnValue's implementation, it calls callerAcceptsFastAutorelease(). Even if you don’t read x86_64 or ARM assembly, the code’s comment is straight-forward:

/*
  Fast handling of returned autoreleased values.
  The caller and callee cooperate to keep the returned object 
  out of the autorelease pool.

  Caller:
    ret = callee();
    objc_retainAutoreleasedReturnValue(ret);
    // use ret here

  Callee:
    // compute ret
    [ret retain];
    return objc_autoreleaseReturnValue(ret);

  objc_autoreleaseReturnValue() examines the caller's instructions following
  the return. If the caller's instructions immediately call
  objc_autoreleaseReturnValue, then the callee omits the -autorelease and saves
  the result in thread-local storage. If the caller does not look like it
  cooperates, then the callee calls -autorelease as usual.

  objc_autoreleaseReturnValue checks if the returned value is the same as the
  one in thread-local storage. If it is, the value is used directly. If not,
  the value is assumed to be truly autoreleased and is retained again.  In
  either case, the caller now has a retained reference to the value.

  Tagged pointer objects do participate in the fast autorelease scheme, 
  because it saves message sends. They are not entered in the autorelease 
  pool in the slow case.
*/

我身上的东西

让我们看一下objc_autoreleaseReturnValue的源代码.

Let's see the source code of objc_autoreleaseReturnValue.

id 
objc_autoreleaseReturnValue(id obj)
{
#if SUPPORT_RETURN_AUTORELEASE
    assert(tls_get_direct(AUTORELEASE_POOL_RECLAIM_KEY) == NULL);

    if (callerAcceptsFastAutorelease(__builtin_return_address(0))) {
        tls_set_direct(AUTORELEASE_POOL_RECLAIM_KEY, obj);
        return obj;
    }
#endif

    return objc_autorelease(obj);
}

__builtin_return_address(0) 返回当前函数的返回地址,然后让我们看看callerAcceptsFastAutorelease的arm版本的实现:

__builtin_return_address(0) returns the return address of current function, then let's look at the callerAcceptsFastAutorelease's implementation for arm version:

static bool callerAcceptsFastAutorelease(const void *ra)
{
    // if the low bit is set, we're returning to thumb mode
    if ((uintptr_t)ra & 1) {
        // 3f 46          mov r7, r7
        // we mask off the low bit via subtraction
        if (*(uint16_t *)((uint8_t *)ra - 1) == 0x463f) {
            return true;
        }
    } else {
        // 07 70 a0 e1    mov r7, r7
        if (*(uint32_t *)ra == 0xe1a07007) {
            return true;
        }
    }
    return false;
}

在方法中,它会查找mov r7, r7指令,该指令是objc_retainAutoreleaseReturnValue的标记,如果找到该指令,则该方法将返回true,因此被调用方将忽略自动释放.

In the method, it looks for the instruction mov r7, r7 which is a marker for objc_retainAutoreleaseReturnValue, if it find that, then the method return true, so callee will omit the autorelease.

在我的情况下,您可以看到调用方的汇编代码为testFun1.

You can see the assembly code of caller which is testFun1 in my case.

- (void)testFun1:(ViewController *)vc
{
    [vc createATestObj] ;
}

下面是汇编代码,您可以在"mov r7,objc_retainAutoreleaseReturnValue的标记r7 @"行中找到

Below is the assembly code, you can find the line "mov r7, r7 @ marker for objc_retainAutoreleaseReturnValue"

    .cfi_startproc
@ BB#0:
    push    {r7, lr}
    mov r7, sp
    sub sp, #16
    add r3, sp, #4
    movw    r9, #0
    movt    r9, #0
    str r0, [sp, #12]
    str r1, [sp, #8]
    str.w   r9, [sp, #4]
    mov r0, r3
    mov r1, r2
    bl  _objc_storeStrong
    movw    r0, :lower16:(L_objc_msgSend$non_lazy_ptr-(LPC5_0+4))
    movt    r0, :upper16:(L_objc_msgSend$non_lazy_ptr-(LPC5_0+4))
LPC5_0:
    add r0, pc
    ldr r0, [r0]
    movw    r1, :lower16:(L_OBJC_SELECTOR_REFERENCES_12-(LPC5_1+4))
    movt    r1, :upper16:(L_OBJC_SELECTOR_REFERENCES_12-(LPC5_1+4))
LPC5_1:
    add r1, pc
Ltmp14:
    ldr r2, [sp, #4]
    ldr r1, [r1]
    str r0, [sp]                @ 4-byte Spill
    mov r0, r2
    ldr r2, [sp]                @ 4-byte Reload
    blx r2
    @ InlineAsm Start
    mov r7, r7      @ marker for objc_retainAutoreleaseReturnValue
    .code   16
    @ InlineAsm End
    bl  _objc_retainAutoreleasedReturnValue
    bl  _objc_release
    movs    r1, #0
    movt    r1, #0
    add r0, sp, #4
    bl  _objc_storeStrong
    add sp, #16
    pop {r7, pc}
Ltmp15:
Lfunc_end5:
    .cfi_endproc

更新:

我认为苹果的实现的注释中存在一些错误.

正确的注释应该是这样的:

The correct comment should be like this:

/*
  Fast handling of returned autoreleased values.
  The caller and callee cooperate to keep the returned object 
  out of the autorelease pool.

  Caller:
    ret = callee();
    objc_retainAutoreleasedReturnValue(ret);
    // use ret here

  Callee:
    // compute ret
    [ret retain];
    return objc_autoreleaseReturnValue(ret);

  objc_autoreleaseReturnValue() examines the caller's instructions following
  the return. If the caller's instructions immediately call
  objc_retainAutoreleasedReturnValue, then the callee omits the -autorelease and saves
  the result in thread-local storage. If the caller does not look like it
  cooperates, then the callee calls -autorelease as usual.

  objc_retainAutoreleasedReturnValue checks if the returned value is the same as the
  one in thread-local storage. If it is, the value is used directly. If not,
  the value is assumed to be truly autoreleased and is retained again.  In
  either case, the caller now has a retained reference to the value.

  Tagged pointer objects do participate in the fast autorelease scheme, 
  because it saves message sends. They are not entered in the autorelease 
  pool in the slow case.
*/

如果您有其他想法,请发表评论.谢谢!

Leave a comment if you have other ideas. Thank you!

这篇关于objc_autoreleaseReturnValue是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆