mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
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:
parent
fd2132310b
commit
5921606e39
6 changed files with 486 additions and 476 deletions
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
|
|
793
Source/NSZone.m
793
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 <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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue