33
33
#define InterlockedDecrement BadInterlockedDecrement
37
#include "GNUstepBase/preface.h"
39
#include "Foundation/NSObject.h"
40
37
#include <objc/Protocol.h>
41
#include "Foundation/NSMethodSignature.h"
42
#include "Foundation/NSInvocation.h"
43
#include "Foundation/NSLock.h"
44
#include "Foundation/NSAutoreleasePool.h"
45
#include "Foundation/NSString.h"
46
#include "Foundation/NSArray.h"
47
#include "Foundation/NSException.h"
48
#include "Foundation/NSPortCoder.h"
49
#include "Foundation/NSDistantObject.h"
50
#include "Foundation/NSZone.h"
51
#include "Foundation/NSDebug.h"
52
#include "Foundation/NSThread.h"
53
#include "Foundation/NSNotification.h"
54
#include "Foundation/NSObjCRuntime.h"
55
#include "Foundation/NSMapTable.h"
57
#include "GNUstepBase/GSLocale.h"
38
#import "Foundation/NSMethodSignature.h"
39
#import "Foundation/NSInvocation.h"
40
#import "Foundation/NSLock.h"
41
#import "Foundation/NSAutoreleasePool.h"
42
#import "Foundation/NSArray.h"
43
#import "Foundation/NSException.h"
44
#import "Foundation/NSPortCoder.h"
45
#import "Foundation/NSDistantObject.h"
46
#import "Foundation/NSThread.h"
47
#import "Foundation/NSNotification.h"
48
#import "Foundation/NSMapTable.h"
49
#import "GNUstepBase/GSLocale.h"
58
50
#ifdef HAVE_LOCALE_H
59
51
#include <locale.h>
109
106
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector;
109
@interface GSContentAccessingProxy : NSProxy
111
NSObject<NSDiscardableContent> *object;
113
- (id) initWithObject: (id)anObject;
113
117
* allocationLock is needed when running multi-threaded for
114
* protecting the map table of zombie information and for retain
115
* count protection (when using a map table ... REFCNT_LOCAL is NO)
118
* protecting the map table of zombie information.
117
static objc_mutex_t allocationLock = NULL;
120
static NSLock *allocationLock;
119
122
BOOL NSZombieEnabled = NO;
120
123
BOOL NSDeallocateZombies = NO;
123
126
static Class zombieClass;
124
static NSMapTable zombieMap;
127
static NSMapTable *zombieMap;
126
130
static void GSMakeZombie(NSObject *o)
128
132
Class c = ((id)o)->class_pointer;
149
148
if (NSDeallocateZombies == NO)
151
if (allocationLock != 0)
153
objc_mutex_lock(allocationLock);
150
[allocationLock lock];
155
151
c = NSMapGet(zombieMap, (void*)o);
156
if (allocationLock != 0)
158
objc_mutex_unlock(allocationLock);
152
[allocationLock unlock];
163
NSLog(@"Deallocated object (0x%x) sent %@",
156
NSLog(@"Deallocated object (%p) sent %@",
164
157
o, NSStringFromSelector(sel));
168
NSLog(@"Deallocated %@ (0x%x) sent %@",
169
NSStringFromClass(c), o, NSStringFromSelector(sel));
161
NSLog(@"Deallocated %@ (%p) sent %@",
162
c, o, NSStringFromSelector(sel));
171
164
if (GSPrivateEnvironmentFlag("CRASH_ON_ZOMBIE", NO) == YES)
179
172
* Reference count and memory management
181
* If REFCNT_LOCAL is defined, reference counts for object are stored
182
* with the object, otherwise they are stored in a global map table
183
* that has to be protected by mutexes in a multithreraded environment.
184
* You therefore want REFCNT_LOCAL defined for best performance.
186
* If CACHE_ZONE is defined, the zone in which an object has been
187
* allocated is stored with the object - this makes lookup of the
188
* correct zone to free memory very fast.
173
* Reference counts for object are stored
175
* The zone in which an object has been
176
* allocated is stored with the object.
192
#if GS_WITH_GC == 0 && !defined(NeXT_RUNTIME)
193
#define REFCNT_LOCAL 1
198
179
/* Now, if we are on a platform where we know how to do atomic
199
180
* read, increment, and decrement, then we define the GSATOMICREAD
200
181
* macro and macros or functions to increment/decrement.
229
208
#define GSAtomicIncrement(X) InterlockedIncrement((LONG volatile*)X)
230
209
#define GSAtomicDecrement(X) InterlockedDecrement((LONG volatile*)X)
212
#elif defined(__llvm__) || (defined(USE_ATOMIC_BUILDINS) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)))
213
/* Use the GCC atomic operations with recent GCC versions */
215
typedef int32_t volatile *gsatomic_t;
216
#define GSATOMICREAD(X) (*(X))
217
#define GSAtomicIncrement(X) __sync_fetch_and_add(X, 1)
218
#define GSAtomicDecrement(X) __sync_fetch_and_sub(X, 1)
235
221
#elif defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
287
273
__asm__ __volatile__ (
289
275
"lwarx %0,0,%1 \n"
290
276
"addic %0,%0,-1 \n"
291
277
"stwcx. %0,0,%1 \n"
295
281
:"cc", "memory");
285
#elif defined(__m68k__)
287
typedef int32_t volatile *gsatomic_t;
289
#define GSATOMICREAD(X) (*(X))
291
static __inline__ int
292
GSAtomicIncrement(gsatomic_t X)
294
__asm__ __volatile__ (
300
static __inline__ int
301
GSAtomicDecrement(gsatomic_t X)
303
__asm__ __volatile__ (
309
#elif defined(__mips__)
311
typedef int32_t volatile *gsatomic_t;
313
#define GSATOMICREAD(X) (*(X))
315
static __inline__ int
316
GSAtomicIncrement(gsatomic_t X)
320
__asm__ __volatile__ (
326
:"=&r" (tmp), "=m" (*X));
330
static __inline__ int
331
GSAtomicDecrement(gsatomic_t X)
335
__asm__ __volatile__ (
341
:"=&r" (tmp), "=m" (*X));
301
#if defined(REFCNT_LOCAL) && !defined(GSATOMICREAD)
346
#if !defined(GSATOMICREAD)
304
349
* Having just one allocationLock for all leads to lock contention
305
350
* if there are lots of threads doing lots of retain/release calls.
306
* To alleviate this, if using REFCNT_LOCAL, instead of a single
351
* To alleviate this, instead of a single
307
352
* allocationLock for all objects, we divide the object space into
308
353
* chunks, each with its own lock. The chunk is selected by shifting
309
354
* off the low-order ALIGNBITS of the object's pointer (these bits
316
361
#define LOCKMASK (LOCKCOUNT-1)
317
362
#define ALIGNBITS 3
319
static objc_mutex_t allocationLocks[LOCKCOUNT] = { 0 };
364
static NSLock *allocationLocks[LOCKCOUNT] = { 0 };
321
static inline objc_mutex_t GSAllocationLockForObject(id p)
366
static inline NSLock *GSAllocationLockForObject(id p)
323
unsigned i = ((((unsigned)(uintptr_t)p) >> ALIGNBITS) & LOCKMASK);
368
NSUInteger i = ((((NSUInteger)(uintptr_t)p) >> ALIGNBITS) & LOCKMASK);
324
369
return allocationLocks[i];
354
393
* structure correct.
356
395
struct obj_layout {
357
#if defined(REFCNT_LOCAL)
360
#if defined(CACHE_ZONE)
363
398
char padding[ALIGN - ((UNP % ALIGN) ? (UNP % ALIGN) : ALIGN)];
365
400
typedef struct obj_layout *obj;
367
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
369
#if !defined(REFCNT_LOCAL)
372
* Set up map table for non-local reference counts.
375
#define GSI_MAP_EQUAL(M, X, Y) (X.obj == Y.obj)
376
#define GSI_MAP_HASH(M, X) (X.uint >> 2)
377
#define GSI_MAP_RETAIN_KEY(M, X)
378
#define GSI_MAP_RELEASE_KEY(M, X)
379
#define GSI_MAP_RETAIN_VAL(M, X)
380
#define GSI_MAP_RELEASE_VAL(M, X)
381
#define GSI_MAP_KTYPES GSUNION_OBJ|GSUNION_INT
382
#define GSI_MAP_VTYPES GSUNION_INT
383
#define GSI_MAP_NOCLEAN 1
385
#include "GNUstepBase/GSIMap.h"
387
static GSIMapTable_t retain_counts = {0};
389
#endif /* !defined(REFCNT_LOCAL) */
393
404
* Examines the extra reference count for the object and, if non-zero
403
414
if (double_release_check_enabled)
405
unsigned release_count;
406
unsigned retain_count = [anObject retainCount];
416
NSUInteger release_count;
417
NSUInteger retain_count = [anObject retainCount];
407
418
release_count = [autorelease_class autoreleaseCountForObject: anObject];
408
419
if (release_count >= retain_count)
409
420
[NSException raise: NSGenericException
410
421
format: @"Release would release object too many times."];
412
#if defined(REFCNT_LOCAL)
413
423
if (allocationLock != 0)
415
425
#if defined(GSATOMICREAD)
436
446
#else /* GSATOMICREAD */
437
objc_mutex_t theLock = GSAllocationLockForObject(anObject);
447
NSLock *theLock = GSAllocationLockForObject(anObject);
439
objc_mutex_lock(theLock);
440
450
if (((obj)anObject)[-1].retained == 0)
442
objc_mutex_unlock(theLock);
447
457
((obj)anObject)[-1].retained--;
448
objc_mutex_unlock(theLock);
451
461
#endif /* GSATOMICREAD */
468
if (allocationLock != 0)
470
objc_mutex_lock(allocationLock);
471
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
474
objc_mutex_unlock(allocationLock);
477
if (node->value.uint == 0)
479
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
480
objc_mutex_unlock(allocationLock);
485
(node->value.uint)--;
487
objc_mutex_unlock(allocationLock);
491
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
496
if ((node->value.uint) == 0)
498
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
503
--(node->value.uint);
475
#endif /* !GS_WITH_GC */
513
481
* from 0 to the maximum unsigned integer value minus one).<br />
514
482
* The retain count for an object is this value plus one.
517
485
NSExtraRefCount(id anObject)
520
488
return UINT_MAX - 1;
521
489
#else /* GS_WITH_GC */
522
#if defined(REFCNT_LOCAL)
523
490
return ((obj)anObject)[-1].retained;
528
if (allocationLock != 0)
530
objc_mutex_t theLock = GSAllocationLockForObject(anObject);
532
objc_mutex_lock(theLock);
533
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
540
ret = node->value.uint;
542
objc_mutex_unlock(theLock);
546
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
553
ret = node->value.uint;
491
#endif /* GS_WITH_GC */
585
517
format: @"NSIncrementExtraRefCount() asked to increment too far"];
587
519
#else /* GSATOMICREAD */
588
objc_mutex_t theLock = GSAllocationLockForObject(anObject);
520
NSLock *theLock = GSAllocationLockForObject(anObject);
590
objc_mutex_lock(theLock);
591
523
if (((obj)anObject)[-1].retained == UINT_MAX - 1)
593
objc_mutex_unlock (theLock);
594
526
[NSException raise: NSInternalInconsistencyException
595
527
format: @"NSIncrementExtraRefCount() asked to increment too far"];
597
529
((obj)anObject)[-1].retained++;
598
objc_mutex_unlock (theLock);
599
531
#endif /* GSATOMICREAD */
608
540
((obj)anObject)[-1].retained++;
610
#else /* REFCNT_LOCAL */
613
if (allocationLock != 0)
615
objc_mutex_lock(allocationLock);
616
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
619
if ((node->value.uint) == UINT_MAX - 1)
621
objc_mutex_unlock(allocationLock);
622
[NSException raise: NSInternalInconsistencyException
624
@"NSIncrementExtraRefCount() asked to increment too far"];
626
(node->value.uint)++;
630
GSIMapAddPair(&retain_counts, (GSIMapKey)anObject, (GSIMapVal)1);
632
objc_mutex_unlock(allocationLock);
636
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
639
if ((node->value.uint) == UINT_MAX - 1)
641
[NSException raise: NSInternalInconsistencyException
643
@"NSIncrementExtraRefCount() asked to increment too far"];
645
(node->value.uint)++;
649
GSIMapAddPair(&retain_counts, (GSIMapKey)anObject, (GSIMapVal)1);
652
#endif /* REFCNT_LOCAL */
653
542
#endif /* GS_WITH_GC */
546
#define AADD(c, o) GSDebugAllocationAdd(c, o)
547
#define AREM(c, o) GSDebugAllocationRemove(c, o)
658
554
* Now do conditional compilation of memory allocation functions
665
561
GSObjCZone(NSObject *object)
563
GSOnceFLog(@"GSObjCZone() is deprecated ... use -zone instead");
564
/* MacOS-X 10.5 seems to return the default malloc zone if GC is enabled.
566
return NSDefaultMallocZone();
671
570
GSFinalize(void* object, void* data)
673
[(id)object gcFinalize];
675
GSDebugAllocationRemove(((id)object)->class_pointer, (id)object);
572
[(id)object finalize];
573
AREM(((id)object)->class_pointer, (id)object);
677
574
((id)object)->class_pointer = (void*)0xdeadface;
681
NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone)
578
GSIsFinalizable(Class c)
580
if (get_imp(c, finalize_sel) != finalize_imp)
586
NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone)
686
592
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
687
size = aClass->instance_size + extraBytes;
688
if (zone == GSAtomicMallocZone())
690
new = NSZoneMalloc(zone, size);
593
gc_type = (GC_descr)aClass->gc_object_type;
594
size = class_getInstanceSize(aClass) + extraBytes;
595
if (size % sizeof(void*) != 0)
597
/* Size must be a multiple of pointer size for the garbage collector
598
* to be able to allocate explicitly typed memory.
600
size += sizeof(void*) - size % sizeof(void*);
605
new = NSZoneCalloc(zone, 1, size);
606
NSLog(@"No garbage collection information for '%s'",
607
class_getName(aClass));
694
GC_descr gc_type = (GC_descr)aClass->gc_object_type;
698
new = NSZoneMalloc(zone, size);
699
NSLog(@"No garbage collection information for '%s'",
700
GSNameFromClass(aClass));
702
else if ([aClass requiresTypedMemory])
704
new = GC_CALLOC_EXPLICTLY_TYPED(1, size, gc_type);
708
new = NSZoneMalloc(zone, size);
611
new = GC_calloc_explicitly_typed(1, size, gc_type);
714
memset(new, 0, size);
715
616
new->class_pointer = aClass;
716
if (__objc_responds_to(new, @selector(gcFinalize)))
617
if (GSIsFinalizable(aClass))
720
* We only do allocation counting for objects that can be
721
* finalised - for other objects we have no way of decrementing
722
* the count when the object is collected.
619
/* We only do allocation counting for objects that can be
620
* finalised - for other objects we have no way of decrementing
621
* the count when the object is collected.
724
GSDebugAllocationAdd(aClass, new);
726
624
GC_REGISTER_FINALIZER (new, GSFinalize, NULL, NULL, NULL);
733
NSDeallocateObject(NSObject *anObject)
631
NSDeallocateObject(id anObject)
737
635
#else /* GS_WITH_GC */
739
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
741
#if defined(CACHE_ZONE)
744
638
GSObjCZone(NSObject *object)
746
if (GSObjCClass(object) == NSConstantStringClass)
640
GSOnceFLog(@"GSObjCZone() is deprecated ... use -zone instead");
641
if (object_getClass(object) == NSConstantStringClass)
747
642
return NSDefaultMallocZone();
748
643
return ((obj)object)[-1].zone;
751
#else /* defined(CACHE_ZONE) */
754
GSObjCZone(NSObject *object)
756
if (GSObjCClass(object) == NSConstantStringClass)
757
return NSDefaultMallocZone();
758
return NSZoneFromPointer(&((obj)object)[-1]);
761
#endif /* defined(CACHE_ZONE) */
764
NSAllocateObject (Class aClass, unsigned extraBytes, NSZone *zone)
767
extern void GSDebugAllocationAdd(Class c, id o);
647
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
772
652
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
773
size = aClass->instance_size + extraBytes + sizeof(struct obj_layout);
653
size = class_getInstanceSize(aClass) + extraBytes + sizeof(struct obj_layout);
776
656
zone = NSDefaultMallocZone();
781
661
memset (new, 0, size);
782
#if defined(CACHE_ZONE)
783
662
((obj)new)->zone = zone;
785
663
new = (id)&((obj)new)[1];
786
664
new->class_pointer = aClass;
788
GSDebugAllocationAdd(aClass, new);
795
NSDeallocateObject(NSObject *anObject)
671
NSDeallocateObject(id anObject)
798
extern void GSDebugAllocationRemove(Class c, id o);
800
673
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
802
675
obj o = &((obj)anObject)[-1];
803
NSZone *z = GSObjCZone(anObject);
806
GSDebugAllocationRemove(((id)anObject)->class_pointer, (id)anObject);
678
AREM(((id)anObject)->class_pointer, (id)anObject);
808
679
if (NSZombieEnabled == YES)
810
681
GSMakeZombie(anObject);
696
#endif /* GS_WITH_GC */
700
GSPrivateSwizzle(id o, Class c)
702
if ((Class)o->class_pointer != c)
705
/* We only do allocation counting for objects that can be
706
* finalised - for other objects we have no way of decrementing
707
* the count when the object is collected.
709
if (GSIsFinalizable(o->class_pointer))
711
/* Already finalizable, so we just need to do any allocation
714
AREM(o->class_pointer, o);
717
else if (GSIsFinalizable(c))
719
/* New class is finalizable, so we must register the instance
720
* for finalisation and do allocation acounting for it.
723
GC_REGISTER_FINALIZER (o, GSFinalize, NULL, NULL, NULL);
828
GSObjCZone(NSObject *object)
830
if (GSObjCClass(object) == NSConstantStringClass)
831
return NSDefaultMallocZone();
832
return NSZoneFromPointer(object);
836
NSAllocateObject (Class aClass, unsigned extraBytes, NSZone *zone)
841
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
842
size = aClass->instance_size + extraBytes;
843
new = NSZoneMalloc (zone, size);
846
memset (new, 0, size);
847
new->class_pointer = aClass;
849
GSDebugAllocationAdd(aClass, new);
856
NSDeallocateObject(NSObject *anObject)
858
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
860
NSZone *z = [anObject zone];
863
GSDebugAllocationRemove(((id)anObject)->class_pointer, (id)anObject);
865
if (NSZombieEnabled == YES)
867
GSMakeZombie(anObject);
868
if (NSDeallocateZombies == YES)
870
NSZoneFree(z, anObject);
875
((id)anObject)->class_pointer = (void*) 0xdeadface;
876
NSZoneFree(z, anObject);
882
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
726
AREM(o->class_pointer, o);
884
728
#endif /* GS_WITH_GC */
729
o->class_pointer = c;
887
735
NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
892
740
return (!requestedZone || requestedZone == NSDefaultMallocZone()
893
|| GSObjCZone(anObject) == requestedZone);
741
|| [anObject zone] == requestedZone);
747
/* FIXME ... the following code is a hack for the gnu runtime only
900
749
struct objc_method_description_list {
902
751
struct objc_method_description list[1];
754
/* Must have same layout as ivars of Protocol class
756
struct protocol_class {
759
struct objc_protocol_list *protocol_list;
760
struct objc_method_description_list *instance_methods;
761
struct objc_method_description_list *class_methods;
908
764
struct objc_method_description *
909
GSDescriptionForInstanceMethod(pcl self, SEL aSel)
765
GSDescriptionForInstanceMethod(Protocol *self, SEL aSel)
767
struct protocol_class *pcl = (struct protocol_class*)self;
912
769
struct objc_protocol_list *p_list;
913
const char *name = GSNameFromSelector(aSel);
770
const char *name = sel_getName(aSel);
914
771
struct objc_method_description *result;
916
if (self->instance_methods != 0)
773
if (pcl->instance_methods != 0)
918
for (i = 0; i < self->instance_methods->count; i++)
775
for (i = 0; i < pcl->instance_methods->count; i++)
920
if (!strcmp ((char*)self->instance_methods->list[i].name, name))
921
return &(self->instance_methods->list[i]);
777
if (!strcmp ((char*)pcl->instance_methods->list[i].name, name))
778
return &(pcl->instance_methods->list[i]);
924
for (p_list = self->protocol_list; p_list != 0; p_list = p_list->next)
781
for (p_list = pcl->protocol_list; p_list != 0; p_list = p_list->next)
926
783
for (i = 0; i < p_list->count; i++)
928
result = GSDescriptionForInstanceMethod((pcl)p_list->list[i], aSel);
785
result = GSDescriptionForInstanceMethod(p_list->list[i], aSel);
939
796
struct objc_method_description *
940
GSDescriptionForClassMethod(pcl self, SEL aSel)
797
GSDescriptionForClassMethod(Protocol *self, SEL aSel)
799
struct protocol_class *pcl = (struct protocol_class*)self;
943
801
struct objc_protocol_list *p_list;
944
const char *name = GSNameFromSelector(aSel);
802
const char *name = sel_getName(aSel);
945
803
struct objc_method_description *result;
947
if (self->class_methods != 0)
805
if (pcl->class_methods != 0)
949
for (i = 0; i < self->class_methods->count; i++)
807
for (i = 0; i < pcl->class_methods->count; i++)
951
if (!strcmp ((char*)self->class_methods->list[i].name, name))
952
return &(self->class_methods->list[i]);
809
if (!strcmp ((char*)pcl->class_methods->list[i].name, name))
810
return &(pcl->class_methods->list[i]);
955
for (p_list = self->protocol_list; p_list != 0; p_list = p_list->next)
813
for (p_list = pcl->protocol_list; p_list != 0; p_list = p_list->next)
957
815
for (i = 0; i < p_list->count; i++)
959
result = GSDescriptionForClassMethod((pcl)p_list->list[i], aSel);
817
result = GSDescriptionForClassMethod(p_list->list[i], aSel);
972
830
- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel
974
return GSDescriptionForInstanceMethod((pcl)self, aSel);
832
return GSDescriptionForInstanceMethod(self, aSel);
977
835
- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel;
979
return GSDescriptionForClassMethod((pcl)self, aSel);
837
return GSDescriptionForClassMethod(self, aSel);
1047
905
if (allocationLock == 0)
1049
#if defined(REFCNT_LOCAL) && !defined(GSATOMICREAD)
907
#if !defined(GSATOMICREAD)
1052
910
for (i = 0; i < LOCKCOUNT; i++)
1054
allocationLocks[i] = objc_mutex_allocate();
912
allocationLocks[i] = [NSLock new];
1057
allocationLock = objc_mutex_allocate();
915
allocationLock = [NSLock new];
1063
* A utility method used when garbage collection is enabled. Can be ignored.
1065
+ (BOOL) requiresTypedMemory
1072
* This message is sent to a class once just before it is used for the first
1073
* time. If class has a superclass, its implementation of +initialize is
1074
* called first. You can implement +initialize in your own class if you need
1075
* to. NSObject's implementation handles essential root object and base
1076
* library initialization.
920
/* Function to log Boehm GC warnings
921
* NB. This must not allocate any collectable memory as it may result
922
* in a deadlock in the garbage collecting library.
925
GSGarbageCollectorLog(char *msg, GC_word arg)
927
char buf[strlen(msg)+1024];
928
sprintf(buf, msg, (unsigned long)arg);
929
fprintf(stderr, "Garbage collector: %s", buf);
934
* Semi-private function in libobjc2 that initialises the classes used for
939
objc_create_block_classes_as_subclasses_of(Class super) __attribute__((weak));
945
/* When NSObject is loaded, register it as the superclass of the block
947
if (objc_create_block_classes_as_subclasses_of)
948
objc_create_block_classes_as_subclasses_of(self);
1078
952
+ (void) initialize
1080
954
if (self == [NSObject class])
1083
// See libgnustep-base-entry.m
1084
extern void gnustep_base_socket_init(void);
1085
gnustep_base_socket_init();
957
/* Make sure that the garbage collection library is initialised.
958
* This is not necessary on most platforms, but is good practice.
961
GC_set_warn_proc(GSGarbageCollectorLog);
966
// See libgnustep-base-entry.m
967
extern void gnustep_base_socket_init(void);
968
gnustep_base_socket_init();
970
#else /* __MINGW__ */
1123
1007
signal(SIGPIPE, handler);
1010
#endif /* HAVE_SIGACTION */
1011
#endif /* SIGPIPE */
1012
#endif /* __MINGW__ */
1015
finalize_sel = @selector(finalize);
1016
finalize_imp = get_imp(self, finalize_sel);
1130
1019
#if defined(__FreeBSD__) && defined(__i386__)
1131
1020
// Manipulate the FPU to add the exception mask. (Fixes SIGFPE
1132
1021
// problems on *BSD)
1133
1022
// Note this only works on x86
1138
__asm__ volatile ("fstcw (%0)" : : "g" (&cw));
1139
cw |= 1; /* Mask 'invalid' exception */
1140
__asm__ volatile ("fldcw (%0)" : : "g" (&cw));
1023
fedisableexcept(FE_INVALID);
1145
1026
#ifdef HAVE_LOCALE_H
1146
1027
GSSetLocaleC(LC_ALL, ""); // Set up locale from environment.
1149
1030
// Create the global lock
1150
1031
gnustep_global_lock = [NSRecursiveLock new];
1033
// Behavior debugging
1034
GSObjCBehaviorDebug(GSPrivateEnvironmentFlag("GNUSTEP_BEHAVIOR_DEBUG",
1035
GSObjCBehaviorDebug(-1)));
1152
1037
// Zombie management stuff.
1153
1038
zombieMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
1154
1039
NSNonOwnedPointerMapValueCallBacks, 0);
1159
1044
autorelease_class = [NSAutoreleasePool class];
1160
1045
autorelease_sel = @selector(addObject:);
1161
1046
autorelease_imp = [autorelease_class methodForSelector: autorelease_sel];
1163
#if !defined(REFCNT_LOCAL)
1164
GSIMapInitWithZoneAndCapacity(&retain_counts,
1165
NSDefaultMallocZone(), 1024);
1168
1047
NSConstantStringClass = [NSString constantStringClass];
1169
1048
GSPrivateBuildStrings();
1170
1049
[[NSNotificationCenter defaultCenter]
1564
1448
[NSException raise: NSInvalidArgumentException
1565
1449
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
1567
* If 'self' is an instance, GSObjCClass() will get the class,
1451
* If 'self' is an instance, object_getClass() will get the class,
1568
1452
* and get_imp() will get the instance method.
1569
* If 'self' is a class, GSObjCClass() will get the meta-class,
1453
* If 'self' is a class, object_getClass() will get the meta-class,
1570
1454
* and get_imp() will get the class method.
1572
return get_imp(GSObjCClass(self), aSelector);
1456
return get_imp(object_getClass(self), aSelector);
1608
1491
[NSException raise: NSInvalidArgumentException
1609
1492
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
1611
selTypes = sel_get_type(aSelector);
1612
c = (GSObjCIsInstance(self) ? GSObjCClass(self) : (Class)self);
1494
c = (GSObjCIsInstance(self) ? object_getClass(self) : (Class)self);
1613
1495
mth = GSGetMethod(c, aSelector, GSObjCIsInstance(self), YES);
1668
else if (selTypes != 0 && GSSelectorTypesMatch(selTypes, types) == NO)
1670
[NSException raise: NSInternalInconsistencyException
1671
format: @"[%@%c%@] selector types (%s) don't match method types (%s)",
1672
NSStringFromClass(c), (GSObjCIsInstance(self) ? '-' : '+'),
1673
NSStringFromSelector(aSelector), selTypes, types];
1675
1550
return [NSMethodSignature signatureWithObjCTypes: types];
1954
1836
[NSException raise: NSInvalidArgumentException
1955
1837
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
1957
msg = get_imp(GSObjCClass(self), aSelector);
1839
msg = get_imp(object_getClass(self), aSelector);
1960
1842
[NSException raise: NSGenericException
1961
1843
format: @"invalid selector passed to %s",
1962
GSNameFromSelector(_cmd)];
1965
1847
return (*msg)(self, aSelector);
1979
1861
[NSException raise: NSInvalidArgumentException
1980
1862
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
1982
msg = get_imp(GSObjCClass(self), aSelector);
1864
msg = get_imp(object_getClass(self), aSelector);
1985
1867
[NSException raise: NSGenericException
1986
1868
format: @"invalid selector passed to %s",
1987
GSNameFromSelector(_cmd)];
2007
1889
[NSException raise: NSInvalidArgumentException
2008
1890
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
2010
msg = get_imp(GSObjCClass(self), aSelector);
1892
msg = get_imp(object_getClass(self), aSelector);
2013
1895
[NSException raise: NSGenericException
2014
format: @"invalid selector passed to %s", GSNameFromSelector(_cmd)];
1896
format: @"invalid selector passed to %s", sel_getName(_cmd)];
2164
* Returns the version number of the receiving class. This will default to
2165
* a number assigned by the Objective C compiler if [NSObject -setVersion] has
2170
return class_get_version(self);
2051
+ (BOOL) resolveClassMethod: (SEL)name
2056
+ (BOOL) resolveInstanceMethod: (SEL)name
2174
2062
* Sets the version number of the receiving class. Should be nonnegative.
2176
+ (id) setVersion: (int)aVersion
2064
+ (id) setVersion: (NSInteger)aVersion
2178
2066
if (aVersion < 0)
2179
2067
[NSException raise: NSInvalidArgumentException
2322
2229
@implementation NSObject (GNUstep)
2324
/* GNU Object class compatibility */
2327
* Called to change the class used for autoreleasing objects.
2329
+ (void) setAutoreleaseClass: (Class)aClass
2331
autorelease_class = aClass;
2332
autorelease_imp = [self instanceMethodForSelector: autorelease_sel];
2336
* returns the class used to autorelease objects.
2338
+ (Class) autoreleaseClass
2340
return autorelease_class;
2344
2232
* Enables runtime checking of retain/release/autorelease operations.<br />
2345
2233
* <p>Whenever either -autorelease or -release is called, the contents of any
2408
2296
- (BOOL) isClass
2410
return GSObjCIsClass((Class)self);
2415
return GSObjCIsInstance(self);
2298
return class_isMetaClass(object_getClass(self));
2418
2301
- (BOOL) isMemberOfClassNamed: (const char*)aClassName
2420
2303
return ((aClassName!=NULL)
2421
&&!strcmp(GSNameFromClass(GSObjCClass(self)), aClassName));
2304
&&!strcmp(class_getName(object_getClass(self)), aClassName));
2424
2307
+ (struct objc_method_description *) descriptionForInstanceMethod: (SEL)aSel
2440
2323
return ((struct objc_method_description *)
2441
2324
GSGetMethod((GSObjCIsInstance(self)
2442
? GSObjCClass(self) : (Class)self),
2325
? object_getClass(self) : (Class)self),
2444
2327
GSObjCIsInstance(self),
2449
* Transmutes the receiver into an immutable version of the same object
2450
* and returns the result.<br />
2451
* If the receiver is not a mutable object or cannot be simply transmuted,
2452
* then this method either returns the receiver unchanged or,
2453
* if the force flag is set to YES, returns an autoreleased copy of the
2455
* Mutable classes should override this default implementation.<br />
2456
* This method is used in methods which are declared to return immutable
2457
* objects (eg. an NSArray), but which create and build mutable ones
2460
- (id) makeImmutableCopyOnFail: (BOOL)force
2464
return AUTORELEASE([self copy]);
2470
* Changes the class of the receiver (the 'isa' pointer) to be aClassObject,
2471
* but only if the receiver is an instance of a subclass of aClassObject
2472
* which has not added extra instance variables.<br />
2473
* Returns zero on failure, or the old class on success.
2475
- (Class) transmuteClassTo: (Class)aClassObject
2477
if (GSObjCIsInstance(self) == YES)
2478
if (class_is_class(aClassObject))
2479
if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
2480
if ([self isKindOfClass: aClassObject])
2482
Class old_isa = isa;
2489
+ (int) streamVersion: (TypedStream*)aStream
2331
+ (NSInteger) streamVersion: (TypedStream*)aStream
2491
2333
#ifndef NeXT_RUNTIME
2492
2334
if (aStream->mode == OBJC_READONLY)
2623
if (allocationLock != 0)
2625
objc_mutex_lock(allocationLock);
2469
[allocationLock lock];
2627
2470
c = NSMapGet(zombieMap, (void*)self);
2628
if (allocationLock != 0)
2630
objc_mutex_unlock(allocationLock);
2471
[allocationLock unlock];
2632
2472
return [c instanceMethodSignatureForSelector: aSelector];
2476
@implementation GSContentAccessingProxy
2479
[object endContentAccess];
2485
[object endContentAccess];
2488
- (id) forwardingTargetForSelector: (SEL)aSelector
2492
/* Support for legacy runtimes... */
2493
- (void) forwardInvocation: (NSInvocation*)anInvocation
2495
[anInvocation invokeWithTarget: object];
2498
- (id) initWithObject: (id)anObject
2500
ASSIGN(object, anObject);
2501
[object beginContentAccess];
2505
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
2507
return [object methodSignatureForSelector: aSelector];