40
iGC Garbage Collection User’s Manual Harnix Technologies Inc. 2011-08-16

iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

iGC Garbage Collection

User’s Manual

Harnix Technologies Inc.

2011-08-16

Page 2: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 2 -

Page 3: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 3 -

Contents

Overview ................................................................................................................................................................................................. 6 Basic Concepts ................................................................................................................................................................................ 6

Architecture ............................................................................................................................................................................ 7 How the Garbage Collector Works ............................................................................................................................................ 7 Enabling Garbage Collection .................................................................................................................................................... 8

Features & Specs ............................................................................................................................................................................. 9 Performance Testing ...................................................................................................................................................................... 11

GCBench testing ................................................................................................................................................................... 11 Pause-less testing ................................................................................................................................................................. 11 GC Throughputs.................................................................................................................................................................... 12

FAQs............................................................................................................................................................................................. 12 Programming Guide................................................................................................................................................................................ 14

Object References.......................................................................................................................................................................... 14 Managed reference ............................................................................................................................................................... 14 Strong reference ................................................................................................................................................................... 15 Weak reference..................................................................................................................................................................... 15 Zeroing weak reference ......................................................................................................................................................... 15 Summary.............................................................................................................................................................................. 16 ARCGC_C & Reference Mapping ............................................................................................................................................. 16

Object Reclamation........................................................................................................................................................................ 19 The cleanup routine .............................................................................................................................................................. 19 Immediate reclamation.......................................................................................................................................................... 19 Reclamation ordering ............................................................................................................................................................ 20 Resurrection ......................................................................................................................................................................... 20 Dynamic associated destructor............................................................................................................................................... 21 Reclaim circular depended cycles ........................................................................................................................................... 21

Linear Pool .................................................................................................................................................................................... 21 Features & tech specs ........................................................................................................................................................... 21 Create a linear pool ............................................................................................................................................................... 22 Create an object from a pool ................................................................................................................................................. 22 Drop references to pool or objects ......................................................................................................................................... 22 Evacuate objects from a pool ................................................................................................................................................. 23

API References....................................................................................................................................................................................... 24 Predefined Macros.................................................................................................................................................................................. 25

__OBJC_GC__ .................................................................................................................................................................................. 25 __has_feature(objc_arc) .............................................................................................................................................................. 25 __has_feature(objc_arc_gc) ......................................................................................................................................................... 25 __has_feature(objc_arc_gc_compatible)....................................................................................................................................... 25 __has_feature(objc_hnxgc)........................................................................................................................................................... 25 __has_feature(objc_hnx) .............................................................................................................................................................. 25

Objective-C Methods............................................................................................................................................................................... 26

Page 4: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 4 -

destruct ....................................................................................................................................................................................... 26 Declaration: .......................................................................................................................................................................... 26 Example:.............................................................................................................................................................................. 26

createFromPool ............................................................................................................................................................................. 26 Declaration: .......................................................................................................................................................................... 26 Example:.............................................................................................................................................................................. 26

__weak .......................................................................................................................................................................................... 27 __autoweak.................................................................................................................................................................................... 27

C Functions ............................................................................................................................................................................................ 28 _hnxgc_collect ............................................................................................................................................................................. 28

Declaration: .......................................................................................................................................................................... 28 _hnxgc_destruct_object................................................................................................................................................................ 28

Declaration: .......................................................................................................................................................................... 28 _hnxgc_add_memory_pressure ......................................................................................................................................................... 28

Declaration: .......................................................................................................................................................................... 28 Example:.............................................................................................................................................................................. 28

_hnxgc_did_receive_memory_warning ............................................................................................................................................. 29 Declaration: .......................................................................................................................................................................... 29 Example:.............................................................................................................................................................................. 29

_hnxgc_set_trace_level................................................................................................................................................................ 29 Declaration: .......................................................................................................................................................................... 29 Example:.............................................................................................................................................................................. 29

_hnxgc_set_cycle_breaker ............................................................................................................................................................ 29 Declaration: .......................................................................................................................................................................... 29

_hnxgc_set_nonrc.......................................................................................................................................................................... 29 Declaration: .......................................................................................................................................................................... 30

_hnxgc_weakref_allocate .............................................................................................................................................................. 30 Declaration: .......................................................................................................................................................................... 30

_hnxgc_weakref_deallocate........................................................................................................................................................... 30 Declaration: .......................................................................................................................................................................... 30

_hnxgc_weakref_read..................................................................................................................................................................... 30 Declaration: .......................................................................................................................................................................... 30

_hnxgc_weakref_write ................................................................................................................................................................... 30 Declaration: .......................................................................................................................................................................... 30

<General C API> ........................................................................................................................................................................... 30 C++ API ................................................................................................................................................................................................ 31

gcptr<T>::i .................................................................................................................................................................................. 31 Declaration: .......................................................................................................................................................................... 31 Example:.............................................................................................................................................................................. 31

gcptr<T> ....................................................................................................................................................................................... 31 Declaration: .......................................................................................................................................................................... 31

gcnew_i......................................................................................................................................................................................... 31 Declaration: .......................................................................................................................................................................... 31

Page 5: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 5 -

Example:.............................................................................................................................................................................. 31 gcdelete ....................................................................................................................................................................................... 31

Example:.............................................................................................................................................................................. 31 Example 2: ........................................................................................................................................................................... 32

<General C++ API> ...................................................................................................................................................................... 32 Articles .................................................................................................................................................................................................. 33

Maintaining existing RC cleanup ordering ........................................................................................................................................ 34 The problem ......................................................................................................................................................................... 34 Discarded attempts ............................................................................................................................................................... 34 iGC solution .......................................................................................................................................................................... 34

Solving stack overflow due to deep-nested destructions ................................................................................................................... 35 Choosing new style coding ............................................................................................................................................................. 37

Reducing your code writing workload ..................................................................................................................................... 37 Making more cycles non-sensitive to cleanup ordering............................................................................................................. 37 Writing one code for both GC and RC ..................................................................................................................................... 38 Conclusion............................................................................................................................................................................ 38

Advanced Subtle Topics.................................................................................................................................................................. 39 Access after destruction......................................................................................................................................................... 39 Reference counting ............................................................................................................................................................... 39 Aggressive garbage collection ................................................................................................................................................ 39 C++ Exceptions .................................................................................................................................................................... 39 Where GC runs ..................................................................................................................................................................... 39

Page 6: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 6 -

Overview

iGC is an innovative runtime garbage collector designed for the iOS (iPhoneOS) platform to collect unused objects, including those

circular-referenced, which cannot be reclaimed by Apple's Automatic Reference Counting (ARC) or manual retain/release (MRR) code.

