Search code examples
objective-carmclang

Why does Clang for arm64 move the frame pointer into itself before every objc_retainAutoreleasedReturnValue call when ARC is on?


When ARC is on, clang for arm64 produces the following in between each objc_msgSend and corresponding objc_retainAutoreleasedReturnValue:

MOV X29, X29

X29 is, of course, the frame pointer; from what I can tell, this instruction does nothing.

Any idea why the compiler does this?

The only clue I could find in Google are the MAGIC and NOT_MAGIC definitions here: http://opensource.apple.com//source/objc4/objc4-680/test/rr-autorelease-fastarc.m . But that doesn't seem to elucidate much.


Solution

  • This is the autorelease optimization mechanism.

    static ALWAYS_INLINE bool callerAcceptsOptimizedReturn(const void *ra) {
    // fd 03 1d aa mov fp, fp
    // arm64 instructions are well-aligned
    if (*(uint32_t *)ra == 0xaa1d03fd) {
        return true;
    }
    return false;
    

    }

    If the statement at the return address is mov x29, x29, optimization can be performed. This statement is inserted by the compiler. When the compiler finds that the current control flow can be optimized, it will insert a mov x29, x29 after the branch jump statement as Optimization Flag to dynamically execute autorelease optimization logic at runtime.

    The callee's recognition of the optimized caller is architecture-dependent. x86_64: Callee looks for mov rax, rdi followed by a call or jump instruction to objc_retainAutoreleasedReturnValue or objc_unsafeClaimAutoreleasedReturnValue.

    i386: Callee looks for a magic nop movl %ebp, %ebp (frame pointer register)

    armv7: Callee looks for a magic nop mov r7, r7 (frame pointer register).

    arm64: Callee looks for a magic nop mov x29, x29 (frame pointer register).

    [reference: https://developer.aliyun.com/article/713747]