The fast paths follow the pattern that we established for fast ARC:
Framework base classes can opt in by implementing a `+_TrivialAllocInit`
method.
This opt-in behaviour is inherited and is removed implicitly in any
subclass that implements alloc or init methods (alloc and init are
treated independently).
Compilers can emit calls to `objc_alloc(cls)` instead of `[cls alloc]`,
`objc_allocWithZone(cls)` instead of `[cls allocWithZone: NULL]`, and
`objc_alloc_init` instead of `[[cls alloc] init]`.
Direct methods don't require very much support in the runtime. Apple
reuses their fast path for `-self` (which is supported only in the Apple
fork of clang, not the upstream version) for a fast init. Given that
the first few fields of the runtime's class structure have been stable
for around 30 years, I'm happy moving the flags word (and the
initialised bit, in particular) into the public ABI. This lets us do a
fast-path check for whether a class is initialised in class methods and
call `objc_send_initialize` if it isn't. This function is now exposed
as part of the public ABI, it was there already and does the relevant
checks without invoking any of the message-sending machinery.
Fixes#165#169
This was actually a memory leak in the hidden class implementation, but
it was mostly visible in the @synchronized implementation. Every hidden
class registered a custom .cxx_destruct method, to handle cleanup of all
of the hidden class structures. Unfortunately, this destructor failed
to delete the reflection metadata structures associated with the class,
specifically the objc_method_list containing the objc_method pointing to
the destructor itself.
Fixes#98
This cleans up handling of objects that are not reference counted and
makes their interactions with ARC more consistent. We should probably
generalise this somewhat - it currently special cases NSConstantString
and NSGlobalBlock, but it would be nice to have an API for constant
objects.
Coverage checking of the test suite showed that objc_disposeClassPair
wasn't tested at all, which then led to discovering that it didn't
unregister the class.
Every class is either a class or a metaclass, it doesn't make sense to
use two flags to store one bit of data.
Also remove the newabi flag from classes in the v2 ABI, where it's
redundant.
This change set incorporates a number of changes that all needed to
happen together:
* The imp is now the first field of the `objc_method` structure. This
makes it possible to extend the structure without breaking anything
that relies on being able to access the IMP.
* There is no owner in the slot, so we must use other mechanisms for
determining the owner of a method (e.g. whether the same method appears
in the superclass)
* Again, because there is no owner in the slot, we can't use this as a
fast path for finding the C++ construct / destruct methods. These are
now cached in the class structure when they are found.
* The version field is gone from the slot and now we provide a global
version. This is based on the observation that method replacements
are relatively infrequent and the overhead of invalidating all method
caches is cheaper than adding extra state for every (class, method)
pair.
* A number of the runtime functions are simplified because replacing
the IMP in a `Method` now implicitly updates the dtable.
We're now using a new class and category structure and auto-upgrading the old ones. Other changes:
- The Ivar structure now points to the ivar offset variable, so we can more easily find it.
- Categories can now add properties.
The new structure has extra fields for alignment and flags (e.g.
ownership).
Old structures are auto-upgraded at load time, so the rest of the code
can assume the presence of the new structure type.
Added fields to the end of the class structure for strong / weak ivar bitmaps (not yet generated by any compiler).
Fixed definition of __sync_swap() so that it works on GCC again.
I now have an out-of-tree replacement for the dtable stuff, so sarray.{h,c} will be going away soon. The replacement offers similar (slightly worse currently) performance in microbenchmarks, but uses half as much memory (Gorm goes from 95MB to 48MB on my machine). This will be committed once it's been tweaked a little bit.
Imported selector table code frm the Étoilé runtime. We can now make dispatch type dependent with a -D switch. Not enabled yet, but it will be enabled in a warning mode soon - I consider preferable to the existing GNU and Apple solution of corrupting the stack.