[cfe-dev] [Proposal]: Devirtualizing local methods (messages) in final class in Objective-C

John McCall via cfe-dev cfe-dev at lists.llvm.org
Tue Sep 11 22:24:47 PDT 2018



> On Sep 12, 2018, at 12:09 AM, Aditya K <hiraditya at msn.com> wrote:
> 
> 
>> Objective-C allows method implementations to be replaced  dynamically.  It is not obvious that `objc_subclassing_restricted` in  any > way prevents either this or similar techniques where a dynamic  subclass is formed in order to change the implementation of a 
>> method  on a particular instance.
> 
> Can we revise the semantics of `objc_subclassing_restricted` to disallow subclassing dynamically?

No.  In general, we can't take existing attributes and make them mean something much stronger.

>> Objective-C also allows the class of a particular instance to be  changed, although I think it would be fair to restrict this to ensure  
>> that the new class is related in some reasonable way to the old class —  probably that it must have the old class (ignoring  dynamic > subclasses) as a superclass.
> 
> Yes, I guess while utilizing some of the super-dynamic behavior of Objective-C, it may be tricky to take advantage of devirutalization. We may need to have proper documentation etc. to make the programmers aware of the expected behavior as a result of this optimization.

It needs to be opt-in.  You can't really fix "we changed the basic semantics of the language" with documentation.

>> There are some other concerns that apply to devirtualization in general, but not to your restricted case:
>>   - The receiver of a message send is generally allowed to be `nil`.
> That was the reason why I restricted the optimization to work only for messages passed to self because, IIUC, self cannot be nil.

That seems reasonable.  It also prevents proxy objects.

>>   - Objective-C is not strongly typed.  Instance-variable accesses  have C-like restrictions, but otherwise static type information is  
>> defined to only be meaningful for determining the type signature for  message sends, not for determining the actual dynamic  type. > For example, several major libraries rely on the ability to  create "proxy" objects that transparently forward most messages to  
>> another object.
> 
>> Ultimately, while I think devirtualization would be very powerful  in Objective-C, I think it really needs to be opted-in in some more  
>> explicit way.
> 
> We can have a compiler flag to enable Objective-C devirtualization. Additionally we can introduce an __attribute__((objc_local_method)) to enable finer grained control of devirtualization.

I don't think an optimization that globally miscompiles Objective-C's dynamic features unless an attribute is used to suppress it is ever going to be acceptable, even if it's an opt-in flag.  So given that the optimization has to be opt-in with some new attribute, I don't think the flag adds anything.

> Thanks for the review, I can start putting the patches for review if you think the overall approach seems reasonable.

I haven't really thought about the technical approach.  Assorted thoughts:
- The attribute could maybe just be the "inline" keyword, which both seems appropriate and is not otherwise used on Objective-C methods.
- You need some way to make synthesized property accessors inlinable.
- For the specific purpose of inlining privately-declared methods of the same class from the @implementation, do you even need a middle-end pass?  Can't this just be straight-up done by the frontend when it sees a use of the method?  (Incidentally, there's yet another reason you really need this to be opt-in for it to work — Objective-C overriding is defined by whether the selectors match, so a method can be legally overridden even if it's not declared outside the @implementation.)
- If we can reliably inline all the callers of the method, should we even add it to the method table?  Maybe it should only be in the method table if it's declared outside the @implementation (or overrides such a method) — users can always add such a declaration in a "private" class extension if they need it in the method table for dynamic reasons but don't want to make the method easily usable externally.
- If a method is declared outside the @implementation, is it actually reasonable to assume that this attribute on its definition means it isn't ever overridden?
- Is there a viable path from this to a more traditional devirtualization optimization?  Is such an optimization ever going to be feasible in Objective-C without a slew of new attributes?

Also, regardless of the technical approach, while you are welcome to work on an implementation, nobody here can actually approve adding it to Clang on our own.  Clang has a policy for language extensions that you can read here:
  https://clang.llvm.org/get_involved.html <https://clang.llvm.org/get_involved.html>
It is the longstanding practice of the Clang project to treat Apple as Objective-C's effective governing body; Objective-C is not an open language.  So to add a major feature like this to Clang, you will need to propose it to Apple's internal language committee for Objective-C.  Assuming we can get this into a satisfactory shape, I would be happy to serve as your proxy on this, but I do have to warn you that it can be a slow and frustratingly opaque process.

But I do think it's an interesting feature that would solve a significant problem for Objective-C programmers.  Currently, Objective-C programmers who need inlining for performance have to rewrite their methods as static functions, which requires them to rewrite the method calls as well.  Being able to easily turn those message sends into direct function calls would be great.

John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180912/ac5bc1cf/attachment.html>


More information about the cfe-dev mailing list