diff --git a/ANNOUNCE b/ANNOUNCE index cedbe8b..4016e26 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -8,15 +8,17 @@ release include: - Support for small objects (ones hidden inside a pointer). On 32-bit systems, the runtime permits one small object class, on 64-bit systems it permits 4. +- Support for prototype-style object orientation. You can now add methods, as + well as associated references, to individual objects. You may obtain the code for this release from subversion at the following subversion branch: -svn://svn.gna.org/svn/gnustep/libs/libobjc2/1.5 +svn://svn.gna.org/svn/gnustep/libs/libobjc2/1.6 Alternatively, a tarball is available from: -http://download.gna.org/gnustep/libobjc2-1.5.tar.bz2 +http://download.gna.org/gnustep/libobjc2-1.6.tar.bz2 The runtime library is responsible for implementing the core features of the object model, as well as exposing introspection features to the user. The diff --git a/Makefile b/Makefile index ff17db2..5795769 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ .SUFFIXES: .cc .c .m .o MAJOR_VERSION = 1 -MINOR_VERSION = 5 +MINOR_VERSION = 6 SUBMINOR_VERSION = 0 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) diff --git a/associate.m b/associate.m index ebbac08..1cf5525 100644 --- a/associate.m +++ b/associate.m @@ -227,13 +227,14 @@ static inline Class initHiddenClassForObject(id obj) } else { - const char *types = - method_getTypeEncoding(class_getInstanceMethod(obj->isa, - SELECTOR(dealloc))); - class_addMethod(hiddenClass, SELECTOR(dealloc), (IMP)deallocHiddenClass, - types); - class_addMethod(hiddenClass, SELECTOR(finalize), (IMP)deallocHiddenClass, - types); + static SEL cxx_destruct; + if (NULL == cxx_destruct) + { + cxx_destruct = sel_registerName(".cxx_destruct"); + } + const char *types = sizeof(void*) == 4 ? "v8@0:4" : "v16@0:8"; + class_addMethod(hiddenClass, cxx_destruct, + (IMP)deallocHiddenClass, types); obj->isa = hiddenClass; } return hiddenClass; @@ -242,20 +243,13 @@ static inline Class initHiddenClassForObject(id obj) static void deallocHiddenClass(id obj, SEL _cmd) { Class hiddenClass = findHiddenClass(obj); - Class realClass = class_getSuperclass(hiddenClass); - // Call the real -dealloc method (this ordering is required in case the - // user does @synchronized(self) in -dealloc) - struct objc_super super = {obj, realClass}; - objc_msg_lookup_super(&super, _cmd)(obj, _cmd); // After calling [super dealloc], the object will no longer exist. // Free the hidden struct reference_list *list = object_getIndexedIvars(hiddenClass); DESTROY_LOCK(&list->lock); cleanupReferenceList(list); freeReferenceList(list->next); - free_dtable(hiddenClass->dtable); - // Free the class free(hiddenClass); } @@ -357,3 +351,37 @@ int objc_sync_exit(id object) } return 1; } + +static Class hiddenClassForObject(id object) +{ + if (isSmallObject(object)) { return nil; } + if (class_isMetaClass(object->isa)) + { + return object->isa; + } + Class hiddenClass = findHiddenClass(object); + if (NULL == hiddenClass) + { + volatile int *lock = lock_for_pointer(object); + lock_spinlock(lock); + hiddenClass = findHiddenClass(object); + if (NULL == hiddenClass) + { + hiddenClass = initHiddenClassForObject(object); + struct reference_list *list = object_getIndexedIvars(hiddenClass); + INIT_LOCK(list->lock); + } + unlock_spinlock(lock); + } + return hiddenClass; +} + +BOOL object_addMethod_np(id object, SEL name, IMP imp, const char *types) +{ + return class_addMethod(hiddenClassForObject(object), name, imp, types); +} + +IMP object_replaceMethod_np(id object, SEL name, IMP imp, const char *types) +{ + return class_replaceMethod(hiddenClassForObject(object), name, imp, types); +} diff --git a/objc/runtime.h b/objc/runtime.h index fe1fbc1..9ba510d 100644 --- a/objc/runtime.h +++ b/objc/runtime.h @@ -822,6 +822,17 @@ void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPo */ void objc_removeAssociatedObjects(id object); +/** + * Adds a method to a specific object, This method will not be added to any + * other instances of the same class. + */ +BOOL object_addMethod_np(id object, SEL name, IMP imp, const char *types); + +/** + * Replaces a method on a specific object, This method will not be added to + * any other instances of the same class. + */ +IMP object_replaceMethod_np(id object, SEL name, IMP imp, const char *types); /** * Toggles whether Objective-C objects caught in C++ exception handlers in diff --git a/runtime.c b/runtime.c index 0001b39..7ce0d11 100644 --- a/runtime.c +++ b/runtime.c @@ -41,8 +41,8 @@ PRIVATE void call_cxx_destruct(id obj) cls = Nil; if (NULL != slot) { - slot->method(obj, cxx_destruct); cls = slot->owner->super_class; + slot->method(obj, cxx_destruct); } } }