This was generating a relocation that didn't do the right thing and
didn't raise linker errors. Now it is using GOT-relative addressing.
In combination with the last two commits, this now makes all of the
objc_msgSend tests pass on AArch64.
Fixes#105
If we called into C to find the IMP (e.g. for forwarding), we were then
reloading all of the arguments but failing to adjust the stack pointer
by the correct amount, leaving it around 192 bytes offset from its
correct location. This, unsurprisingly, led to crashing and other
exciting behaviour.
As an optimisation, on load of a weak reference we check if the object
has already been deallocated and, if so, decrement the weak reference
count and zero the pointer to the weak reference structure so that the
next check is faster and doesn't need to hold locks for as long.
Unfortunately, the prior implementation of this instead decremented the
weak reference count and then only zeroed the pointer if the reference
count reached zero. This meant that loading the same __weak pointer
twice after the pointed-to object had been deallocated would decrement
the reference count twice.
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.
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.
Setting these tests to use 3 processors is weird, but it means that in
CI (where we do 4 tests in parallel), we won't ever run more than one of
these at a time (though we can run any other one test at the same time
as these). This should fix the intermittent failure.
These most likely led to some intermittent failures in weak references.
The `objc_moveWeak` and `objc_copyWeak` functions were assuming that the
target may contain valid data, but the spec for these says that it may
be uninitialised data. We were reading uninitialised data and then
seeing if it happened to be a valid object. Most of the time it was
likely to be nil, so this wasn't an easily reproduceable problem...
I believe this is the correct fix for PR #95.
Fixes#95