We weren't correctly sign-extending the value being compared, which was
resulting in objects not being deallocated. For some reason, this only
appeared on Windows, even though the code looked wrong on all platforms.
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.
* use fiber local storage if NO_PTHREADS is defined
* use critical sections instead of mutexes
Contributing-author: Ben Viglietta <benvi@microsoft.com>
Weak refs were being left as dangling pointers after being deleted. The
load that caused the deallocation would return nil, but then the next
one would dereference a dangling pointer.
Fixes a bug introduced (replacing a similar bug) in the last rewrite of
objc_moveWeak. This version should now be correct.
objc_copyWeak was implemented in a naive way, which had a lot more
overhead than required.
Rather than tracking all of the locations of weak pointers, keep a weak
refcount. This should also make it easier to add finer-grained locking to weak
references.
We were not correctly checking that the object being assigned had a
reference count in the object header. We're also now avoiding assigning
small objects to the weak reference table, which is quite important as
they have no destructor.
Fixes#12
the table incorrectly, causing objects inserted at offsets due to hash
collisions to fail to be moved up and then fail to be found later.
Test by Eric Wasylishen!
- Make objc_retain() check for stack blocks and implicitly copy them. This fixes the case where a block pointer is stored in an object-typed variable and is assigned.
- Tweak objc_retainAutoreleaseReturnValue() so that the ARC optimiser doesn't detect that the body looks like a call to objc_retainAutoreleaseReturnValue() and replace it with an infinitely recursive call.
The second fix now means that arc.m will compile with clang without producing a function that calls itself.
In a simple example:
- foo { return self; }
void someFunction(void)
{
id a = foo;
...
}
In ARC mode, this expands to:
- foo { return objc_retainAutoreleaseReturnValue(self); }
void someFunction(void)
{
id a = objc_retainAutoreleasedReturnValue(foo);
...
}
In the slow path, this is equivalent to:
- foo { return [[self retain] autorelease]; }
void someFunction(void)
{
id a = [foo retain];
...
[a release];
}
The fast path skips the autorelease / retain pair. The return value is stored
in thread-local storage temporarily and then retrieved, the retain balancing
out the autorelease.
This gives a 50% speedup on a single thread. It also avoids some atomic
operations.