diff --git a/GNUmakefile b/GNUmakefile index 45a5fc2..ad30fe5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -18,6 +18,7 @@ ${LIBOBJC}_VERSION = 4 ${LIBOBJC}_OBJC_FILES = \ NSBlocks.m\ Protocol2.m\ + arc.m\ associate.m\ blocks_runtime.m\ mutation.m\ diff --git a/arc.m b/arc.m new file mode 100644 index 0000000..c69718f --- /dev/null +++ b/arc.m @@ -0,0 +1,123 @@ +#import "objc/runtime.h" +#import "objc/blocks_runtime.h" +#import "nsobject.h" +#import "selector.h" + +static Class AutoreleasePool; +static IMP NewAutoreleasePool; +static IMP DeleteAutoreleasePool; + +void *objc_autoreleasePoolPush(void) +{ + // TODO: This should be more lightweight. We really just need to allocate + // an array here... + if (Nil == AutoreleasePool) + { + AutoreleasePool = objc_getRequiredClass("NSAutoreleasePool"); + NewAutoreleasePool = class_getMethodImplementation( + object_getClass(AutoreleasePool), + SELECTOR(new)); + DeleteAutoreleasePool = class_getMethodImplementation( + object_getClass(AutoreleasePool), + SELECTOR(release)); + } + return NewAutoreleasePool(AutoreleasePool, SELECTOR(new)); +} +void objc_autoreleasePoolPop(void *pool) +{ + // TODO: Keep a small pool of autorelease pools per thread and allocate + // from there. + DeleteAutoreleasePool(pool, SELECTOR(release)); +} + +id objc_autorelease(id obj) +{ + return [obj autorelease]; +} + +id objc_autoreleaseReturnValue(id obj) +{ + // TODO: Fast path for allowing this to be popped from the pool. + return [obj autorelease]; +} + +id objc_retain(id obj) +{ + return [obj retain]; +} + +id objc_retainAutorelease(id obj) +{ + return objc_autorelease(objc_retain(obj)); +} + +id objc_retainAutoreleaseReturnValue(id obj) +{ + return objc_autoreleaseReturnValue(objc_retain(obj)); +} + +id objc_retainAutoreleasedReturnValue(id obj) +{ + // TODO: Fast path popping this from the autorelease pool + return objc_retain(obj); +} + +id objc_retainBlock(id b) +{ + return _Block_copy(b); +} + +void objc_release(id obj) +{ + [obj release]; +} + +id objc_storeStrong(id *object, id value) +{ + value = [value retain]; + id oldValue = *object; + *object = value; + [oldValue release]; + return value; +} + +//////////////////////////////////////////////////////////////////////////////// +// Weak references +//////////////////////////////////////////////////////////////////////////////// +// +//FIXME: These are all stubs! +#if 0 + +id objc_storeWeak(id*addr, id obj) { return obj;} + +id objc_loadWeakRetained(id* obj) +{ +} + +id objc_loadWeak(id* object) +{ + return objc_autorelease(objc_loadWeakRetained(object)); +} + + +void objc_moveWeak(id *dest, id *src) +{ +} + +void objc_copyWeak(id *dest, id *src) +{ + objc_release(objc_initWeak(dest, objc_loadWeakRetained(src))); +} + +void objc_destroyWeak(id* obj) +{ + objc_storeWeak(object, nil); +} + +id objc_initWeak(id*, id) +{ + *object = nil; + return objc_storeWeak(object, value); +} + +#endif diff --git a/gc_boehm.c b/gc_boehm.c index 47c3f09..ed1329d 100644 --- a/gc_boehm.c +++ b/gc_boehm.c @@ -186,45 +186,14 @@ BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate, id replaceme return objc_atomicCompareAndSwapPtr(predicate, replacement, objectLocation); } -SEL copy; -static const int MaxStackClasses = 16; -static Class StackClasses[MaxStackClasses]; -static IMP StackCopyFunctions[MaxStackClasses]; -static int StackClassCount; - -static inline id copy_to_heap(id val) -{ - if ((0 == val) || ((1 & (intptr_t)val) == 1)) { return val; } - for (unsigned int i=0 ; iisa == StackClasses[i]) - { - return StackCopyFunctions[i](val, copy); - } - } - return val; -} - -BOOL objc_register_stack_class(Class cls, IMP copyFunction) -{ - LOCK_RUNTIME_FOR_SCOPE(); - if (StackClassCount+1 >= MaxStackClasses) { return NO; } - StackClasses[StackClassCount] = cls; - StackCopyFunctions[StackClassCount] = copyFunction; - StackClassCount++; - return YES; -} - id objc_assign_strongCast(id val, id *ptr) { - val = copy_to_heap(val); *ptr = val; return val; } id objc_assign_global(id val, id *ptr) { - val = copy_to_heap(val); if (isGCEnabled) { GC_add_roots(ptr, ptr+1); @@ -235,7 +204,6 @@ id objc_assign_global(id val, id *ptr) id objc_assign_ivar(id val, id dest, ptrdiff_t offset) { - val = copy_to_heap(val); *(id*)((char*)dest+offset) = val; return val; } @@ -697,7 +665,7 @@ PRIVATE void init_gc(void) int s = envValue[0] ? (int)strtol(envValue, NULL, 10) : SIGUSR2; signal(s, collectAndDumpStats); } - GC_clear_roots(); + //GC_clear_roots(); } BOOL objc_collecting_enabled(void) @@ -761,7 +729,5 @@ PRIVATE void enableGC(BOOL exclude) refcount_initialize(&refcounts, 4096); finalize = sel_registerName("finalize"); cxx_destruct = sel_registerName(".cxx_destruct"); - copy = sel_registerName("copy"); GC_finalizer_notifier = runFinalizers; - objc_register_stack_class(&_NSConcreteStackBlock, (IMP)_Block_copy); } diff --git a/objc/runtime.h b/objc/runtime.h index 38888b8..d415ee2 100644 --- a/objc/runtime.h +++ b/objc/runtime.h @@ -9,6 +9,13 @@ extern "C" { # define __GNUSTEP_RUNTIME__ #endif +#ifndef __unsafe_unretained +# ifndef __has_feature +# define __unsafe_unretained +# elif !__has_feature(objc_arc) +# define __unsafe_unretained +# endif +#endif #include @@ -74,7 +81,7 @@ typedef struct objc_object struct objc_super { /** The receiver of the message. */ - id receiver; + __unsafe_unretained id receiver; /** The class containing the method to call. */ # if !defined(__cplusplus) && !__OBJC2__ Class class; @@ -224,7 +231,7 @@ objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount); * outCount argument is set to the number of protocols returned. The caller is * responsible for freeing the returned buffer. */ -Protocol ** class_copyProtocolList(Class cls, unsigned int *outCount); +Protocol *const* class_copyProtocolList(Class cls, unsigned int *outCount); /** * Creates an instance of this class, allocating memory using malloc. @@ -606,7 +613,7 @@ objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *count); * number of protocols in the array being returned via the last argument. The * caller is responsible for freeing this array. */ -Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count); +Protocol *const*protocol_copyProtocolList(Protocol *p, unsigned int *count); /** * Returns all of the protocols that the runtime is aware of. Note that @@ -616,7 +623,7 @@ Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count); * * The caller is responsible for freeing the returned array. */ -Protocol **objc_copyProtocolList(unsigned int *outCount); +Protocol *const*objc_copyProtocolList(unsigned int *outCount); /** * Returns the method description for the specified method within a given * protocol. diff --git a/protocol.c b/protocol.c index 66f43d1..d2791c5 100644 --- a/protocol.c +++ b/protocol.c @@ -329,7 +329,7 @@ struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, return out; } -Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count) +Protocol*const* protocol_copyProtocolList(Protocol *p, unsigned int *count) { if (NULL == p) { return NULL; } *count = 0; @@ -474,7 +474,7 @@ BOOL protocol_isEqual(Protocol *p, Protocol *other) return NO; } -Protocol **objc_copyProtocolList(unsigned int *outCount) +Protocol*const* objc_copyProtocolList(unsigned int *outCount) { unsigned int total = known_protocol_table->table_used; Protocol **p = calloc(sizeof(Protocol*), known_protocol_table->table_used); diff --git a/runtime.c b/runtime.c index 298024f..f2ffcb2 100644 --- a/runtime.c +++ b/runtime.c @@ -235,7 +235,7 @@ Method * class_copyMethodList(Class cls, unsigned int *outCount) return list; } -Protocol** class_copyProtocolList(Class cls, unsigned int *outCount) +Protocol*const* class_copyProtocolList(Class cls, unsigned int *outCount) { CHECK_ARG(cls); struct objc_protocol_list *protocolList = NULL;