Does LLVM LTO(Link-time Optimization) have any impact on Objective-C codes? - objective-c

AFAIK, LTO can reduce dead codes and do some cross-file inlining. However,
Objective-C is based on runtime. Whether a method is indeed called is resolved until runtime, so it's not possible to reduce dead methods in Objective-C at link time, right? For cross-file inlining, it couldn't happen either as a method's implementation can be replaced during runtime.
So, how could LTO affect Objective-C codes?
I'm new to LLVM, so any advice is appreciated.

Related

Is it possible to see Objective-C ARC output?

In xcode, it's possible given some Objective-C code, to see the code it would output in Assembly.
Is it possible to see given ARC enabled code, to see the Objective-C that would be outputted by ARC?
It is not possible, because ARC does not produce Objective-C code. ARC is a compiler feature that modifies the assembly produced in the same way that enabling optimizations might do. You can't tell the compiler to show you "optimized" C code; the optimizations are not applied at the level of C code. Likewise, you cannot ask to see the "ARC-ified" Objective-C, because the ARC memory management calls are not applied at the level of Objective-C code.
If you really want to see where the memory management calls are being made, you'll have to look at the assembly.
ARC doesn't as such output Objective-C, it a phase of the compiler which alters the assembler/machine code the compiler produces - and as you noted you can see that in Xcode. However if you use a decompiler on the binary you should see a "MRC equivalent", which is as good as you'll get. Try Hopper - demo available, I've not used it myself, don't know the producers, etc. However it produces psuedo-code, which looks like structured assembly, not Objective-C. HTH.

ARC with non-Foundation Objects

I have made my own Objective-C base class to use in Objective-C projects (without Foundation/Cocoa classes or API). While I don't mind writing my own retains and releases, it's a tedious process so I'm wondering if I can use ARC with my custom classes.
Specifically:
Is it possible to use ARC with custom classes?
Do my reference-counting selectors have to be called retain and release (and autorelease)?
What additional requirements are there to make ARC work as expected for custom classes (other than including the -fobjc-arc argument when compiling)?
Is it possible to use ARC with custom classes?
Of course it is.
Do my reference-counting selectors have to be called retain and release (and autorelease)?
Yes, they do. Apple has hardcoded the method names of its favorite Objective-C library (Foundation) into the compiler. Damn bad programming pattern, isn't it?
What additional requirements are there to make ARC work as expected for custom classes (other than including the -fobjc-arc argument when compiling)?
As far as I know, nothing.

How to programmatically detect automatic reference counting?

This might be a silly question, but I just wanted to know. I want my code to detect if ARC is enabled, programmatically. How do I do that? Is there is any flag that I could check? Actually the problem is that, I have written an open-source library. I have used release and retain in it. if some one else uses my library files using ARC enabled, I dont want them to get any errors. how do I achieve this? or is there any possible ways I can provide any tools to compile my library before using it?
#if !__has_feature(objc_arc)
//Do manual memory management...
#else
//Usually do nothing...
#endif
This is of course a compile-time check, you cannot check for ARC at runtime.
An alternative would be to set the -fno-objc-arc compiler flag for your files that use manual memory management in a project that otherwise uses ARC.
Whether you want to bother with this at all or just use ARC everywhere depends on how backward-compatible you want/need to be. Code that supports both ARC and MRC can get quite hard to read and maintain.
You don't detect it programmatically, it operates based on translations. That is, it is not like Garbage Collection -- which is process-wide, required all linked libraries to support (and implement it correctly in that mode). You can have some files compiled with ARC, and some without.
However, you can detect it at compilation.
As far as the distribution of your library: I would not bother with a translation based system, where ref count ops are conditionally enabled. I would (personally) just support one model (MRC in your case, until you choose to migrate it to ARC), then expect people to link to the library, or if they compile it in a target they configure, to disable ARC. Conditionally enabling/disabling code based on the presence of a feature is asking for tough bugs, particularly when it's likely to affect 9% of your library's lines of code.
NO, you can't, Xcode would not compile in ARC projects if your source uses retain-release

Why is 'no known method for selector x' a hard error under ARC?

