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
CI was failing because a number of our host platforms were no longer
supported. This commit:
- Moves to the latest FreeBSD 12, 13, and 14 branch releases.
- Moves to modern Ubuntu.
- Replaces Windows 2016 with 2022
- Moves from Azure Pipelines to GitHub for the non-FreeBSD tests.
- Fixes some tests that are not reliable in some contexts.
* Add test for emptying autorelease pool
* Fix arc autorelease pool emptying when adding further references
When releasing a reference in the arc autorelease pool, it is
possible and anticipated that new references may added to the pool.
This fix addresses an edge case where releasing a reference in the
same pool page as the stop position can add more references which
cause the insertion of a new page and emptyPool() returns early
after emptying the new page.
This fixes a regression in 73132a6 (#200) where nil was returned
from a retain call after the object begins deallocating. Normal
retains of a deallocating object are still expected to return an
instance pointer inside its dealloc method and code compiled with ARC
will generate calls to objc_storeStrong() when a block captures the
self pointer inside the dealloc method.
The previous checks for a deallocating object with negative reference count did not work because:
1. the sign bit has to be recreated as was happening in objc_delete_weak_refs()
2. there was no distinction between a saturated count and a negative reference count
refcount_max now indicates when the refcount has saturated and should no longer be mutated.
An underflow to -1 still maps to refcount_mask, allowing us to detect when an object is supposed to be deallocated.
Neither objc_release_fast_no_destroy_np() nor objc_retain_fast_np() mutate the refcount when it is one of those values, so the comment in objc_delete_weak_refs() was adjusted.
This bug is also present in the original version:
When removing a WeakRef from the map, we use its obj field to find the
key, but the obj field has already been zeroed by this point and so we
end up leaving dangling pointers in the map.