diff --git a/ANNOUNCE b/ANNOUNCE index cca6744..d5e5f6d 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -6,6 +6,14 @@ libobjc2). This runtime was designed to support the features of Objective-C 2 for use with GNUstep and other Objective-C programs. Highlights of this release include: +- Support for Apple-compatible garbage collection APIs, along with extensions + to support CoreFoundation-style explicit reference counting in a garbage + collected environment. This uses the Boehm garbage collector. +- This is the first release to provide a superset of the functionality provided + by the Mac Objective-C runtime, as shipped with OS X 10.6. +- The LLVM optimisation passes have been improved and better tested. Code + compiled with them now passes the EtoileFoundation test suite. + You may obtain the code for this release from subversion at the following subversion branch: diff --git a/associate.m b/associate.m index c54df21..423d58f 100644 --- a/associate.m +++ b/associate.m @@ -8,6 +8,7 @@ #include "dtable.h" #include "selector.h" #include "lock.h" +#include "gc_ops.h" /** * A single associative reference. Contains the key, value, and association @@ -107,7 +108,7 @@ static void freeReferenceList(struct reference_list *l) { if (NULL == l) { return; } freeReferenceList(l->next); - free(l); + gc->free(l); } static void setReference(struct reference_list *list, @@ -145,7 +146,7 @@ static void setReference(struct reference_list *list, while (NULL != l->next) { l = l->next; } - l->next = calloc(1, sizeof(struct reference_list)); + l->next = gc->malloc(sizeof(struct reference_list)); r = &l->next->list[0]; } r->key = key; @@ -262,7 +263,7 @@ static struct reference_list* referenceListForObject(id object, BOOL create) lock_spinlock(lock); if (NULL == cls->extra_data) { - cls->extra_data = calloc(1, sizeof(struct reference_list)); + cls->extra_data = gc->malloc(sizeof(struct reference_list)); INIT_LOCK(cls->extra_data->lock); } unlock_spinlock(lock); diff --git a/blocks_runtime.m b/blocks_runtime.m index aa7baa1..837c7ad 100644 --- a/blocks_runtime.m +++ b/blocks_runtime.m @@ -25,6 +25,7 @@ */ #import "objc/blocks_runtime.h" #import "objc/runtime.h" +#include "gc_ops.h" #include #include #include @@ -314,7 +315,7 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags) if ((src->flags & BLOCK_REFCOUNT_MASK) == 0) { - *dst = malloc(src->size); + *dst = gc->malloc(src->size); fprintf(stderr, "Copying %d bytes to %p\n", src->size, *dst); memcpy(*dst, src, src->size); (*dst)->isa = _HeapBlockByRef; @@ -340,7 +341,7 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags) { src->byref_dispose(*dst); } - free(*dst); + gc->free(*dst); *dst = src->forwarding; } } @@ -402,7 +403,7 @@ void _Block_object_dispose(const void *object, const int flags) { src->byref_dispose(src); } - free(src); + gc->free(src); } } else @@ -458,7 +459,7 @@ void *_Block_copy(void *src) fprintf(stderr, "block flags: %d\n", self->flags); if(self->reserved == 0) { - ret = malloc(self->descriptor->size); + ret = gc->malloc(self->descriptor->size); memcpy(ret, self, self->descriptor->size); if(self->flags & BLOCK_HAS_COPY_DISPOSE) { @@ -486,7 +487,7 @@ void _Block_release(void *src) { if(self->flags & BLOCK_HAS_COPY_DISPOSE) self->descriptor->dispose_helper(self); - free(self); + gc->free(self); } } } diff --git a/gc_boehm.c b/gc_boehm.c index 4368bac..bd7444a 100644 --- a/gc_boehm.c +++ b/gc_boehm.c @@ -370,7 +370,9 @@ void objc_finalizeOnMainThread(Class cls) {} PRIVATE struct gc_ops gc_ops_boehm = { .allocate_class = allocate_class, - .init = init + .malloc = GC_malloc_uncollectable, + .free = GC_free, + .init = init }; PRIVATE void enableGC(BOOL exclude) diff --git a/gc_none.c b/gc_none.c index 32982f8..784b64e 100644 --- a/gc_none.c +++ b/gc_none.c @@ -9,9 +9,16 @@ static id allocate_class(Class cls, size_t extraBytes) return calloc(cls->instance_size + extraBytes, 1); } +static void *alloc(size_t size) +{ + return calloc(size, 1); +} + PRIVATE struct gc_ops gc_ops_none = { - .allocate_class = allocate_class + .allocate_class = allocate_class, + .malloc = alloc, + .free = free }; PRIVATE struct gc_ops *gc = &gc_ops_none; diff --git a/gc_ops.h b/gc_ops.h index ffc3fbf..31babac 100644 --- a/gc_ops.h +++ b/gc_ops.h @@ -1,3 +1,4 @@ + /** * Garbage collection operations. */ @@ -11,6 +12,17 @@ struct gc_ops * Allocates enough space for a class, followed by some extra bytes. */ id (*allocate_class)(Class, size_t); + /** + * Allocates some memory that can be used to store pointers. This must be + * used instead of malloc() for internal data structures that will store + * pointers passed in from outside. The function is expected to zero the + * memory that it returns. + */ + void* (*malloc)(size_t); + /** + * Frees some memory that was previously used to store pointers. + */ + void (*free)(void*); }; /** @@ -19,7 +31,7 @@ struct gc_ops * If the exclusive flag is set, then this will ensure that all -retain / * -release / -autorelease messages become no-ops. */ -PRIVATE void enableGC(BOOL exclusive); +void enableGC(BOOL exclusive); /** * The mode for garbage collection */