2014-05-07 16 views
8

Đoạn mã dưới đây được lấy từ mã nguồn thời gian chạy ObjC (libobjc) của Apple. Tôi tự hỏi điều này có ý nghĩa gì. (Không phải rất google-thể, xin lỗi)Tại sao lắp ráp nội tuyến này gọi phát hành, giữ lại và tự động trả lời trong 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]"); 

Cập nhật:

Đây là những gì một cuộc gọi đến bypass_msgSend_release() tạo ra:

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

Chúng xuất hiện để được yêu cầu rõ ràng về giữ lại, phát hành và tự động chạy, để phá vỡ mong muốn của trình biên dịch đối tượng giống nhau. Về lý do tại sao họ có mặt, tôi không có một đầu mối. –

+0

Tệp này có ở đâu? –

+0

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

Trả lời

4

Đây là việc thực hiện thực tế của retain từ sau trong tệp:

__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; 
} 

Vì vậy, nếu đó là một con trỏ được gắn thẻ, không làm gì cả. Đủ công bằng, điều đó có nghĩa là nó không thực sự liên quan đến bất cứ thứ gì trên heap và không có số lượng giữ lại.

Nếu không trong những ngày cũ, họ chỉ cần nhắn tin retain cho đối tượng. Bây giờ họ nhắn tin retain cho đối tượng nếu nó đã được ghi chú có chứa một tùy chỉnh retain (không có nghi ngờ không phải là một cái gì đó thời gian chạy cũ sẽ ghi lại, do đó kiểm tra phiên bản) nếu không họ sử dụng phương pháp bỏ qua.

Đường vòng xuất hiện để gọi trực tiếp vào địa chỉ đã biết của [NSObject retain].

Vì vậy, tôi đoán? Đó là một tối ưu hóa tốc độ. Nếu bạn có thể nói rằng không có tùy chỉnh giữ lại và, trong thực tế, nhảy thẳng đến IMP sau đó bạn tiết kiệm chi phí của công văn năng động. Cho rằng trình biên dịch bây giờ ném trong C cuộc gọi tự động dưới ARC (đáng chú ý không phải là các cuộc gọi Objective-C) có nghĩa là bạn không bao giờ đi vào những thứ đắt tiền hơn.

+0

Điều này có ý nghĩa rất nhiều và giải thích 'bypass_msgSend_'. Chỉ cần nhảy ở đó, dang nó! : D –

Các vấn đề liên quan