This replaces a few home-grown datastructures with third-party ones that
get a lot more testing:
- The home-grown hopscotch hash table is moved to using robin map. The
original was designed to be lock free, but we've been using it behind
a lock for ages.
- The selector list is now a std::vector.
- The types list now use std::forward_list.
This also removes a couple of code paths that haven't been used since we
started using the new ABI data structures internally and upgrading at
load time.
The new code tries to differentiate in the static type system between
registered and unregistered selectors. The check for whether a selector
is registered is fragile and depends on no selector being mapped or
allocated in memory below the total number of selectors. This check can
now disappear on most code paths.
On a single test machine (not guaranteed to be representative) the test
suite now completes around 20% faster.
This is necessary because FreeBSD/ARM and possibly other platforms use
.init_array and not .ctors, so never call the init functions. As a
result, we will need the compiler to move to putting the load function
in .init_array and may end up with it being called by both variants.
We use the existence of the `Protocol` class in a set of loaded objects
to determine whether we are mixing ABIs in a safe way (i.e. only mixing
a new ABI runtime with old ABI everything else). Unfortunately, in
static linking, the Protocol class was not being linked because it is
never directly referenced, which made this check fail.
Fixes#85
These are currently ignored, because they are only important when the
runtime has upgraded the protocol. The runtime will upgrade legacy
protocols, but they are not referenced by this indirection layer.
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.
- __strong pointers, preventing objects from being freed
_ __weak pointers are automatically freed when the last remaining __strong pointer goes away
- objc_gc_{retain,release}_np() functions, which can be used to implement CFRetain() and CFRelease() (adds an reference count - the object will not be collected until after its last retain is gone.