- 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.
- Don't call C++ constructors if they don't exist.
- Don't check the owner of retain / release methods if they are not implemented.
- Add arc.m as a file to ignore when checking for GC compatibility.
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.
Weak references are still not supported, but code that doesn't use them (i.e. any code that wants to be compatible with OS X 10.6) will work fine.
The current implementation is VERY inefficient and has a large number of missed optimisation opportunities: this is the 'make it right' phase, and should be almost equivalent to explicit retain / release code.
allocations and all deallocations. It's now possible to implement
malloc_history entirely parsing the dump file (or doing /dev/fd style tricks
send it straight to a monitoring process).
registered to be copied on heap assignment. By default, this is just
_NSConcreteStackBlock. Other classes can be registered (LanguageKit should
register BlockClosure to make sure that Smalltalk works).
Fred: This makes the stuff that we discussed briefly at FOSDEM possible in GC
mode: We can allocate a GSStackEvent subclass of NSEvent on the stack. If it
implements a -copy method that returns an NSEvent and is registered with the
runtime in this way, then any code that assigns it anywhere on the heap will
end up implicitly creating a heap copy.
- Add objc_gc_collectable_address() to determine whether a pointer is managed
by the GC
- If LIBOBJC_CANARIES is set (optionally to a random number seed) then store a
canary value after every allocation returned by
objc_gc_allocate_collectable() and, when it is finalised, check that the
canary has not been modified, aborting if it has. This catches some
heap-buffer overflows, and currently causes GNUstep to abort.
- If LIBOBJC_LOG_ALLOCATIONS is set to a file name, log all GC-managed
allocations to that file. This gives something like malloc_history on OS X.
- objc_memmove_collectable() now guarantees that all copied pointers remain
visible to the GC at all times (which was the point of the function - the
original implementation was just a quick stub).
does run-time detection of whether to use GC calls objc_collecting_enabled()
(sometimes indirectly, via NSGarbageCollector) to see if we're in GC mode.
After any of these calls, it is not safe to switch modes.
Store the refcount structures inside the hash table, rather than in a chained structure. This uses less space and should be easier for the GC to scan (less cache used).