gc improvements

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28192 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-04-10 08:25:03 +00:00
parent fd2132310b
commit 5921606e39
6 changed files with 486 additions and 476 deletions

View file

@ -1,3 +1,12 @@
2009-04-10 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <fedor@gnu.org>
* Source/NSObject.m: Revert previous patch (David to fix up later).

View file

@ -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

View file

@ -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);
}
}

View file

@ -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__

View file

@ -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;

View file

@ -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 <gc.h>
/*
* 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 <gc.h>
/*
* 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 <gc.h>
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)
{