- 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.