mirror of
https://github.com/darlinghq/darling-libobjc2.git
synced 2025-01-01 09:18:29 +00:00
5b1911b4f4
Although GCKit is mostly finished, it is still not well tested. It contains bugs, and possibly dragons. Do not use it. If you disregard this advice, do not file any bug reports. If you disregard this instruction, then I will point and laugh at you.
127 lines
5.1 KiB
Plaintext
127 lines
5.1 KiB
Plaintext
GCKit
|
|
=====
|
|
|
|
GCKit is a garbage collection kit designed for Objective-C. It is a hybrid collector, using a combination of reference counting, cycle detection, and tracing. The design goals are:
|
|
|
|
- Easy interoperability with non-GC code using retain/release semantics.
|
|
- Easy interoperability with code designed for Apple's GC implementation.
|
|
- Support for assisted reference counting with no compiler support.
|
|
- Support for automatic garbage collection with compiler support.
|
|
- Low overheads.
|
|
- Performance in memory-constrained conditions, without causing undue swapping
|
|
|
|
Memory Types
|
|
------------
|
|
|
|
There are three types of memory in GCKit's model:
|
|
|
|
- Objects
|
|
- Traced regions
|
|
- Untraced regions
|
|
|
|
Objects have a fixed layout and may contain strong, weak, and traced pointers.
|
|
|
|
Traced regions include the stack, and any regions explicitly designated for
|
|
tracing. Stacks are traced synchronously, from the thread that owns them,
|
|
while other regions are not.
|
|
|
|
Untraced regions are opaque to GCKit. They may contain pointers to GC'd
|
|
objects only if the pointers are manually reference counted using GCRetain()
|
|
and GCRelease().
|
|
|
|
Object Types
|
|
------------
|
|
|
|
GCKit will allocate two kind of memory. Objective-C objects, and buffers.
|
|
|
|
Reference Types
|
|
---------------
|
|
|
|
There are four kinds of reference (pointer) in GCKit's memory model:
|
|
|
|
- Strong.
|
|
- Zeroing weak.
|
|
- Traced.
|
|
- Invisible.
|
|
|
|
Strong references use reference counting. When an object is strongly assigned
|
|
to a pointer, its reference count is incremented and the reference count of the
|
|
old object is decremented. Objects will never be deleted as long as they have
|
|
a strong reference count greater than 0 and their references can not all be
|
|
accounted for by cycles.
|
|
|
|
Zeroing weak references are also reference counted, however they do not prevent
|
|
an object from being finalized. Zeroing weak references follow similar
|
|
assignment semantics to strong references. When an object is only referenced
|
|
by zeroing weak references, it will be finalized, but not freed. Subsequent
|
|
reads of zeroing weak pointers to the object will decrement its reference count
|
|
and it will be freed once this reaches 0.
|
|
|
|
Traced pointers do not perform any reference counting. All pointers on the
|
|
stack are traced, as are pointers in memory buffers explicitly allocated for
|
|
tracing. Objects with a reference count of 0 will not be freed until tracing
|
|
these regions determines that there are no unseen references to them.
|
|
|
|
Copying traced pointers between stacks directly is not supported. If a thread
|
|
somehow gets a reference to another thread's stack and copies a pointer then
|
|
the compiler will not generate a write barrier. This means that, if the two
|
|
threads' stacks are not traced in the right order relative to each other (50%
|
|
chance) and there are no locatable heap references to the object then it may be
|
|
freed.
|
|
|
|
Invisible pointers are outside regions that the garbage collector knows about.
|
|
Objects pointed to by these may be deleted if their reference count hits 0.
|
|
|
|
Interior pointers are not supported. A pointer to the start of an object or
|
|
managed buffer must be maintained
|
|
|
|
Object Deletion
|
|
---------------
|
|
|
|
Objects marked as using CoreFoundation semantics are deleted as soon as their
|
|
reference counts hit 0.
|
|
|
|
All other objects are marked as potential garbage once their reference count
|
|
drops to a value that is equal to the number of references that the cycle
|
|
detector can find. If A and B both hold strong references to each other, then
|
|
they are marked as potential garbage once their reference count hits 1.
|
|
|
|
Interfaces
|
|
----------
|
|
|
|
Writing pointers into traced heap memory requires a write barrier. The
|
|
objc_assign_strongCast function generates this barrier for a single write
|
|
(another function, as yet unwritten, will generate it for multiple writes).
|
|
|
|
Assignments to instance variables or globals must increment the strong
|
|
reference count of the new value and decrement the value of the old one. The
|
|
objc_assignIvar() and objc_assignGlobal() functions perform this for you.
|
|
|
|
If you are storing pointers in memory that is not managed by GCKit then you
|
|
must call the CGRetain() function on the pointer to prevent it from being freed
|
|
and the GCRelease() function when you are finished with it.
|
|
|
|
Degenerate Cases
|
|
----------------
|
|
|
|
Objects using the Core Foundation or OpenStep models may set a flag indicating
|
|
that they do not contain cycles (or, more accurately, that the programmer takes
|
|
responsibility for freeing cycles). In this case, GCKit will trace the stack,
|
|
catching bugs where you might have used -release instead of -autorelease, but
|
|
aside from that will not provide any benefits.
|
|
|
|
Objects may also be marked as having CF semantics. In this case, they will be
|
|
checked for cycles (unless explicitly marked as acyclic), but will be finalised
|
|
when their reference count hits zero and subsequently destroyed when their weak
|
|
reference count hits zero.
|
|
|
|
Finally, you can use traced memory for everything. Don't do this. GCKit is
|
|
designed to be efficient when only a relatively small proportion of allocated
|
|
memory needs to be traced.
|
|
|
|
Outstanding Bugs
|
|
----------------
|
|
|
|
Lots. Seriously, don't use GCKit yet. Cycles in traced memory are not yet
|
|
detected. Lots of GCKit is completely untested.
|