Basic support for prototype-style object orientation (you can now add methods to an individual object).

main
theraven 15 years ago
parent 55d86bba6c
commit b54719abf1

@ -8,15 +8,17 @@ release include:
- Support for small objects (ones hidden inside a pointer). On 32-bit systems, - 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. 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 You may obtain the code for this release from subversion at the following
subversion branch: 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: 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 The runtime library is responsible for implementing the core features of the
object model, as well as exposing introspection features to the user. The object model, as well as exposing introspection features to the user. The

@ -3,7 +3,7 @@
.SUFFIXES: .cc .c .m .o .SUFFIXES: .cc .c .m .o
MAJOR_VERSION = 1 MAJOR_VERSION = 1
MINOR_VERSION = 5 MINOR_VERSION = 6
SUBMINOR_VERSION = 0 SUBMINOR_VERSION = 0
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION) VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION)

@ -227,13 +227,14 @@ static inline Class initHiddenClassForObject(id obj)
} }
else else
{ {
const char *types = static SEL cxx_destruct;
method_getTypeEncoding(class_getInstanceMethod(obj->isa, if (NULL == cxx_destruct)
SELECTOR(dealloc))); {
class_addMethod(hiddenClass, SELECTOR(dealloc), (IMP)deallocHiddenClass, cxx_destruct = sel_registerName(".cxx_destruct");
types); }
class_addMethod(hiddenClass, SELECTOR(finalize), (IMP)deallocHiddenClass, const char *types = sizeof(void*) == 4 ? "v8@0:4" : "v16@0:8";
types); class_addMethod(hiddenClass, cxx_destruct,
(IMP)deallocHiddenClass, types);
obj->isa = hiddenClass; obj->isa = hiddenClass;
} }
return hiddenClass; return hiddenClass;
@ -242,20 +243,13 @@ static inline Class initHiddenClassForObject(id obj)
static void deallocHiddenClass(id obj, SEL _cmd) static void deallocHiddenClass(id obj, SEL _cmd)
{ {
Class hiddenClass = findHiddenClass(obj); 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. // After calling [super dealloc], the object will no longer exist.
// Free the hidden // Free the hidden
struct reference_list *list = object_getIndexedIvars(hiddenClass); struct reference_list *list = object_getIndexedIvars(hiddenClass);
DESTROY_LOCK(&list->lock); DESTROY_LOCK(&list->lock);
cleanupReferenceList(list); cleanupReferenceList(list);
freeReferenceList(list->next); freeReferenceList(list->next);
free_dtable(hiddenClass->dtable); free_dtable(hiddenClass->dtable);
// Free the class // Free the class
free(hiddenClass); free(hiddenClass);
} }
@ -357,3 +351,37 @@ int objc_sync_exit(id object)
} }
return 1; 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);
}

@ -822,6 +822,17 @@ void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPo
*/ */
void objc_removeAssociatedObjects(id object); 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 * Toggles whether Objective-C objects caught in C++ exception handlers in

@ -41,8 +41,8 @@ PRIVATE void call_cxx_destruct(id obj)
cls = Nil; cls = Nil;
if (NULL != slot) if (NULL != slot)
{ {
slot->method(obj, cxx_destruct);
cls = slot->owner->super_class; cls = slot->owner->super_class;
slot->method(obj, cxx_destruct);
} }
} }
} }

Loading…
Cancel
Save