Unlike some other garbage collectors, e.g. the conservative GC in Mac OS X, iGC is fully compatible with reference counting. There is no need to

work with two separate system libraries and frameworks for non-GC and GC apps. Just by linking in your code with the iGC static library, you can

use Objective-C and C++ language to write your auto-managed iOS App with existing system libraries and frameworks from Apple and other 3rd

parties. Only your code knows GC was enabled, while others continue to see your code running as manually managed.

Basically, iGC can be viewed as a combination of reference counting and tracing garbage collection, with the strengths of each merged in a

unique and innovative way that retains the merits and reduces costs. The following illustrate some of its main advantages:

(1) iGC employs a deterministic reclamation of objects (when the last effective reference to the object goes away), where traditional GCs free an

object “sometime later”. This meets programmers’ natural expectations concerning object lifetimes, and makes debugging easier as subtle

memory bugs come out earlier and are reproducible.

(2) The amount of memory required by an iGC app is generally much lower than a traditional GC because objects are released sooner.

(3) Reference counting in iGC helps the system to determine roots for live object traversal. It reduces iGC cost to less than RC + GC.

(4) iGC is accurate. It doesn’t suffer from fraudulent roots because it doesn’t scan stack to determine roots.

(5) iGC never kicks in and suspends your threads. This fully-concurrent GC maintains high responsiveness of UI apps.

(6) Objects are auto-managed by the system. This makes it open to numerous performance optimizations. We can rely on GC to recycle memory

space while maintaining objects being destructed immediately after use. And, the system can move some objects around in heap to provide fast

linear memory allocation, increasing performance by 4x – 6x faster over the standard Objective-C/C++ allocator.

(7) Garbage collection in iGC maintains the same RC reclamation ordering, even when they are referenced by cycles. This feature is important in

order to reuse the existing iOS frameworks and libraries.

Basic Concepts

The iGC system automatically manages your object’s lifetime by monitoring every assignment to ivars, the fields of instance of Objective-C class.

Contributions to reference count from ivars are done automatically by the system. There is no need to explicitly send retain/release messages for

ivars in your iGC program. If you use iOS 5 LLVM Clang 3.0 compiler with ARC enabled, you can use iGC without any retain/release calls.

Page 7: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 7 -

Let’s take a look at an example of iGC (with ARC enabled).

