From 669d22f6d94a241fbb81eaaa73e721490df360d6 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 10 Apr 2009 08:25:03 +0000 Subject: [PATCH] gc improvements git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28192 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 + Source/GSPrivate.h | 6 +- Source/GSString.m | 135 ++++---- Source/NSObject.m | 7 +- Source/NSString.m | 12 +- Source/NSZone.m | 793 ++++++++++++++++++++++----------------------- 6 files changed, 486 insertions(+), 476 deletions(-) diff --git a/ChangeLog b/ChangeLog index 16b030d47..f258c430d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-04-10 Richard Frith-Macdonald + + * Source/GSPrivate.h: + * Source/NSString.m: + * Source/NSObject.m: + * Source/GSString.m: + * Source/NSZone.m: + GC tweaks ... Improve realloc when in gc world. + 2009-04-03 Adam Fedor * Source/NSObject.m: Revert previous patch (David to fix up later). diff --git a/Source/GSPrivate.h b/Source/GSPrivate.h index 11caecc64..3de3ebe3e 100644 --- a/Source/GSPrivate.h +++ b/Source/GSPrivate.h @@ -165,7 +165,7 @@ typedef union { unsigned int _count; struct { unsigned int wide: 1; // 16-bit characters in string? - unsigned int free: 1; // Set if the instance owns the + unsigned int owned: 1; // Set if the instance owns the // _contents buffer unsigned int unused: 2; unsigned int hash: 28; @@ -186,12 +186,12 @@ typedef union { unsigned int _count; struct { unsigned int wide: 1; - unsigned int free: 1; + unsigned int owned: 1; unsigned int unused: 2; unsigned int hash: 28; } _flags; - NSZone *_zone; unsigned int _capacity; + NSZone *_zone; } @end diff --git a/Source/GSString.m b/Source/GSString.m index 91aa5b12a..ffa9f734d 100644 --- a/Source/GSString.m +++ b/Source/GSString.m @@ -94,9 +94,6 @@ a single flag for the structure classes: free. This is set only if the _contents buffer is guaranteed to remain valid at least until the instance has been deallocated. -(It really should be named 'ownsContents' or something similar, but it's -'free' in GSMutableString, and the structures need to be interchangeable.) - Many optimizations, such as retaining instead of copying, and using pointers to another strings _contents buffer, are valid only if this flag is set. @@ -125,8 +122,8 @@ method which can be used to initialize that specific subclass. GS*BufferString, concrete subclasses that store the data in an external (wrt. the instance itself) buffer. The buffer may or may not be owned -by the instance; the 'free' flag indicates which. If it is set, -we need to free the buffer when we are deallocated. +by the instance; the 'owned' flag indicates which. If it is set, +we may need to free the buffer when we are deallocated. */ @interface GSCBufferString : GSCString { @@ -367,7 +364,7 @@ static void getCString_u(GSStr self, char *buffer, unsigned int maxLength, * Remove any BOM and perform byte swapping if required. */ static void -fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, +fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned, NSStringEncoding encoding) { unsigned char *b = *bytes; @@ -379,17 +376,16 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, // Got a byte order marker ... remove it. if (len == sizeof(unichar)) { - if (*shouldFree) + if (*owned) { NSZoneFree(NSZoneFromPointer(b), b); + *owned = NO; } *length = 0; - *shouldFree = NO; *bytes = 0; } else { - NSZone *z = NSZoneFromPointer(b); unsigned char *from = b; unsigned char *to; unichar u; @@ -398,7 +394,11 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, len -= sizeof(unichar); memcpy(&u, from, sizeof(unichar)); from += sizeof(unichar); - to = NSZoneMalloc(z, len); +#if GS_WITH_GC + to = NSAllocateCollectable(len, 0); +#else + to = NSZoneMalloc(NSDefaultMallocZone(), len); +#endif if (u == 0xFEFF) { // Native byte order @@ -414,13 +414,16 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, to[i+1] = from[i]; } } - if (*shouldFree == YES) + if (*owned == YES) { - NSZoneFree(z, b); + NSZoneFree(NSZoneFromPointer(b), b); + } + else + { + *owned = YES; } *length = len; *bytes = to; - *shouldFree = YES; } } else if (encoding == NSUTF8StringEncoding && len >= 3 @@ -428,32 +431,38 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, { if (len == 3) { - if (*shouldFree) + if (*owned) { NSZoneFree(NSZoneFromPointer(b), b); + *owned = NO; } *length = 0; - *shouldFree = NO; *bytes = 0; } else { - NSZone *z = NSZoneFromPointer(b); unsigned char *from = b; unsigned char *to; // Got a byte order marker ... remove it. len -= 3; from += 3; - to = NSZoneMalloc(z, len); +#if GS_WITH_GC + to = NSAllocateCollectable(len, 0); +#else + to = NSZoneMalloc(NSDefaultMallocZone(), len); +#endif memcpy(to, from, len); - if (*shouldFree == YES) + if (*owned == YES) { - NSZoneFree(z, b); + NSZoneFree(NSZoneFromPointer(b), b); + } + else + { + *owned = YES; } *length = len; *bytes = to; - *shouldFree = YES; } } } @@ -480,7 +489,11 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, */ if (original == bytes) { +#if GS_WITH_GC + chars = NSAllocateCollectable(length, 0); +#else chars = NSZoneMalloc(GSObjCZone(self), length); +#endif memcpy(chars, bytes, length); } else @@ -585,7 +598,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.c = chars.c; me->_count = length; me->_flags.wide = 0; - me->_flags.free = flag; + me->_flags.owned = flag; return (id)me; } @@ -633,7 +646,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1]; me->_count = length; me->_flags.wide = 0; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer while (length-- > 0) { me->_contents.c[length] = chars.u[length]; @@ -650,7 +663,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.u = chars.u; me->_count = length; me->_flags.wide = 1; - me->_flags.free = flag; + me->_flags.owned = flag; } return (id)me; } @@ -711,7 +724,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, len = [format length]; if (len >= 1024) { - fmt = objc_malloc((len+1)*sizeof(unichar)); + fmt = NSZoneMalloc(NSDefaultMallocZone(), (len+1)*sizeof(unichar)); } [format getCharacters: fmt]; fmt[len] = '\0'; @@ -726,11 +739,11 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, f._capacity = sizeof(buf); f._count = 0; f._flags.wide = 0; - f._flags.free = 0; + f._flags.owned = 0; GSPrivateFormat(&f, fmt, argList, locale); if (fmt != fbuf) { - objc_free(fmt); + NSZoneFree(NSDefaultMallocZone(), fmt); } /* @@ -748,7 +761,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_count = f._count; me->_flags.wide = 1; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer memcpy(me->_contents.u, f._contents.u, f._count*sizeof(unichar)); } else @@ -758,7 +771,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1]; me->_count = f._count; me->_flags.wide = 0; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer memcpy(me->_contents.c, f._contents.c, f._count); } @@ -766,7 +779,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, * If the string had to grow beyond the initial buffer size, we must * release any allocated memory. */ - if (f._flags.free == 1) + if (f._flags.owned == 1) { NSZoneFree(f._zone, f._contents.c); } @@ -805,7 +818,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1]; me->_count = length; me->_flags.wide = 0; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer memcpy(me->_contents.c, ((GSStr)string)->_contents.c, length); } else if (GSObjCIsKindOf(c, GSUnicodeStringClass) == YES @@ -820,7 +833,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_count = length; me->_flags.wide = 1; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer memcpy(me->_contents.u, ((GSStr)string)->_contents.u, length*sizeof(unichar)); } @@ -835,7 +848,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *shouldFree, me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_count = length; me->_flags.wide = 1; - me->_flags.free = 1; // Ignored on dealloc, but means we own buffer + me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer [string getCharacters: me->_contents.u]; } return (id)me; @@ -1607,7 +1620,7 @@ getCString_c(GSStr self, char *buffer, unsigned int maxLength, o._contents.c = self->_contents.c; GSStrWiden((GSStr)&o); getCString_u((GSStr)&o, buffer, maxLength, aRange, leftoverRange); - if (o._flags.free == 1) + if (o._flags.owned == 1) { NSZoneFree(o._zone, o._contents.u); } @@ -2229,7 +2242,7 @@ static void GSStrMakeSpace(GSStr s, unsigned size) { s->_capacity = want; } - if (s->_flags.free == 1) + if (s->_flags.owned == 1) { /* * If we own the character buffer, we can simply realloc. @@ -2287,7 +2300,7 @@ static void GSStrMakeSpace(GSStr s, unsigned size) memcpy(s->_contents.c, tmp, s->_count); } } - s->_flags.free = 1; + s->_flags.owned = 1; } } @@ -2341,13 +2354,13 @@ static void GSStrWiden(GSStr s) [NSException raise: NSInternalInconsistencyException format: @"widen of string failed"]; } - if (s->_flags.free == 1) + if (s->_flags.owned == 1) { NSZoneFree(s->_zone, s->_contents.c); } else { - s->_flags.free = 1; + s->_flags.owned = 1; } s->_contents.u = tmp; s->_flags.wide = 1; @@ -2603,7 +2616,7 @@ substring_c(GSStr self, NSRange aRange) o->_contents.c = self->_contents.c + aRange.location; o->_count = aRange.length; o->_flags.wide = 0; - o->_flags.free = 0; + o->_flags.owned = 0; ASSIGN(o->_parent, (id)self); return AUTORELEASE((id)o); } @@ -2622,7 +2635,7 @@ substring_u(GSStr self, NSRange aRange) o->_contents.u = self->_contents.u + aRange.location; o->_count = aRange.length; o->_flags.wide = 1; - o->_flags.free = 0; + o->_flags.owned = 0; ASSIGN(o->_parent, (id)self); return AUTORELEASE((id)o); } @@ -3078,7 +3091,7 @@ agree, create a new GSCInlineString otherwise. */ - (id) copyWithZone: (NSZone*)z { - if (!_flags.free || NSShouldRetainWithZone(self, z) == NO) + if (!_flags.owned || NSShouldRetainWithZone(self, z) == NO) { struct { @defs(GSCInlineString) @@ -3089,7 +3102,7 @@ agree, create a new GSCInlineString otherwise. o->_count = _count; memcpy(o->_contents.c, _contents.c, _count); o->_flags.wide = 0; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } else @@ -3105,7 +3118,7 @@ agree, create a new GSCInlineString otherwise. @implementation GSCBufferString - (void) dealloc { - if (_flags.free && _contents.c != 0) + if (_flags.owned && _contents.c != 0) { NSZoneFree(NSZoneFromPointer(_contents.c), _contents.c); _contents.c = 0; @@ -3143,7 +3156,7 @@ agree, create a new GSCInlineString otherwise. o->_count = _count; memcpy(o->_contents.c, _contents.c, _count); o->_flags.wide = 0; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } @@ -3415,7 +3428,7 @@ agree, create a new GSUnicodeInlineString otherwise. */ - (id) copyWithZone: (NSZone*)z { - if (!_flags.free || NSShouldRetainWithZone(self, z) == NO) + if (!_flags.owned || NSShouldRetainWithZone(self, z) == NO) { struct { @defs(GSUnicodeInlineString) @@ -3427,7 +3440,7 @@ agree, create a new GSUnicodeInlineString otherwise. o->_count = _count; memcpy(o->_contents.u, _contents.u, _count * sizeof(unichar)); o->_flags.wide = 1; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } else @@ -3443,7 +3456,7 @@ agree, create a new GSUnicodeInlineString otherwise. @implementation GSUnicodeBufferString - (void) dealloc { - if (_flags.free && _contents.u != 0) + if (_flags.owned && _contents.u != 0) { NSZoneFree(NSZoneFromPointer(_contents.u), _contents.u); _contents.u = 0; @@ -3482,7 +3495,7 @@ agree, create a new GSUnicodeInlineString otherwise. o->_count = _count; memcpy(o->_contents.u, _contents.u, _count * sizeof(unichar)); o->_flags.wide = 1; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } @@ -3529,7 +3542,7 @@ agree, create a new GSUnicodeInlineString otherwise. len = [format length]; if (len >= 1024) { - fmt = objc_malloc((len+1)*sizeof(unichar)); + fmt = NSZoneMalloc(NSDefaultMallocZone(), (len+1)*sizeof(unichar)); } [format getCharacters: fmt]; fmt[len] = '\0'; @@ -3550,7 +3563,7 @@ agree, create a new GSUnicodeInlineString otherwise. _flags.hash = 0; // Invalidate the hash for this string. if (fmt != buf) { - objc_free(fmt); + NSZoneFree(NSDefaultMallocZone(), fmt); } va_end(ap); } @@ -3612,7 +3625,7 @@ agree, create a new GSUnicodeInlineString otherwise. o->_count = _count; memcpy(o->_contents.u, _contents.u, _count * sizeof(unichar)); o->_flags.wide = 1; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } else @@ -3626,7 +3639,7 @@ agree, create a new GSUnicodeInlineString otherwise. o->_count = _count; memcpy(o->_contents.c, _contents.c, _count); o->_flags.wide = 0; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return (id)o; } } @@ -3666,7 +3679,7 @@ agree, create a new GSUnicodeInlineString otherwise. - (void) dealloc { -NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); +NSAssert(_flags.owned == 1 && _zone != 0, NSInternalInconsistencyException); if (_contents.c != 0) { NSZoneFree(self->_zone, self->_contents.c); @@ -3830,7 +3843,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); BOOL isLatin1 = NO; BOOL shouldFree = NO; - _flags.free = YES; + _flags.owned = YES; #if GS_WITH_GC _zone = GSAtomicMallocZone(); #else @@ -4007,7 +4020,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); #endif _contents.c = NSZoneMalloc(_zone, capacity + 1); _flags.wide = 0; - _flags.free = 1; + _flags.owned = 1; return self; } @@ -4048,7 +4061,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); len = [format length]; if (len >= 1024) { - fmt = objc_malloc((len+1)*sizeof(unichar)); + fmt = NSZoneMalloc(NSDefaultMallocZone(), (len+1)*sizeof(unichar)); } [format getCharacters: fmt]; fmt[len] = '\0'; @@ -4056,7 +4069,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); GSPrivateFormat((GSStr)self, fmt, argList, locale); if (fmt != fbuf) { - objc_free(fmt); + NSZoneFree(NSDefaultMallocZone(), fmt); } return self; } @@ -4108,7 +4121,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); - (id) makeImmutableCopyOnFail: (BOOL)force { -NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); +NSAssert(_flags.owned == 1 && _zone != 0, NSInternalInconsistencyException); #ifndef NDEBUG GSDebugAllocationRemove(isa, self); #endif @@ -4404,7 +4417,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); memcpy(o->_contents.u, _contents.u + aRange.location, aRange.length * sizeof(unichar)); o->_flags.wide = 1; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return AUTORELEASE((id)o); } else @@ -4419,7 +4432,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); o->_count = aRange.length; memcpy(o->_contents.c, _contents.c + aRange.location, aRange.length); o->_flags.wide = 0; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return AUTORELEASE((id)o); } } @@ -4445,7 +4458,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); memcpy(o->_contents.u, _contents.u + aRange.location, aRange.length * sizeof(unichar)); o->_flags.wide = 1; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return AUTORELEASE((id)o); } else @@ -4460,7 +4473,7 @@ NSAssert(_flags.free == 1 && _zone != 0, NSInternalInconsistencyException); o->_count = aRange.length; memcpy(o->_contents.c, _contents.c + aRange.location, aRange.length); o->_flags.wide = 0; - o->_flags.free = 1; // Ignored on dealloc, but means we own buffer + o->_flags.owned = 1; // Ignored on dealloc, but means we own buffer return AUTORELEASE((id)o); } } diff --git a/Source/NSObject.m b/Source/NSObject.m index 8e6cf56ab..56645cbcd 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -542,8 +542,7 @@ NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone) if (new != nil) { new->class_pointer = aClass; - if (get_imp(aClass, finalize_sel) != finalize_imp - && __objc_responds_to(new, finalize_sel)) + if (get_imp(aClass, finalize_sel) != finalize_imp) { #ifndef NDEBUG /* @@ -817,7 +816,7 @@ GSDescriptionForClassMethod(pcl self, SEL aSel) * in a deadlock in the garbage collecting library. */ static void -warn_proc(char *msg, GC_word arg) +GSGarbageCollectorLog(char *msg, GC_word arg) { char buf[strlen(msg)+1024]; sprintf(buf, msg, (unsigned long)arg); @@ -841,7 +840,7 @@ warn_proc(char *msg, GC_word arg) * This is not necessary on most platforms, but is good practice. */ GC_init(); - GC_set_warn_proc(warn_proc); + GC_set_warn_proc(GSGarbageCollectorLog); #endif #ifdef __MINGW32__ diff --git a/Source/NSString.m b/Source/NSString.m index 30c87dfa8..5984cdc46 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -1103,7 +1103,7 @@ handle_printf_atsign (FILE *stream, len = [format length]; if (len >= 1024) { - fmt = objc_malloc((len+1)*sizeof(unichar)); + fmt = NSZoneMalloc(NSDefaultMallocZone(), (len+1)*sizeof(unichar)); } [format getCharacters: fmt range: ((NSRange){0, len})]; fmt[len] = '\0'; @@ -1120,12 +1120,12 @@ handle_printf_atsign (FILE *stream, #if HAVE_WIDE_PRINTF_FUNCTION f._flags.wide = 0; #endif /* HAVE_WIDE_PRINTF_FUNCTION */ - f._flags.free = 0; + f._flags.owned = 0; GSPrivateFormat(&f, fmt, argList, locale); GSPrivateStrExternalize(&f); if (fmt != fbuf) { - objc_free(fmt); + NSZoneFree(NSDefaultMallocZone(), fmt); } /* @@ -1151,7 +1151,7 @@ handle_printf_atsign (FILE *stream, * If the string had to grow beyond the initial buffer size, we must * release any allocated memory. */ - if (f._flags.free == 1) + if (f._flags.owned == 1) { NSZoneFree(f._zone, f._contents.c); } @@ -2999,7 +2999,7 @@ handle_printf_atsign (FILE *stream, */ if (len >= 4096) { - u = objc_malloc(len * sizeof(unichar)); + u = NSZoneMalloc(NSDefaultMallocZone(), len * sizeof(unichar)); } [self getCharacters: u]; if (flag == NO) @@ -3021,7 +3021,7 @@ handle_printf_atsign (FILE *stream, } if (u != buf) { - objc_free(u); + NSZoneFree(NSDefaultMallocZone(), u); } } return d; diff --git a/Source/NSZone.m b/Source/NSZone.m index d71bda6e5..6933aec73 100644 --- a/Source/NSZone.m +++ b/Source/NSZone.m @@ -96,6 +96,364 @@ #include "Foundation/NSZone.h" #include "Foundation/NSLock.h" +/* Default zone functions for default zone. */ +static void* default_malloc (NSZone *zone, size_t size); +static void* default_realloc (NSZone *zone, void *ptr, size_t size); +static void default_free (NSZone *zone, void *ptr); +static void default_recycle (NSZone *zone); +static BOOL default_check (NSZone *zone); +static BOOL default_lookup (NSZone *zone, void *ptr); +static struct NSZoneStats default_stats (NSZone *zone); + +static void* +default_malloc (NSZone *zone, size_t size) +{ + void *mem; + + mem = objc_malloc(size); + if (mem == NULL) + [NSException raise: NSMallocException + format: @"Default zone has run out of memory"]; + return mem; +} + +static void* +default_realloc (NSZone *zone, void *ptr, size_t size) +{ + void *mem; + + if (size == 0) + { + objc_free(ptr); + return NULL; + } + if (ptr == 0) + { + mem = objc_malloc(size); + if (mem == NULL) + [NSException raise: NSMallocException + format: @"Default zone has run out of memory"]; + return mem; + } + mem = objc_realloc(ptr, size); + if (mem == NULL) + [NSException raise: NSMallocException + format: @"Default zone has run out of memory"]; + return mem; +} + +static void +default_free (NSZone *zone, void *ptr) +{ + objc_free(ptr); +} + +static void +default_recycle (NSZone *zone) +{ + /* Recycle the default zone? Thou hast got to be kiddin'. */ + [NSException raise: NSGenericException + format: @"Trying to recycle default zone"]; +} + +static BOOL +default_check (NSZone *zone) +{ + /* We can't check memory managed by objc_malloc(). */ + [NSException raise: NSGenericException + format: @"No checking for default zone"]; + return NO; +} + +static BOOL +default_lookup (NSZone *zone, void *ptr) +{ + /* Assume all memory is in default zone. */ + return YES; +} + +static struct NSZoneStats +default_stats (NSZone *zone) +{ + struct NSZoneStats dummy = {0,0,0,0,0}; + + /* We can't obtain statistics from the memory managed by objc_malloc(). */ + [NSException raise: NSGenericException + format: @"No statistics for default zone"]; + return dummy; +} + +static NSZone default_zone = +{ + default_malloc, default_realloc, default_free, default_recycle, + default_check, default_lookup, default_stats, 0, @"default", 0 +}; + +/* + * For backward compatibility. + */ +NSZone *__nszone_private_hidden_default_zone = &default_zone; + + + +/** + * Sets name of the given zone (useful for debugging and logging). + */ +void +NSSetZoneName (NSZone *zone, NSString *name) +{ + if (!zone) + zone = NSDefaultMallocZone(); + [gnustep_global_lock lock]; + name = [name copy]; + if (zone->name != nil) + [zone->name release]; + zone->name = name; + [gnustep_global_lock unlock]; +} + +NSString* +NSZoneName (NSZone *zone) +{ + if (!zone) + zone = NSDefaultMallocZone(); + return zone->name; +} + +#if GS_WITH_GC + +#if defined(DEBUG) +#define GC_DEBUG 1 +#endif /* DEBUG */ + +#include + +/* + * Dummy zones used with garbage collection. + * The 'atomic' zone is for memory that will be assumed not to contain + * pointers for garbage collection purposes. + */ +static NSZone atomic_zone = +{ + 0, 0, 0, 0, 0, 0, 0, 0, @"default", 0 +}; + +void * +NSAllocateCollectable(NSUInteger size, NSUInteger options) +{ + void *ptr; + + if (options & NSScannedOption) + { + if (options & NSCollectorDisabledOption) + { + ptr = (void*)GC_MALLOC_UNCOLLECTABLE(size); + memset(ptr, '\0', size); + } + else + { + ptr = (void*)GC_MALLOC_IGNORE_OFF_PAGE(size); + memset(ptr, '\0', size); + } + } + else + { + if (options & NSCollectorDisabledOption) + { + ptr = (void*)calloc(1, size); + } + else + { + ptr = (void*)GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(size); + memset(ptr, '\0', size); + } + } + return ptr; +} + +void * +NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options) +{ + if (ptr == 0) + { + ptr = NSAllocateCollectable(size, options); + } + else if (size > 0 && GC_base(ptr) == 0) + { + /* This is not collectable memory, so we don't know how big it is. + * that means we must use realloc first, to get a known size, and + * then, if needed, allocate a chunk the right size and copy to it. + */ + ptr = realloc(ptr, size); + if (ptr != 0) + { + if ((options & NSScannedOption) + || !(options & NSCollectorDisabledOption)) + { + void *tmp = NSAllocateCollectable(size, options); + + memcpy(tmp, ptr, size); + free(ptr); + ptr = tmp; + } + } + } + else + { + void *tmp = NSAllocateCollectable(size, options); + unsigned length = GC_size(ptr); + + if (length > size) + { + length = size; + } + if (tmp != 0 && length > 0) + { + memcpy(tmp, ptr, length); + } + GC_FREE(ptr); + ptr = tmp; + } + return ptr; +} + +NSZone* +NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree) +{ + NSLog(@" *** Creating a zone while running GC is ignored."); + return &default_zone; +} + +NSZone* +NSDefaultMallocZone (void) +{ + return &default_zone; +} + +NSZone* +GSAtomicMallocZone (void) +{ + return &atomic_zone; +} + +NSZone* +NSZoneFromPointer (void *ptr) +{ + return &default_zone; +} + +void +NSRecycleZone (NSZone *zone) +{ +} + +BOOL +NSZoneCheck (NSZone *zone) +{ + return YES; +} + +struct +NSZoneStats NSZoneStats (NSZone *zone) +{ + struct NSZoneStats stats = { 0 }; + return stats; +} + +void +GSMakeWeakPointer(Class class, const char *iVarName) +{ + class_ivar_set_gcinvisible(class, iVarName, YES); +} + +BOOL +GSAssignZeroingWeakPointer(void **destination, void *source) +{ + if (destination == 0) + { + return NO; // Bad destination pointer + } + if (*destination == source) + { + return YES; // Already assigned. + } + if (source != 0 && GC_base(source) == 0) + { + return NO; // Source is not garbage collectable. + } + if (*destination != 0) + { + GC_unregister_disappearing_link(destination); + } + *destination = source; + if (source != 0) + { + GC_general_register_disappearing_link(destination, source); + } + return YES; +} + +void* +NSZoneMalloc (NSZone *zone, NSUInteger size) +{ + return NSZoneCalloc(zone, 1, size); +} + +void* +NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes) +{ + size_t size = elems * bytes; + void *ptr; + + if (zone == &atomic_zone) + { + ptr = (void*)GC_MALLOC_ATOMIC(size); + memset(ptr, '\0', size); + } + else + { + ptr = (void*)malloc(size); + if (ptr == 0) + { + ptr = GSOutOfMemory(size, NO); + } + if (ptr != 0) + { + memset(ptr, '\0', size); + } + } + return ptr; +} + +void* +NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size) +{ + if (GC_base(ptr) != 0) + { + ptr = GC_REALLOC(ptr, size); + } + else + { + ptr = realloc(ptr, size); + } + return ptr; +} + +void +NSZoneFree (NSZone *zone, void *ptr) +{ + if (GC_base(ptr) != 0) + { + GC_FREE(ptr); + } + else + { + free(ptr); + } +} + +#else /* GS_WITH_GC */ + /** * Try to get more memory - the normal process has failed. * If we can't do anything, just return a null pointer. @@ -109,7 +467,6 @@ GSOutOfMemory(NSUInteger size, BOOL retry) return 0; } -#if GS_WITH_GC == 0 /* Alignment */ #ifdef ALIGN @@ -355,17 +712,6 @@ struct _nfree_zone_struct size_t use; }; - - -/* Default zone functions for default zone. */ -static void* default_malloc (NSZone *zone, size_t size); -static void* default_realloc (NSZone *zone, void *ptr, size_t size); -static void default_free (NSZone *zone, void *ptr); -static void default_recycle (NSZone *zone); -static BOOL default_check (NSZone *zone); -static BOOL default_lookup (NSZone *zone, void *ptr); -static struct NSZoneStats default_stats (NSZone *zone); - /* Memory management functions for freeable zones. */ static void* fmalloc (NSZone *zone, size_t size); static void* frealloc (NSZone *zone, void *ptr, size_t size); @@ -399,49 +745,6 @@ static void rffree (NSZone *zone, void *ptr); static void rnfree (NSZone *zone, void *ptr); -static NSZone default_zone = -{ - default_malloc, default_realloc, default_free, default_recycle, - default_check, default_lookup, default_stats, DEFBLOCK, @"default", 0 -}; - -/* - * For backward compatibility. - */ -NSZone *__nszone_private_hidden_default_zone = &default_zone; - -/* - * Lists of zones to be used to determine if a pointer is in a zone. - */ -static NSZone *zone_list = 0; - -/** - * Searches and finds the zone ptr was allocated from. The speed depends - * upon the number of zones and their size. - */ -GS_DECLARE NSZone* -NSZoneFromPointer(void *ptr) -{ - NSZone *zone; - - if (ptr == 0) return 0; - if (zone_list == 0) return &default_zone; - - /* - * See if we can find the zone in our list of all zones. - */ - [gnustep_global_lock lock]; - for (zone = zone_list; zone != 0; zone = zone->next) - { - if ((zone->lookup)(zone, ptr) == YES) - { - break; - } - } - [gnustep_global_lock unlock]; - return (zone == 0) ? &default_zone : zone; -} - static inline void destroy_zone(NSZone* zone) { @@ -459,84 +762,6 @@ destroy_zone(NSZone* zone) objc_free((void*)zone); } -static void* -default_malloc (NSZone *zone, size_t size) -{ - void *mem; - - mem = objc_malloc(size); - if (mem == NULL) - [NSException raise: NSMallocException - format: @"Default zone has run out of memory"]; - return mem; -} - -static void* -default_realloc (NSZone *zone, void *ptr, size_t size) -{ - void *mem; - - if (size == 0) - { - objc_free(ptr); - return NULL; - } - if (ptr == 0) - { - mem = objc_malloc(size); - if (mem == NULL) - [NSException raise: NSMallocException - format: @"Default zone has run out of memory"]; - return mem; - } - mem = objc_realloc(ptr, size); - if (mem == NULL) - [NSException raise: NSMallocException - format: @"Default zone has run out of memory"]; - return mem; -} - -static void -default_free (NSZone *zone, void *ptr) -{ - objc_free(ptr); -} - -static void -default_recycle (NSZone *zone) -{ - /* Recycle the default zone? Thou hast got to be kiddin'. */ - [NSException raise: NSGenericException - format: @"Trying to recycle default zone"]; -} - -static BOOL -default_check (NSZone *zone) -{ - /* We can't check memory managed by objc_malloc(). */ - [NSException raise: NSGenericException - format: @"No checking for default zone"]; - return NO; -} - -static BOOL -default_lookup (NSZone *zone, void *ptr) -{ - /* Assume all memory is in default zone. */ - return YES; -} - -static struct NSZoneStats -default_stats (NSZone *zone) -{ - struct NSZoneStats dummy = {0,0,0,0,0}; - - /* We can't obtain statistics from the memory managed by objc_malloc(). */ - [NSException raise: NSGenericException - format: @"No statistics for default zone"]; - return dummy; -} - /* Search the buffer to see if there is any memory chunks large enough to satisfy request using first fit. If the memory chunk found has a size exactly equal to the one requested, remove it from the buffer @@ -1589,6 +1814,38 @@ rrealloc (NSZone *zone, void *ptr, size_t size) static void rnfree (NSZone *zone, void *ptr); +/* + * Lists of zones to be used to determine if a pointer is in a zone. + */ +static NSZone *zone_list = 0; + +/** + * Searches and finds the zone ptr was allocated from. The speed depends + * upon the number of zones and their size. + */ +GS_DECLARE NSZone* +NSZoneFromPointer(void *ptr) +{ + NSZone *zone; + + if (ptr == 0) return 0; + if (zone_list == 0) return &default_zone; + + /* + * See if we can find the zone in our list of all zones. + */ + [gnustep_global_lock lock]; + for (zone = zone_list; zone != 0; zone = zone->next) + { + if ((zone->lookup)(zone, ptr) == YES) + { + break; + } + } + [gnustep_global_lock unlock]; + return (zone == 0) ? &default_zone : zone; +} + /** * Creates a new zone of start bytes, which will grow and shrink by * granularity bytes. If canFree is 0, memory in zone is allocated but @@ -1724,22 +1981,6 @@ NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes) return memset(NSZoneMalloc(zone, elems*bytes), 0, elems*bytes); } -/** - * Sets name of the given zone (useful for debugging and logging). - */ -void -NSSetZoneName (NSZone *zone, NSString *name) -{ - if (!zone) - zone = NSDefaultMallocZone(); - [gnustep_global_lock lock]; - name = [name copy]; - if (zone->name != nil) - [zone->name release]; - zone->name = name; - [gnustep_global_lock unlock]; -} - void * NSAllocateCollectable(NSUInteger size, NSUInteger options) { @@ -1749,252 +1990,8 @@ NSAllocateCollectable(NSUInteger size, NSUInteger options) void * NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options) { - return NSZoneRealloc(NSDefaultMallocZone(), ptr, size); + return NSZoneRealloc(0, ptr, size); } -#else - -#if defined(DEBUG) -#define GC_DEBUG 1 -#endif - -#include - -/* - * Dummy zones used with garbage collection. - * The 'atomic' zone is for memory that will be assumed not to contain - * pointers for garbage collection purposes. - */ -static NSZone default_zone = -{ - 0, 0, 0, 0, 0, 0, 0, 0, @"default", 0 -}; - -static NSZone atomic_zone = -{ - 0, 0, 0, 0, 0, 0, 0, 0, @"default", 0 -}; - -void * -NSAllocateCollectable(NSUInteger size, NSUInteger options) -{ - void *ptr; - - if (options & NSScannedOption) - { - if (options & NSCollectorDisabledOption) - { - ptr = (void*)GC_MALLOC_UNCOLLECTABLE(size); - memset(ptr, '\0', size); - } - else - { - ptr = (void*)GC_MALLOC_IGNORE_OFF_PAGE(size); - memset(ptr, '\0', size); - } - } - else - { - if (options & NSCollectorDisabledOption) - { - ptr = (void*)calloc(1, size); - } - else - { - ptr = (void*)GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(size); - memset(ptr, '\0', size); - } - } - return ptr; -} - -void * -NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options) -{ - if (ptr == 0) - { - ptr = NSAllocateCollectable(size, options); - } - else - { - void *tmp = NSAllocateCollectable(size, options); - unsigned length = GC_size(ptr); - - if (length > size) - { - length = size; - } - if (tmp != 0 && length > 0) - { - memcpy(tmp, ptr, length); - } - GC_free(ptr); - ptr = tmp; - } - return ptr; -} - -#endif /* GS_WITH_GC */ - - -#ifdef IN_NSZONE_M -#define GS_ZONE_SCOPE extern -#define GS_ZONE_ATTR -#else -#define GS_ZONE_SCOPE static inline -#define GS_ZONE_ATTR __attribute__((unused)) -#endif - -#if GS_WITH_GC - -NSZone* -NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree) -{ - return &default_zone; -} - -NSZone* -NSDefaultMallocZone (void) -{ - return &default_zone; -} - -NSZone* -GSAtomicMallocZone (void) -{ - return &atomic_zone; -} - -NSZone* -NSZoneFromPointer (void *ptr) -{ - return &default_zone; -} - -void -NSRecycleZone (NSZone *zone) -{ -} - -void -NSSetZoneName (NSZone *zone, NSString *name) -{ -} - -NSString* -NSZoneName (NSZone *zone) -{ - return nil; -} - -BOOL -NSZoneCheck (NSZone *zone) -{ - return YES; -} - -struct -NSZoneStats NSZoneStats (NSZone *zone) -{ - struct NSZoneStats stats = { 0 }; - return stats; -} - -void -GSMakeWeakPointer(Class class, const char *iVarName) -{ - class_ivar_set_gcinvisible(class, iVarName, YES); -} - - -#include - -BOOL -GSAssignZeroingWeakPointer(void **destination, void *source) -{ - if (destination == 0) - { - return NO; // Bad destination pointer - } - if (*destination == source) - { - return YES; // Already assigned. - } - if (source != 0 && GC_base(source) == 0) - { - return NO; // Source is not garbage collectable. - } - if (*destination != 0) - { - GC_unregister_disappearing_link(destination); - } - *destination = source; - if (source != 0) - { - GC_general_register_disappearing_link(destination, source); - } - return YES; -} - -void* -NSZoneMalloc (NSZone *zone, NSUInteger size) -{ - return NSZoneCalloc(zone, 1, size); -} - -void* -NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes) -{ - size_t size = elems * bytes; - void *ptr; - - if (zone == &atomic_zone) - { - ptr = (void*)GC_MALLOC_ATOMIC(size); - memset(ptr, '\0', size); - } - else - { - ptr = (void*)malloc(size); - if (ptr == 0) - { - ptr = GSOutOfMemory(size, NO); - } - if (ptr != 0) - { - memset(ptr, '\0', size); - } - } - return ptr; -} - -void* -NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size) -{ - if (GC_base(ptr) != 0) - { - ptr = GC_REALLOC(ptr, size); - } - else - { - ptr = realloc(ptr, size); - } - return ptr; -} - -void -NSZoneFree (NSZone *zone, void *ptr) -{ - if (GC_base(ptr) != 0) - { - GC_FREE(ptr); - } - else - { - free(ptr); - } -} - -#else /* GS_WITH_GC */ NSZone* NSDefaultMallocZone (void) @@ -2057,14 +2054,6 @@ NSZoneFree (NSZone *zone, void *ptr) (zone->free)(zone, ptr); } -NSString* -NSZoneName (NSZone *zone) -{ - if (!zone) - zone = NSDefaultMallocZone(); - return zone->name; -} - BOOL NSZoneCheck (NSZone *zone) {