Maybe it's useful if calling a method that MyClass doesn't understand on a something typed MyClass is an error rather than a warning since it's probably either a mistake or going to cause mistakes in the future...
However, why is this error specific to ARC? ARC decides what it needs to retain/release/autorelease based on the cocoa memory management conventions, which would suggest that knowing the selector's name is enough. So it makes sense that there are problems with passing a SEL variable to performSelector:, as it's not known at compile-time whether the selector is an init/copy/new method or not. But why does seeing this in a class interface or not make any difference?
Am I missing something about how ARC works, or are the clang warnings just being a bit inconsistent?
ARC decides what it needs to retain/release/autorelease based on the cocoa memory management conventions, which would suggest that knowing the selector's name is enough.
This is just one way that ARC determines memory management. ARC can also determine memory management via attributes. For example, you can declare any typedef retainable using __attribute__((NSObject)) (never, ever do this, but it's legal). You can also use other attributes like __attribute((ns_returns_retained)) and several others to override naming conventions (these are things you might reasonably do if you couldn't fix the naming; but it's much better to fix the naming).
Now, imagine a case where you failed to include the header file that declares these attributes in some files but not others. Now, some compile units (.m files) memory manage it one way and some memory manage it another. Hijinks ensure. This is much, much worse than the situation without ARC, and the resulting bugs would be mindbending because some ARC code would do one thing and other ARC code would do something different.
So, yeah, don't do that. (Of course you should never ignore warnings in Objective-C anyway, but this is a particularly nasty situation.)
It's an ounce of prevention, I'd assume. Incidentally, it's not foolproof in larger systems because selectors do not need to match and matching is all based on the translation, so it could still blow up on you if you are not writing your program such that it introduces type safety. Something is better than nothing, though!
The compiler wants to know about parameters and return types, potentially annotations and out parameters. ObjC has defaults to fall back on, but it's a good source of multiple types of bugs as the compiler does more for you.
There are a number of reasons you should introduce type safety and turn up the warning levels. With ARC, there are even more. Regardless of whether it is truly necessary, it's a good direction for an objc compiler to move towards (IMHO). You might consider C99 safer than ObjC 2.0 in this regard ;)
If there really is a restriction for codegen, I'd like to hear it.

What determines the process by which unimplemented methods are resolved?

As I understand it, an unimplemented method gets resolved in the following way:
resolveInstanceMethod: / resolveClassMethod: gets a chance to implement the method
forwardingTargetForSelector: gets a chance to forward to a delegate
forwardInvocation: gets a chance to handle the method as it sees fit.
Where is this three-step process defined? I'd like to handle it myself as NSInvocation might be too heavyweight for my needs. I've had a poke around the runtime source and can't really see anything.
It looks like the old runtime would call forward:args: on the receiver, to do this but that seems to have gone from the new one. I'm guessing that the process must be defined by the framework rather than the runtime, since it'd be strange if the runtime depended on Cocoa to the extent of requiring NSInvocation to handle messages. Is it maybe an undocumented method that gets called on NSObject / NSProxy?
Edit:
It looks like the runtime declares, but never defines, a C function which is called when objc_msgSend can't find an implementation:
id objc_msgForward(id object,SEL message,...);
I don't work for Apple, so I don't know how Foundation implements this, but at least in the case of Cocotron, they use:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,#selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,#selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
adding a forwardSelector:arguments: method doesn't seem to work, so I'm guessing this is specific to Cocotron. Anyone know what objc_msgForward does in Foundation?
I'm writing something a bit like a
scripting language that uses message
forwarding to interface with
objective-c. For now, I'm using
NSInvocation, but it could end up
doing this thousands of times per
second, so the overhead would be
noticeable. But I guess I'm also just
curious...
As far as message forwarding is concerned, the behavior is [often subtly] different across different platforms and versions of the runtime.
In any case, don't re-invent the wheel. There are two language bridges available today that do pretty close to full-fidelity bridging from which you can learn a ton. Both have liberal licenses specifically to allow for such re-use.
Specifically, the MacRuby project offers a Ruby implementation that sits on top of CoreFoundation and the Objective-C Garbage Collector. It is the "most native" bridge available (and not terribly portable as a result -- not a goal of the project).
The PyObjC bridge is the best example available of a high fidelity bridge between the Objective-C runtime and another dynamic OO language's runtime; Python. It is a bit more portable, though the non-Mac OS X bits have likely rotted somewhat.
(I would be remiss in not mentioning F-Script; a new language built on Objective-C for which, I believe, the source is/was available?)
All of the bridges deal with both method forwarding, subclassing and cross-runtime proxying, all of which sound like they are applicable to your particular needs.