@interface Node : NSObject { Node *next; } @end @implementation Node + (void)work { Node * pA = [Node alloc]; // create obj `A’ pA->next = [Node alloc]; // create obj `B’ Node * pC = [Node alloc]; // create obj `C’ pC->next = pC; // form a cycle } @end

In the "work" method, when assigning an object reference to ivar `next’, the system will monitor the operation and retain the object, e.g. object

‘B’ is retained by ivar ‘next’, and will be released immediately when object ‘A’ is destructed. Circular referenced objects, like object `C’, will be

eventually collected by garbage collection. There is no memory leak.

Architecture iGC garbage collector is implemented as a static library (libiGC.a). When creating an instance of a class that uses default system [NSObject alloc]

method, the system will automatically invoke iGC API to return a managed object. C++ malloc or other objects created from custom routes are

unmanaged. The system monitors ivar assignments and performs different operations according to whether the type of object is managed or

not.

The collector only scans managed heap. It doesn’t scan traditional root-set areas of other GCs, such as stack, global variables, malloc heap, etc.

Objects created outside managed heap are not affected by the collector.

How the Garbage Collector Works We noticed that cyclic references are only formed within managed heap. Although there are references from root-set, like stacks, to managed

objects, but there is no effective reference from managed heap to the outside. From the collector’s point of view, the reference graph between

outside and heap is acyclic. It is appropriate to use reference counting to describe this situation.

iGC Runtime Objective-C Runtime

Frameworks & Libraries

iGC Managed Application

Platform OS Services

Page 8: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 8 -

In general, iGC maintains two reference counts for a managed object (there is nothing related to Objective-C retain count). One count (LRC)

reflects the number of references from outside the heap. The other (ERC) reflects the number of references from within the heap. If both counts

(LRC and ERC) of an object reach zero, then the object is freed immediately. If LRC is not zero, then the object is root for tracing in garbage

collection. Unreachable objects are of zero LRC and non-zero ERC.

These two counts, with some other control data, are stored in a special area separate from user-visible content of Objective-C objects. The area

is packed and efficient for collector to scan. When garbage collection is triggered, the collector scans this area instead scanning or traversing all

objects to determine roots. So the process of root determination is very fast compared to traditional GCs, which need to invoke system services

to suspend threads, wait for synchronizations of multiple threads, avoid unsafe kick-in points, scan stacks (which may be deeply nested), etc.

Several points of note regarding the collector:

The collector is fully-concurrent. That is, it runs concurrently in a dedicated background thread, and never suspends any of your app

threads. Write barriers are used to ensure the collector see the correct graph while app threads are constantly changing them.

The system automatically triggers garbage collection if some conditions are reached, like memory threshold. And you can trigger garbage

collection explicitly with some parameters, altering its behaviour.

After the collector determines unreachable objects, each unreachable object is given a chance to declare a relationship of dependence for

the process of destructing the object, and then the collector will figure out a reclamation ordering that satisfies all dependence

requirements.

iGC has no "finalizer" concept, as is the case with some traditional GCs. Only destructor in C++ or [dealloc] method in Objective-C is

associated with the lifetime of an object. The collector guarantees they are executed only once, even with resurrections.

Enabling Garbage Collection You can mix iGC code with non-GC code within an iOS App project. If you use C++ or Objective-C++ smart pointer techniques, you don’t even

need to make patches on existing compilers. After applying patches to Xcode compilers, including GCC-4.2 and LLVM 3.0, you can use

"-fobjc-gc" compiler flag to turn on iGC garbage collection for iOS platform.

Stacks Globals

Managed Heap Unmanaged memory

0/1

1/0

0/2

0/1 0/1

1/1

1/0

Page 9: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 9 -

NOTE: We reuse this flag in iOS, while in Mac OS X it is used to enable libauto conservative GC. The flag "-fobjc-gc-only" is still forbidden in iGC

for iOS.

For using iGC with LLVM 3.0 Automatic Reference Counting (ARC), you can use the "-fobjc-arc-gc" compiler flag to turn garbage collection

on. We use the term "ARCGC" mode for using iGC with ARC. Also, you can add "-fobjc-arc-gc-compatible" compiler flag for recompilation of

existing ARC source code.

NOTE: GCC-4.2 doesn’t support ARC, so ARCGC currently can only be used in LLVM 3.0 compiler.

NOTE: Alternatively, you can use both compiler flags "-fobjc-arc" and "-fobjc-gc" to turn on ARCGC. But notice that Xcode IDE will remove the

ARC "-fobjc-arc" flag if it detects either "–fobjc-gc" or "-fobjc-gc-only" is on. So we recommend the use of "-fobjc-arc-gc".

To link in iGC static library, you need to add "-u __iGC__" and "-liGC" to your Linker Flags and provide correct library search paths.

Sometimes you need to add "-lstdc++" to include standard c++ library.

NOTE: For ARCGC mode, in order to link in Apple’s ARC wrapper library for pre-iOS5 platforms, you need to add "-fobjc-arc" or

"-fojb-arc-gc" to your Linker Flags.

You can disable GC or ARCGC for iOS with the compiler flag "-fno-objc-gc" or "–fno-objc-arc". The last appearance of flags wins. We

don’t provide the corresponding "-fno-objc-arc-gc" flag, since it is not necessary. Your code can use macro __OBJC_GC__ to check if GC

is enabled, and use __has_feature(objc_arc_gc) to check for ARCGC mode.

See document "installation.pdf" in the iGC SDK for more detailed instructions.

Features & Specs

iGC provides you with accurate garbage collection for the iOS platforms. You can write your iOS managed application in Objective-C,

Objective-C++ and C++ languages. This fully-concurrent collector runs in a dedicated background thread. It never suspends your application

threads, giving you a very smooth experience and maintaining the responsiveness of your UI apps. Linear allocation gives you an option to boost

your app’s speed by 4x-6x times faster if it contains massive small-size objects.

Main Features:

Accurate collection – iGC is able to accurately identify all required references for garbage collection.

Deterministic reclamation – when the last effective reference to an object goes away, the object is immediately destructed.

Reclamation ordering control – Let you declare a dependence relationship for the process of destructing objects, and iGC will figure out a

reclamation ordering that satisfies all dependence requirements.

Pause-less – This fully-concurrent collector never suspend your works, maintaining high responsiveness of your UI apps.

Page 10: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 10 -

Compatibility – using the existing iOS frameworks and libraries, maintaining the same RC behaviour and reclamation ordering even if

objects are referenced by cycles.

Technical Details – platforms & devtools

Provide patches to GCC-4.2 and LLVM 3.0 to support GC for iOS platform with or without ARC.

Support Xcode development tools from "iPhone SDK 3.2 Final with Xcode 3.2.2 for Snow Leopard (10.6.0)" to the latest version.

Running on iOS platforms from version 3.0 at least.

Support weak reference (using __weak keyword) to remove cycles at design time for all iOS versions.

Support zeroing weak reference C API for all iOS versions.

Support zeroing weak reference using __autoweak keyword in LLVM 3.0 compiler with ARC.

Your source code is directly compiled into native ARM machine code, no virtual machine.

Pointers are still pointers except ivars operations are emitted with write barrier routines.

Technical Details – reclamation

You can send a [dealloc] message directly or a safer [destruct] message to destruct a live object safely.

Solve the stack overflow issue of deeply nested destruction, which lurks in C++ RAII, reference counting, etc.

Use one cleanup routine instead of a pair of "finalizer" and "destructor" methods, which is complicated and error prone.

Allows resurrection multiple times on an object.

Automatically detects resurrections by the system, which is constantly monitoring ivar assignments.

You can safely access other objects in your destructor, which is impossible in traditional GC without reclamation ordering control.

You can use "strong reference" to retain the target object for safe access from [dealloc] method.

Most cycles formed by existing MRR objects can be detected, and you can use a non-intrusive way (no changes to class implementation

code) to help the system reclaim them in a safe order.

You can associate multiple destructors at runtime to a managed object, including primitive types.

Technical Details – Misc

Page 11: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 11 -

You can use C++ smart pointer to reference an object’s interior, undifferentiated the same as to the head of the object.

The "interior => head" lookup mechanism is almost zero-cost, making it possible for applying interior pointer to frequent RC updates.

Allows multiple-inheritance, embedded object as a field, object array, etc., saving space and unnecessary indirect references costs.

You can have native C/C++ types and primitives under automatic management as a single object or an array.

The count in iGC is almost 64-bit, reducing the chance of count overflow.

You can use Linear Pool to perform linear allocation (bumper allocation) to create massive small-sized objects. These objects can be moved

around by the system when safe. Objects allocated from thread private pool can be shared between threads.

You can switch back to pure reference counting by replacing the static library libiGC.a with libiGC_RR.a, which does not contain any GC

code. Once you are sure your app hasn’t any reference cycles, you are free to use this feature (some performance boost may be lost).

Performance Testing

In this section, we will give a quick look at the performance testing of iGC, including GCbench testing, pause-less testing, and GC throughputs.

GCBench testing GCBench is a widely-used testing program for GC performance. Basically, it creates large amounts

of garbage nodes of binary trees with various depths and object lifetimes. It does not create

circular reference, so that it can be used for reference counting testing as well as for real cycle

collectors. We have built several GCBench testing programs using different memory management

methods. The execution times of them are measured and compared. Here is a chart of the

standardized results from iPod Touch 2G 3.1.3 (7E18) and iPod Touch 4G 4.3.5 (8L1). It shows

significant performance boost by using iGC in this program.

Pause-less testing iGC shares the same core of HnxGC. Here we

present the testing result of HnxGC on Win32

platforms instead (because we don’t have any

other iOS GCs at hand). In this testing program,

an event is raised every 5 milliseconds with 1

millisecond resolution. Time elapsed between

Page 12: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 12 -

two consecutive events are measured, which means in ideal situation the event interval should be 5 milliseconds. Here is the resulting graph of

programs using HnxGC, Microsoft .NET and Boehm conservative GC, comparing with an ideal (idle running, no garbage collection) program. We

can see that the result of HnxGC is indistinguishable from the ideal one.

GC Throughputs This program tests how the size of live objects in heap affects the throughputs of garbage collections.

It shows that although the time spent on object traversal are proportional to the size of live objects, HnxGC outperforms other competitors

significantly, up to almost 1000x(Boehm’s GC) and 100x (.NET CLR) times faster, when the amount of live objects is small.

FAQs

What languages does iGC support?

iGC supports Objective-C, Objective-C++, and C++.

What’s the difference between HnxGC and iGC?

HnxGC is designed for C++ based cross-platform applications. iGC is for iOS platforms, primarily for Objective-C apps (also supports

Objective-C++ and C++). HnxGC and iGC share the same runtime core.

Why not replace weak reference with zeroing weak reference?

Zeroing weak reference is not zero-cost. The synchronization between application threads and the collector cannot be overlooked, since

application thread may convert an object back to active via weak reference. App code must take special care to ensure correctness between

threads. Therefore, zeroing weak reference cannot be used in the same way of non-zeroing weak reference in programming grammar.

iGC weak reference (non-zeroing) operates as it was used in traditional RC for design time cycle-breaking. It is a raw pointer, and iGC doesn’t

monitor it. It is zero cost, and we recommend use it freely as in traditional manual management.

In a hybrid GC (like iGC), weak references are widely used to avoid cyclic references. The performance impact from weak reference is more

important than in a non-RC garbage collection environment, where the uses of weak references are fewer.

Page 13: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 13 -

Can I use zeroing weak reference for pre-iOS5 platforms?

Yes. Zeroing weak reference is provided by iGC runtime. It does not depend on Apple’s iOS 5 runtime. The keyword __autoweak requires the

LLVM 3.0 compiler, which is provided by Xcode 4.2 and iOS SDK 5. You must install iOS 5 devtools to build app for pre-iOS 5 platforms.

Why we need a runtime collector instead a dev-tool that detects cycles?

If you use dev-tools to detect cycles, you have to modify your source code to eliminate cycles. Sometime it is easy, sometime it is not. You have

to change some class definitions with weak ivars, or add some code to break cycles at proper runtime.

Using a runtime collector, you don’t need to inspect every related data structures in detail to figure out how to break cycles; just let the system

to collect cycles, and you can explicitly invoke GC to after massive uses of objects. It shortens your software development cycles.

Furthermore, garbage collection can boost the performance of your apps. Sometimes the boost is significant for a complicate data structure with

massive small-sized objects.

What’s Direct Kill?

If an object is mistakenly retained or referenced by other long-lived objects or code, automatic memory management system will think it may be

actively used by others. To reclaim these types of unused objects, iGC provides “Direct Kill” feature, which allows you explicitly reclaim a live

object and in turn release resources it occupies directly or indirectly.

Page 14: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 14 -

Programming Guide

The following sections describe programming changes from existing iOS app development for writing an iGC managed app. For something not

mentioned in this document, they are the same as before. For example, the statement [[Foo alloc] init] creates an iGC managed instance

of class Foo.

Object References

Once your Objective-C source code is compiled by an iGC compiler with garbage collection enabled, classes defined in the source code are

managed classes, and code accessing ivars are monitored by the iGC runtime.

In iGC, when assigning an object reference to an ivar, the system will automatically maintain reference counts of related objects and invoke write

barrier routines, if necessary. Therefore, you don’t need to send retain/release messages for ivars assignments.

For other operations on non-ivar references, such as function return value and parameters, local and global variables, fields of unmanaged

objects, etc., you need to use traditional ways to retain and release objects involved. For example, when assigning an object reference to a local

variable (auto variable) in a function, you need to explicitly send a "release" message to the old value, and send a "retain" message to the new

value. One exception is in ARCGC mode, since ARC compiler will generate [retain/release] calls for you.

There are four types of references that can be used to declare ivars and property of an Objective-C class. They are "managed", "weak", “strong",

and "zeroing weak". Details of these 4 reference types are described below.

Managed reference In iGC managed code, a default ivar/property declaration is a "managed reference". For example, in the code below, ivar "_next" and property

"next" are both managed references.

@interface Node : NSObject { Node * _next; } @property (nonatomic, assign) Node *next; @end @implementation Node @synthesize next = _next; @end

iGC runtime monitors assignments to “managed references" to maintain correct retain counts, and follow them in tracing garbage collection.

Cycles formed by "managed references" will be collected automatically.

A "managed reference" holds the target object alive except when the containing object is a member of unreachable cycles being collected by

garbage collector. Use "strong reference" instead to demand a reclamation ordering requests, to enforce the target is accessible in [dealloc]

method.

Page 15: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 15 -

Strong reference A strong reference is a special managed reference that holds the target object alive even when the containing object is being destructed as

unreachable cycles. For example, if object A points to object B via a strong reference, then when both A and B become unreachable, either as

member of a cycle or being referenced by cycles, the collector will destruct object A prior to object B. Therefore, it is safe to access object B in

the [dealloc] of object A.

Only a property can be declared as a "strong reference" for compatibility reasons. A property with the "retain" attribute is a "strong reference".

@interface Node : NSObject { Node * _next; } @property (nonatomic, retain) Node * next; @end @implementation Node @synthesize next = _next; @end

Notice that, if "strong references" constitute a cycle, that raises a circular demands for reclamation ordering. This kind of situation should be

avoided whenever possible. If this situation did happen, you can use iGC runtime API _hnxgc_set_cycle_breaker() to overcome this problem by

choosing some objects be reclaimed first.

Weak reference Weak references in iGC are *not* monitored by the system. They are raw pointers without any associated action emitted. Weak reference ivar

and property must be declared explicitly with the __weak keyword. For example,

@interface Node : NSObject { __weak Node * _next; } @property (nonatomic, assign) __weak Node * next; @end @implementation Node @synthesize next = _next; @end

A weak reference does not hold target objects alive. To prevent an object from being reclaimed by the system, there must be at least one

effective (non-weak) reference path to the object, or explicitly retain it by sending retain message.

Zeroing weak reference A "zeroing weak reference" is a special weak reference. Its content will be auto-zeroed by the system when the target object is reclaimed.

Synchronization rules between application threads and the collector should be carefully followed, because while an application thread is loading

value from a "zeroing weak reference", the value may be "zeroing" by the collector. So, the loading operation should be atomic and returning a

non-weak value.

Although, you can use C API _hnxgc_weakref_xxx() to manipulate "zeroing weak reference", such as loading, storing, etc., the iGC LLVM 3.0

compiler provides __autoweak keyword to simplify this work as showed below.

Page 16: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 16 -

@interface Node : NSObject {

__autoweak Node * _next; } @property (nonatomic, assign) __autoweak Node *next; @end @implementation Node @synthesize next = _next; @end

Summary "Managed reference" retains the target object alive, and cycles formed by managed references can be automatically collected. However, it

doesn't enforce any reclamation ordering for unreachable cycles, thus the target object of a managed reference may has been destructed before

the [dealloc] cleanup method of the containing object. "Strong reference" guarantees the target object remains alive for the cleanup method by

demanding a reclamation ordering to iGC system. "Weak reference" can be used to avoid cycles at design time to collect objects immediately.

"Zeroing weak reference" makes your code safe, but does introduce some extra runtime cost compared to non-zeroing weak.

ARCGC_C & Reference Mapping ARCGC_Compatible(ARCGC_C) mode is designed to reuse ARC source code without change in iGC garbage collection environment. It maps ARC

ivar and property attributes and qualifiers to iGC equivalents. For example, ARC @property(strong) is mapped to iGC managed reference.

To enter ARCGC_Compatible mode, add a compiler flag -fobjc-arc-gc-compatible in addition to existing ARCGC flag -fobjc-arc-gc in project

settings.

Below is a table showing reference equivalence of various modes.

Page 17: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 17 -

Page 18: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 18 -

Page 19: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 19 -

Object Reclamation

The cleanup routine In iGC, to define a cleanup routine with an object, you can merely define a [dealloc] method in Objective-C or a destructor in C++. The grammar

is the same as in standard Objective-C and C++ languages. In iGC, there is no concept of "finalizer" or the like as in many other GCs.

Remember, with garbage collection enabled, you should not send [release] message to ivars in your [dealloc] method, as iGC has already

handled that for ivars. Additionally, for ARCGC mode, you don’t need to invoke the [super dealloc] method call, since ARC will do that for you.

- (void)dealloc { printf("[Object (%p) dealloc]\n", self);

free(data); // essential cleanup jobs

#if !defined(__OBJC_GC__) [aIvar release]; // for manual management

#endif #if !__has_feature(objc_arc) [super dealloc]; // for non-arc #endif }

Immediate reclamation When an object loses all effective references to it, the system will destruct it immediately.

Ivars of an object become invalid just after the object has been destructed. Thus, child objects lose references after destruction of the parent

object. Notice that the ivar references are not dropped during the destruction. That is different from previous manual management which drops

member references manually in the [dealloc] method. One of the main reasons for this design is to avoid the nesting of destructions, which

may cause stack overflow in some large data structures. For example, a single linked list with more than 30,000 nodes. Another reason is for

performance, as references dropped by the system are usually slightly faster than in a user-defined [dealloc] method. If you need, you can

assign nil to the ivar reference in your [dealloc] method. The child will be released immediately. If there are no other references to the child,

the child will be destructed nested inside your [dealloc] method call.

Acyclic group of objects can be destructed immediately by destructing the head object of the group. However, if an acyclic group of objects are

referenced by a cycle, then these objects are not destructed immediately. You can use (1) weak reference to avoid cyclic graph at design time, or

(2) assign nil to ivars at runtime to break existing cycles. (3) If you cannot modify your class interface, or access some private ivars, you can use

the following approach to destruct a live object to break a cycle.

You can send an iGC specific [destruct] message to a live object to destruct the object immediately

You can directly send a [dealloc] message to a live object to destruct the object immediately (NOTE: Apple iOS UI framework did do in this way,

although in their document they recommend not do this). The [dealloc] message directly sent should stand-in a [release] message and

balance with a [retain] message as shown in the following iGC code snippet (non-arc mode).

Page 20: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 20 -

Node *a = [Node alloc]; Node *b = [Node alloc];

a->next = b; b->next = a;

[a destruct]; // immediately execute [dealloc] of 'a' and 'b' [a destruct]; // it is safe to send multiple times, only the first [a destruct]; // one is effective

[b release]; [a release];

Alternative, you can use C API _hnxgc_destruct_object() or C++ gcdelete keyword to do the same thing.

NOTE: LLVM 3.0 ARC disallows you to send [dealloc] message. But, in ARCGC mode, this limitation is removed after applying a patch to SDK

headers.

Reclamation ordering Many traditional GCs collect unreachable objects in an unpredictable order. That means, in the [dealloc] method, that the target object

referenced by an ivar may have been destructed even though you hold an effective ivar reference to it. Methods provided by the destructed

object may malfunction.

iGC provides a way to let you control the reclamation ordering of unreachable objects. You can define an "OnReclaim" call back method in your

C++ class, and when the collector has determined all unreachable objects, the system will invoke the "OnReclaim" method of each unreachable

object. In the method, you can use API to declare a dependences relationship for the process of destructing the object. For example, you can

declare that the process of destructing object A depends on object B and C, which may be directly or indirectly referenced. Object A could be

another object, not limited to the "this" pointer of the "OnReclaim" method. After all unreachable objects have claimed their dependence

requirements, the system will figure out a reclamation ordering that satisfies all these requirements. Therefore, you know the objects that you

want to use in your cleanup routine are guaranteed to be alive, and you are free to access them the same as if they were not in a cleanup routine.

For Objective-C and Objective-C++ language, you can use "strong reference" ivar to retain the target object alive during the destruction of the

containing object.

Resurrection In iGC, once the destruction of an object is started, the object cannot be reverted to live again. Because partial destruction may change the

consistency of the internal status of the object, restoring its status to live may require the introduction of complicated API and high runtime costs.

So, we just disallow it and provide an alternative solution.

You can resurrect an object that is going to be reclaimed. In the "OnReclaim" method described previously, you can resurrect another object or

itself by assigning the object to an effective reference to make it reachable again. The collector will monitor that change and put the object and

its descendants back to live again, before real destruction starts.

There is no limitation on the number of resurrections for a single object. Once an object is resurrected, its status is reverted back to original, as

if nothing has happened.

Page 21: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 21 -

Dynamic associated destructor At runtime, you can dynamically associate multiple destructors to an existing managed object, including primitives. For example, suppose you

create a managed integer array, you can associate a destructor to perform some cleanup tasks for it. NOTE: We do not use any hash table or the

like to implement this feature, so the negative performance impacts on object reclamation are minimized almost to zero.

Reclaim circular depended cycles Garbage collector can reclaim circular referenced objects without difficulty, but how should those that are circular depended be handled? For

example, suppose object A and B both request that the system keep each other alive for processing their cleanup routine. In another example,

suppose some design pattern sends "retain" messages to both objects A and B, to keep those objects alive, and sends "release" messages in the

[dealloc] methods of A and B. This makes it impossible to determine a correct reclamation order for objects A and B.

iGC provides a mechanism to address this issue. You don’t need to alter your designs or class layouts. Once you know which objects form circular

dependence cycles by studying debug outputs, you can use API _hnxgc_set_cycle_breaker(obj) to tell the system where to start reclamation for

these cycles. Then, when the collector detects these unreachable cycles, it knows where to start to reclaim the circular dependence cycles.

Linear Pool

Linear Pool is a mechanism that can be used in C++ and Objective-C/C++ to provide fast linear (bumper) allocation for small-sized managed

objects. As illustrated in the figure below, objects are allocated linearly from the pool. The type of allocation is very fast, and unused objects are

freed automatically by the GC system, not individually by the application threads. Thus, application threads gain the maximum performance

benefit from it

Features & tech specs Different sized objects can be allocated linearly from the same pool.

You can create multiple pools in a process.

Object allocation from a pool is not thread safe, but once the object is created, it is thread safe like other usual objects.

If a pool is shared between multiple threads, i.e. not a per-thread private pool, you have to use external synchronizations to ensure safety

for the operation of object allocation.

Objects inside a pool can reference other objects or vice versa, regardless of whether they exist outside the pool or in other pools.

… …

Obj 1 Head Obj n-1 Obj n Free SpaceObj 2

Page 22: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 22 -

The maximum size of an object in a pool is close to 64KB, though we recommend making them not larger than 2KB for performance

considerations. There is no limitation on the number of objects or on total object size in a pool.

Objects are not freed individually; they are freed as a group when all objects inside the group are unreachable or evacuated.

Objects can be evacuated from a pool, i.e., they are moved out of the pool and become a standalone object. The system will automatically

update related references when objects move.

You can explicitly request an evacuation when it is safe.

The pool itself is also auto managed; it will be reclaimed when there is no reference to the pool or to any objects inside the pool.

Objects in pool should not contain any cleanup method, and they should not reference RC type standalone objects.

Create a linear pool You can use C API _hnxgc_linearpool_create() to create a pool. It returns a locked handle to the newly-created pool. Or you can use a

wrapper C++ class, e.g. gcptr<GCLinearPool> pPool = GCLinearPool::Create();

Create an object from a pool C++ with wrapper class:

gcptr<CNode> p = gcnew_pool(pPool) CNode;

Objective-C:

Node * p = [Node createFromPool:hPool];

An object returned from [createFromPool] is a weak reference, not retained. If you want to retain it longer than the lifetime of the pool, you

should make at least one effective reference to it before all references are dropped, e.g., send a [retain] message to it, or assign it to an ivar.

After objects are effectively referenced or retained, you can invoke

_hnxgc_linearpool_safetorelease(hPool)

to let the system to release space of non-referenced objects in the pool.

Drop references to pool or objects References to pools or objects in pools are normal references, the same as for any general standalone objects. You can drop them as usual.

Page 23: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 23 -

Evacuate objects from a pool You can invoke

_hnxgc_linearpool_evacuate(hPool);

to move all live objects out of the specific pool. During the service call, the system will update related references to new object locations. All

spaces in the pool are released.

The time taken by this operation varies depending on some factors, such as the size of active objects in the pool and the number of related

references, etc.

Page 24: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 24 -

API References

Page 25: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 25 -

Predefined Macros

__OBJC_GC__

defined if garbage collection is enabled for iOS platforms

__has_feature(objc_arc)

true if it is in ARC, ARCGC, or ARCGC_Compatible mode

__has_feature(objc_arc_gc)

true if it is in ARCGC or ARCGC_Compatible mode

__has_feature(objc_arc_gc_compatible)

true if it is in ARCGC_Compatible mode

__has_feature(objc_hnxgc)

true if it is in iGC garbage collection is enabled, including in ARCGC and ARCGC_Compatible mode

__has_feature(objc_hnx)

true if the compiler is iGC LLVM 3.0

Page 26: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 26 -

Objective-C Methods

destruct

destruct a live object immediately

Declaration: @interface NSObject ()

- (void)destruct;

@end

Example: id p = [[Foo alloc]init];

...

[p destruct]; // immediately destruct `p'

...

[p release];

createFromPool

allocate a managed object from specified linear pool

Declaration: @interface NSObject ()

+ (__weak id)createFromPool:(uintptr_t)pool;

@end

Example: @interface Node: NSObject {

Node * next;

}

@end

uintptr_t hPool = _hnxgc_linearpool_create();

Node * p = [[Node createFromPool:hPool] retain];

...

[p release];

Page 27: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 27 -

__weak

Objective-C keyword to declare a weak (non-zeroing) ivar or property. <see "Programming Guide: Object Reference">

__autoweak

Objective-C keyword to declare an auto-zeroing weak ivar or property. <see "Programming Guide: Object Reference">

Page 28: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 28 -

C Functions

_hnxgc_collect

explicitly request tracing garbage collection

Declaration: void _hnxgc_collect();

_hnxgc_destruct_object

safely destruct a live object

Declaration: void _hnxgc_destruct_object (void * obj);

_hnxgc_add_memory_pressure

notify the system to perform garbage collection more frequently.

Declaration: void _hnxgc_add_memory_pressure(size_t size, bool bRemove);

Example: int nExtraMemSize = 64 * 1024;

+ (id)alloc {

... // allocate some memory for this object

_hnxgc_add_memory_pressure(nExtraMemSize, 0); // increase

memory pressure

...

}

- (void)dealloc {

... // free the associated memory

_hnxgc_add_memory_pressure(nExtraMemSize, 1); // reduce memory

pressure

...

}

Page 29: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 29 -

_hnxgc_did_receive_memory_warning

notify iGC that the memory available is very low

Declaration: void _hnxgc_did_receive_memory_warning();

Example: - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application

{

...

_hnxgc_did_receive_memory_warning();

}

_hnxgc_set_trace_level

trace iGC behaviors, such as performing GC, allocate objects and reclaim garbages

Declaration: int _hnxgc_set_trace_level(int level);

// returns: existing trace level

// input: new trace level [0 : not trace, 1 - 999: the high value the

more print-outs]

Example: _hnxgc_set_trace_level(200);

_hnxgc_set_cycle_breaker

set an object where iGC start to reclaim dependence cycles

Declaration: void _hnxgc_set_cycle_breaker (void * obj);

_hnxgc_set_nonrc

set an object to non-RC state

NOTE: ivar references to non-RC object are traced but do not contribute to reference count, so the object will

Page 30: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 30 -

not be reclaimed immediately after use (can only be reclaimed by garbage collection).

Declaration: void _hnxgc_set_nonrc(void * obj);

_hnxgc_weakref_allocate

allocate a zeroing weak reference slot

Declaration: uintptr_t _hnxgc_weakref_allocate();

_hnxgc_weakref_deallocate

free a zeroing weak reference slot

Declaration: void _hnxgc_weakref_deallocate(uintptr_t slot);

_hnxgc_weakref_read

return a "retained" reference from a zeroing weak reference slot

Declaration: void * _hnxgc_weakref_read(uintptr_t slot);

_hnxgc_weakref_write

assign a reference to a zeroing weak reference slot

Declaration: void _hnxgc_weakref_write(uintptr_t slot, void * obj);

<General C API>

manipulate managed objects in C, C++, Objective-C and Objective-C++ langugages, see HnxGC documents for more details.

Page 31: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 31 -

C++ API

gcptr<T>::i

smart pointer for managed ivar reference

Declaration: gcptr<T>::i <ivar name> Example: @interface Node : NSObject {

gcptr<Node>::i nextNode;

}

@end

gcptr<T>

flexible smart pointer for non-ivar reference

Declaration: gcptr<T> <ivar name>

gcnew_i

create C++ smart pointer style objective-C object

Declaration: gcnew_i <expression returns a retained object> Example: gcptr<Node> pNode = gcnew_i [Node alloc];

gcdelete

safely destruct a live object

Example: Node * pNode = [[Node alloc] init];

...

gcdelete pNode;

Page 32: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 32 -

Example 2: gcptr<Node> pNode = gcnew_i [[Node alloc] init];

...

gcdelete pNode;

<General C++ API>

manipulate managed objects in C++ and Objective-C++ languages, see HnxGC documents for more details.

Page 33: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 33 -

Articles

The following will contain some selected articles regarding iGC / HnxGC. Some of them are advanced and may not be updated with the changes

of new release of iGC / HnxGC.

Page 34: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 34 -

Maintaining existing RC cleanup ordering

Adding GC to existing RC-based system brings in some new challenges. In this section, we will describe the problem of cleanup ordering and how

it was solved in iGC.

The problem Reference counting has implied a very strong ordering on cleanup of unused objects. Naively switching RC system to GC will break this implicit

behaviour on which many existing RC codes depend. For instance, if existing RC-based objects (acyclic) are referenced by cyclic garbage, then

they can only be collected by GC and may be disposed in a wrong ordering different from existing RC code. Therefore, some existing code may

crash because in their cleanup code, they may access some other objects which have been destructed by GC as effective reference cannot keep

object alive during cleanup code.

Therefore, in order to reuse the existing RC-base code, we must maintain the same cleanup ordering of those RC-based acyclic objects.

Discarded attempts One attempt to solve this problem is to treat RC-based objects as native non-managed, but this way is inefficient and objects are beyond the

management of GC system causing cycles of them uncollectible.

Some GC systems (such as Boehm GC) only cleanup unreachable objects that are not referenced by

others, then in turn expect more objects become eligible for this rule. Using this way to maintain cleanup

ordering has at least two issues: (1) the cleanup of cycles and their descendants are skipped undesirably,

e.g. in Figure-1, if C2 needs cleanup, then because C2 references C1, A1 to A4, all the cleanup routines of

these objects are not executed under this rule; (2) if the GC system does not immediately reclaim zero-RC

objects, then some orderings enforced by RC-based code are violated. For example, RC can enforce a

cleanup ordering of A3 prior to A4 by explicitly nullifying reference from A2 to A3 in A2’s cleanup code. In

conclusion, such GCs are not suitable for a RC compatible system.

iGC solution In iGC, RC-based objects are under the management of the system. Existing RC code (retain/release

message) are replaced with maintaining a per-object count that represents the number of references from

root-set. That is, references from original RC-based objects are treated as coming from root-set, thus the

referents will not be collected by normal GC when they become unreachable. After GC collects other cycles that are referencing them, the

reference counts of these RC-based objects will drop to zero, then the objects will be collected consequently and the ordering of cleanup will be

exactly the same as original RC.

For example, as showed in Figure-1, unreachable RC-based objects A2, A3 and A4 are treated as being referenced by root-set. They are not

collected until C1, C2 and A1 are collected by GC. After GC collects and destructs A1, then objects A2, A3 and A4 will consequently lose their last

references and be destructed in the same order as in the original RC-based system.

See also: "Aggressive garbage collection" – collect cycles of existing RC objects

C2C1

GC Collected

Same RC Order

A1

A2

A4

A3

Unreachable Garbage

Figure 1

Page 35: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 35 -

Solving stack overflow due to deep-nested destructions

Many C++ programmers may be unaware of a bug residing in their data structures. Consider the following innocent looking code which defines

a node for a linked list:

struct Foo { Foo * m_pNext; ~Foo() { delete m_pNext; } };

As is typical, this structure contains the logic for cleaning up the linked list in its destructor by deleting its sibling node. The sibling node then

deletes its sibling and so on, until the entire linked list is deleted.

A typical routine for constructing and using the linked list might look something like this:

#define NESTED_DEPTH 100000 static void doTest() { // create a singlely-linked list Foo * pFirst = 0; for (int i = 0; i < NESTED_DEPTH; i++) { Foo * pNode = new Foo; pNode->m_pNext = pFirst; pFirst = pNode; } // dispose the list delete pFirst; }

When it comes time to delete the list, clean up is invoked by deleting the first node. In applications where there are a relatively small number of

nodes, this code works just fine. But what happens when the length of the linked list is really long such as in the example above where there are

100,000 nodes?

Since Foo's destructor causes a stack based, depth first traversal of all of the nodes in the data structure, the traversal of such a large topology

will overflow the call stack causing a stack overflow exception. This problem can also occur on smaller topologies when the destructor requires a

larger stack frame, e.g. when the destructor contains a fixed sized array. The worse part is that this bug may not show up until the code is being

used in a shipped application handling massive amounts of data.

In HnxGC, this problem is easily solved by rewriting the code as shown here:

struct Foo { HNXGC_ENABLE(Foo) gcptr<Foo> m_pNext; // replace Foo * with gcptr<Foo> ~Foo() { // removed call to delete-deletion of m_pNext is automatically // handled by gcptr } };

gcptr is a smart pointer class provided by HnxGC which takes care of the destruction for you. With HnxGC you simply redefine all pointers to your

structure using the templated gcptr class, passing in your structure name as the template parameter.

Page 36: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 36 -

You then delete the linked list by clearing all pointers to the first node of the data structure as shown here:

#define NESTED_DEPTH 100000 static void doTest() { // create a singlely-linked list gcptr<Foo> pFirst = 0; // replace Foo * with gcptr<foo> for (int i = 0; i < NESTED_DEPTH; i++) { gcptr<Foo> pNode = gcnew Foo; // replace Foo * with gcptr<foo> pNode->m_pNext = pFirst; pFirst = pNode; } // dispose the list pFirst = 0; // using HnxGC, deletion is performed by simply // removing all references to pFirst // all objects will be destructed before the next // instruction }

Behind the scenes HnxGC decreases the reference count when pFirst is set to 0. When the reference count reaches 0, HnxGC safely deletes the

entire linked list for you. The reason why HnxGC safely deletes the list is because HnxGC deletes each node one by one, thereby releasing the

stack frame after execution of the current destructor before calling the next destructor. This means that the size of the destructor's call stack

does not grow and therefore topologies of any size will be safely deleted. This also results in faster execution than with nested destruction

because the space required for the stack is smaller.

With HnxGC you can finally encapsulate the initialization and clean up logic of your data structures directly in the structure itself without worrying

about stack overflow problems. And because destruction executes immediately upon invoking clean up, HnxGC's garbage collection is

deterministic, as opposed to other implementations where you have little or no control over when clean up occurs. Destruction of circular

references (while not immediate even with HnxGC) is also faster with HnxGC because it avoids the costly suspension of application threads.

Stack overflows during destruction are a serious problem, and can exist across different C++ development frameworks. In traditional C++ it's

common to implement Resource Acquisition Is Initialization (RAII) where by construction and destruction of a resource are encapsulated to take

advantage of the fact that objects on the stack are cleaned up. The problem can also exist in other frameworks which may give the illusion that

they enable safe destruction. For example, Boost's shared_ptr and intrusive_ptr classes define an interface for clean up, but because it's up to

the programmer to implement the destruction logic, one can easily implement the nested destruction problem. Another example is Managed

C++ where, despite the apparent safety of the garbage collected environment, programmers are still free to implement nested destruction which

is executed on a growing call stack just like regular C++.

Page 37: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 37 -

Choosing new style coding

In new style coding for Objective-C, you don’t write codes explicitly to maintain RC for references from an object. Instead, the underlying runtime

library will do the RC maintenance for you. Using the new style of coding has the following advantages over previous styles:

Reduced code writing workloads

Making more cycles non-sensitive to cleanup ordering

Writing one code for both GC and RC

Reducing your code writing workload Previously, programmers typically used property mechanisms to alleviate the work for manual maintenance of RC. For example, individuals may

use @property(retain) to declare a property and then allow a compiler to generate appropriate accessor methods to perform RC work. But,

since the compiler has no direct interaction with the dealloc method, properties are not automatically released in the dealloc method for you.

So, in a dealloc method you have to release objects directly or invoke accessor with nil as the parameter. If you forget to do this, or do it in

an incorrect way (e.g., releasing a non-retain property), your application may leak or even crash.

In new style coding, runtime library will automatically release property for you. So you can use @property (retain) to declare property as

usual, but in the dealloc method you don’t need to write code to release it manually. The dealloc method should only contain the essential

cleanup code. This allows you to focus on your application logic and lets the system take care of the rest of the work, such as object lifetime

management.

Also, new style coding uses __weak, @property (assign) and @property (retain) keywords to denote specific uses of properties and

pointer fields. This makes codes more readable and the purpose of pointers more clearly distinguishable.

Making more cycles non-sensitive to cleanup ordering In the new style coding the dealloc method only contains essential cleanup code, as the responsibility of releasing referent objects is passed

to the underlying runtime library. If there is no need to do any essential cleanup job, then there is no need to define a dealloc method. This

increases the chance of not define a dealloc method, compared to the previous style where usually there are many dealloc methods that

exist only to perform object releasing work.

If an object doesn’t have a dealloc method, then it is not concerned with any other objects that are alive or not. No other objects should be

kept alive for this object (iGC allows doing release operation on a dead object). Therefore, it gives more freedom to the system in reclamation

ordering of unreachable cycles.

NOTE: In the previous style, if a cycle has been formed, then it is almost impossible to auto-determine a correct cleanup ordering, as dealloc

methods usually have been defined. To cleanup these cyclic objects in a safe order, you must activate the Aggressive GC option and manually

specify where to start.

Page 38: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 38 -

Writing one code for both GC and RC Once you write code in the new style, your code can be used not only in GC environments, but also in traditional RR (retain/release) based

environments (also known as RC-based in this documentation).

Unlike the built-in GC in Mac OS X, you don’t need to devote a lot of effort into the finalize and dealloc methods, e.g., trying to make it

compatible with both non-deterministic GC and immediately reclaimed RC. In iGC, the runtime behaviour is already compatible with the existing

RR system. Designing a compatible application for both iGC and the existing RR system is straightforward and natural.

You can also roll back your new code to pure RR runtime by simply replacing the iGC library with iGC_RR library without making changes to your

new-style source code, nor any recompilation. Actually, the iGC_RR library is a small wrapper that redirects all implicit RC maintenance to the

iOS Objective-C RR system, including the object releasing works in dealloc methods.

NOTE: You will lose garbage collection benefits if you roll back to the manual retain/release.

Conclusion Using the new style coding for your next application development provides many benefits, and it is easy to switch back and forth between GC

and non-GC.

Page 39: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 39 -

Advanced Subtle Topics

Access after destruction

The contents of member pointers retain valid

The contents of member pointers must maintain valid (NULL or pointing to a valid object) after destruction. The system may access member

pointers of a destructed object and trace them to other objects directly or indirectly. You should not alter the content of member pointer to an

invalid reference in cleanup routine.

Dead object spaces are not recycled concurrently

When the system is performing garbage collection, some objects may lose their last references and become eligible for reclamation by reference

counting system. These objects will be destructed immediately, but the system does not recycle the memory space in this case. It is safe for

tracing GC to access these dead zero-RC objects.

Reference counting

Zero-RC destruction will *not* be affected by GC

When an object becomes Zero-RC, the system will invoke its destructor and in turn reclaim more Zero-RC descendants. This destruction

behaviour will not be affected by a concurrently running GC, i.e. the RC destruction will not be postponed or skipped.

Aggressive garbage collection References from existing RC-based objects are treated as strong references from root-set. Does it cause cycles involving these references never

be collected? The iGC provides Aggressive Garbage Collection, which can automatically adjust RC contributions from existing RC-based objects,

so the system can detect cycles involving RC-based objects, as well as cycles fully composed of existing RC-based objects.

NOTE: By default, the Aggressive GC feature is turned off due to performance considerations. You have to manually turn on this option to collect

cycles involving existing RC-based objects. Alternatively you can migrate existing RC-based code (modifying it very little) to new style GC-based,

achieving the same goal but faster. To using Aggressive GC, simple replace Link settings in you projects to link “libiGC_AGG.a” instead “libiGC.a”.

C++ Exceptions Your code can throw exceptions in the constructor of a managed object, but should not throw any exception into the destructor. The main reason

is the destructor may be executed in a background collector thread or in other threads; the execution environment may not be the same as what

you expected.

Where GC runs When some pre-defined conditions are reached, the system will trigger the background collector to perform tracing garbage collection. You can

also explicitly invoke garbage collection in any context, including in the destructor of an object that is being destructed.

At runtime, you can instruct the system to perform a final garbage collection upon exiting the application.

Page 40: iGC Garbage Collection - harnixtechnologies.ca · - 3 - Contents Overview .....6

- 40 -