[clang] [ObjC] Check entire chain of superclasses to see if class layout can be statically known (PR #81335)

John McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 12 11:26:10 PST 2024


rjmccall wrote:

I talked this over with Mike Ash.  I was concerned that Objective-C might allow dynamic class changes that would burn our ability to do this optimization, such as adding ivars during `+initialize`.  The existing optimization would work even with a relatively lax runtime as long as new ivars always followed existing ivars.  Fortunately, Mike assures me that this is impossible: the layout of a class is fixed before it's ever exposed to user code, including the calls to `+load` and `+initialize`.  The runtime only allows ivars to be added to a class before the class is registered with the runtime (i.e. never for compiler-emitted classes).  It is possible to replace the superclass dynamically (although this is strongly discouraged), but class layout has already happened by any point where this is possible, so there is an effective requirement that the new superclass's class layout matches the old one's.  In short, we're comfortable saying that there's an ABI rule that class layout for compiled classes is solely dependent on information expressed in the language, at least as far as the class's subobject is concerned (that is, we can never rule out subclasses, including dynamic subclasses; but that doesn't interfere with the static optimization here).  So this optimization is indeed possible.

The compiler is not integrated with the linker and cannot see `@implementation`s for classes defined outside the current translation unit.  So the approach in this patch only helps in the case that you have the primary `@implementation` for multiple classes in a single translation unit.  That's fairly uncommon in my experience; ObjC programmers tend to define different classes in different `.m` files.  Still, it probably does happen, especially with code generation, and we ought to be able to optimize it.

We should stress to programmers that they should not change their code by defining everything in a single `.m` file just to get this optimization.  It is not likely to be worthwhile.

In order to optimize this across translation units, we'd need a version of it that worked with LTO.  It should be very feasible to do this with summaries in ThinLTO.  That seems like it'd be a huge win; it would have three effects that I can see:

- We'd be able to pre-slide offset variables in subclasses according to their superclasses in the same image.  This can significantly optimize load times by reducing the amount of memory that has to be dirtied.  However, I think the Mach-O linker already does this, so it's probably not a big deal to do in LTO.
- We'd be able to optimize ivar accesses to use static offsets even when the superclass is defined in a different TU.  This seems like the biggest win.
- We'd be able to optimize ivar accesses to use static offsets even for accesses outside of the main `@implementation`.  This would be a huge win except that it's pretty unidiomatic in Objective-C, which generally strongly encourages the use of properties.

I'll take another look at your patch.  As Aaron said, there is no need to ping me so quickly, especially on the weekend.

https://github.com/llvm/llvm-project/pull/81335


More information about the cfe-commits mailing list