2014-05-07 10 views
8

Il frammento di seguito è preso dal codice sorgente di Apple ObjC runtime (libobjc). Mi chiedo cosa significhi esattamente. (Non molto google-grado, sorry)Perché questo assembly inline chiama release, retain e autorelease in libobjc?

// 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]"); 

Aggiornamento:

Ecco quello che una chiamata a bypass_msgSend_release() genera:

movl -4(%ebp), %eax 
movl %eax, (%esp) 
calll "-[NSObject release]" 
+1

Quelle sembrano invocazioni esplicite di conservazione, rilascio e autorelease, per aggirare il desiderio del compilatore di opporsi allo stesso. Per quanto riguarda il motivo per cui sono presenti, non ne ho idea. –

+0

In che file si trova? –

+0

http://opensource.apple.com/source/objc4/objc4-532.2/runtime/NSObject.mm –

risposta

4

Ecco l'effettiva attuazione del retain da tardi nel 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; 
} 

Quindi, se si tratta di un puntatore con tag, non fare nulla. Abbastanza corretto, ciò significa che in realtà non si riferisce a nulla sullo heap e non vi è alcun numero di ritenzione.

Altrimenti, ai vecchi tempi, avevano appena inviato il messaggio retain all'oggetto. Ora inviano il messaggio retain all'oggetto se è stato annotato che contiene un numero personalizzato retain (senza dubbio non qualcosa che il vecchio runtime registra, quindi il controllo della versione) altrimenti utilizza il metodo bypass.

Il bypass sembra chiamare direttamente l'indirizzo noto di [NSObject retain].

Quindi la mia ipotesi? È un'ottimizzazione della velocità. Se è possibile affermare che non è disponibile la conservazione personalizzata e che, in effetti, passa direttamente a IMP, si risparmia il costo della spedizione dinamica. Dato che il compilatore ora lancia le chiamate C automaticamente sotto ARC (in particolare non le chiamate Objective-C), significa che non si entra mai nelle cose più costose.

+0

Questo ha molto senso e spiega 'bypass_msgSend_'. Basta saltare lì, dang it! : D –

Problemi correlati