2011-11-19 7 views
13
  1. LLVM có tự động chuyển đổi các phương thức Objective-C thành các hàm nội tuyến khi có thể không?LLVM có chuyển đổi các phương thức Objective-C thành các hàm nội tuyến không?

    (Tức là, nó cũng giống như performant để tạo ra một phương pháp Objective-C cho một khối mã mà bạn nếu không có thể dán inline?)

  2. Nếu LLVM không thực hiện tối ưu hóa này, tại sao không? Nếu có, (a) có một số cài đặt xây dựng nhất định mà tôi phải đặt để điều này xảy ra không? (b) Làm thế nào tôi có thể nói nếu một phương pháp Objective-C sẽ được inlined?

Trả lời

12

Không, bởi vì không thể biết trong ngữ cảnh thời gian chạy Obj-C nếu các loại tối ưu hóa đó có thể được thực hiện. Điều cần ghi nhớ là các phương thức Obj-C được gọi bởi một tin nhắn gửi đi, những thông điệp này có thể đến từ nhiều hơn là cú pháp [myObject doSomething].

Hãy xem xét [obj performSelector:NSSelectorFromString(@"hello")] thực tế là điều này có thể xảy ra có nghĩa là không thể bao giờ nội tuyến bất kỳ phương pháp nào.

Ngoài ra còn có một chuỗi các sự kiện xảy ra khi một tin nhắn được nhận bởi một lớp, những sự kiện này có thể định tuyến lại hoặc thậm chí thay đổi thông báo đang được gửi. Điều này xảy ra trong suốt bên dưới tin nhắn gửi đi.

+0

Tại sao LLVM không thể thay thế cuộc gọi thông thường, ví dụ: '[obj x]; Các lệnh gọi hàm obj.x' và 'performSelector', ví dụ:' [obj performSelector: x_sel] ', v.v., với thân phương thức' x'? Và, tại sao nó không thể kiểm tra việc thực hiện các phương thức như 'forwardInvocation:' để xác định xem nó có nên inline không? C'mon LLVM, thông minh hơn! :) – ma11hew28

+7

Bởi vì chúng có thể được hoán đổi trong thời gian chạy trivially. Tôi có thể thay đổi implenentafion của bất kỳ phương thức nào trong 3 hoặc 4 dòng mã thời gian chạy. –

9

số Đây là một tính năng thiết yếu của Objective-C rằng thông điệp của công văn (nhớ rằng trong obj-C bạn gửi một thông điệp, bạn không gọi một phương pháp) xảy ra động trong thời gian chạy, không lúc biên dịch thời gian.

Vì điều này, việc gửi tin nhắn trong Obj-C sẽ luôn chậm hơn một chút so với cuộc gọi hàm thuần túy (ngay cả khi chức năng không được gạch chân).

9

Giả sử trong một khoảnh khắc mà các trình biên dịch inlines một phương pháp:

@implementation AwesomeClass 

- (void)doFoo OBJC_INLINE { // or some way to indicate "this is an inline method" 
    NSLog(@"doing foo!"); 
} 

- (void)doBar { 
    [self doAwesomeStuff]; 
    [self doFoo]; 
} 

@end 

để -doBar về cơ bản trở thành:

- (void)doBar { 
    [self doAwesomeStuff]; 
    { 
    NSLog(@"doing foo!"); 
    } 
} 

Awesome, mà có vẻ như nó muốn được nhanh hơn, đúng không? Chúng tôi tiết kiệm cho mình cả tá hướng dẫn bằng cách không gọi số objc_msgSend. Vì vậy, bạn gói này lên và đăng nó trực tuyến như là một tập tin .a.

NSCleverCoder đến cùng và nói "nhưng tôi muốn doFoo phải làm nhiều hơn một chút", vì vậy anh ta:

@interface SuperAwesomeClass : AwesomeClass @end 
@implementation SuperAwesomeClass 
- (void)doFoo { 
    NSLog(@"doing more foo!"); 
    [super doFoo]; 
} 
@end 

Khi ông cố gắng chạy này, nó không bao giờ được gọi, vì AwesomeClass không bao giờ thực sự gọi phương thức -doFoo.

"Nhưng," bạn nói, "đây là một ví dụ giả tạo!"

Không, không phải. Trong Objective-C, nó là hoàn toàn hợp pháp để làm điều này tại bất kỳ điểm nào trong việc phát triển hoặc thực hiện một ứng dụng. Tôi có thể làm điều này khi viết mã. Heck, tôi thậm chí có thể làm điều này trong thời gian chạy bằng cách sử dụng objc_allocateClassPairclass_addMethod để tạo động một lớp con và thêm ghi đè phương thức.

Tôi cũng có thể triển khai phương pháp gây rối.Không thích triển khai hiện tại của -doFoo? Đó là mát mẻ; hãy tự di chuyển nó đi. Oh chờ đợi; nếu phương pháp được inlined, triển khai mới của bạn sẽ không bao giờ được gọi, bởi vì -doBar không bao giờ thực sự gọi phương thức -doFoo.

chỉ lần tôi có thể thấy điều này là có thể nếu có cách nào đó để chú thích một phương thức không thể ghi đè. But there's no way to do that, do đó vấn đề đó là tranh luận. Và thậm chí sau đó, nó vẫn sẽ là một ý tưởng tồi; chỉ vì trình biên dịch không cho phép bạn làm điều đó không có nghĩa là bạn không thể làm việc xung quanh nó khi chạy. Và một lần nữa, bạn sẽ gặp rắc rối.

+0

Tôi đoán tôi chỉ nghĩ rằng trình biên dịch có thể phát hiện các trường hợp như vậy mà phương thức đang được gọi trong một phương thức ghi đè và cũng chèn nó vào phương thức ghi đè ... Nhưng, tôi có thể thấy cách trình biên dịch phải khá thông minh làm việc đó đi. Tuy nhiên ... ARC là khá tuyệt vời ... Có lẽ họ có thể thêm một tính năng mát mẻ để LLVM mà biết làm thế nào để inline phương pháp. – ma11hew28