An Illustrated History of objc_msgSend

<<   Tiger PowerPC   |   index   |   Leopard   >>

i386: Tiger and later

Tiger
_objc_msgSend:                                                             
        movl   0x4(%esp), %eax        load self                            
        testl  %eax, %eax             if (self == nil)                     
        je     NIL                        return zero                      
        movl   (%eax), %eax           class = self->isa                    
        movl   8(%esp), %ecx          load _cmd                            
        pushl  %edi                   save non-volatile register           
        movl   32(%eax), %eax         cache = class->cache                 
        pushl  %esi                   save non-volatile register           
        leal   8(%eax), %edi          buckets = cache->buckets             
        movl   (%eax), %esi           mask = cache->mask                   
        movl   %ecx, %edx                                                  
        shrl   $2, %edx               index = _cmd * 4                     
 LOOP:  andl   %esi, %edx             index &= mask                        
        movl   (%edi, %edx, 4), %eax  method = buckets[index]              
        testl  %eax, %eax             if (method == nil)                   
        je     MISS                       goto cache miss                  
        cmpl   (%eax), %ecx           if (method->sel == _cmd)             
        je     HIT                        goto cache hit                   
        addl   $1, %edx               index++                              
        jmp    LOOP                   scan more                            
        [...]                                                              
 HIT:   movl   8(%eax), %eax          imp = method->imp                    
        popl   %esi                   restore saved registers              
        popl   %edi                                                        
        movl   $1, %edx               set non-struct return for forwarding 
        jmpl   *%eax                  jump to imp                          

Tiger introduced the 32-bit Intel architecture. This architecture was previously supported at NeXT, and the Mac OS X code was based on that implementation. The code was probably originally written for NeXT by an engineer who was familiar with load-store architectures like PowerPC but not so familiar with register-memory architectures like x86, and was later adapted to Mac OS X by someone who also did not know x86 well (/me raises his hand).

Those of you who do know x86 better may be able to identify some of the inefficiencies in this code. 32-bit x86 was quickly overtaken by 64-bit, so this code received little attention after Tiger and many of those inefficiencies remain to this day. We will not follow it further.

<<   Tiger PowerPC   |   index   |   Leopard   >>