GC changes for MacOS-X compatiblity

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27630 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-01-19 11:00:33 +00:00
parent ff7212cf67
commit 6bccff5fc7
20 changed files with 537 additions and 294 deletions

View file

@ -1,3 +1,38 @@
2009-01-19 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSZone.h:
* Source/NSZone.m:
Add NSAllocateCollectable() and NSReallocateCollectable() functions.
Move inline stuff from header to source fle so that GC differences
are hidden. Change behavior under GC so that the default malloc
zone is non-collectable (as under MacOS-X).
* Headers/Additions/GNUstepBase/GSIMap.h:
Use scanned collectable memory for map.
* Source/Additions/GSObjCRuntime.m:
Use NSAllocateCollectable() for fast buffer.
* Source/GSArray.m:
* Source/GSCountedSet.m:
* Source/GSDictionary.m:
* Source/GSSet.m:
* Source/NSArchiver.m:
* Source/NSConnection.m:
* Source/NSHashTable.m:
* Source/NSKeyedArchiver.m:
* Source/NSMapTable.m:
* Source/NSNotificationCenter.m:
* Source/NSObject.m:
* Source/NSPortCoder.m:
* Source/NSSerializer.m:
* Source/NSPropertyList.m:
Use scanned collectable memory in places where we allocate memory to
hold pointers. This change is needed because of the switch to have
the default zone use unscanned uncollectable memory as in MacOS-X.
These changes probably just scratch the surface ... we need to review
all memory allocation as, anywhere we allocate memory now will need
to be done differently under GC. This does mean that all existing
code needs more work to port to GC than it otherwise would. On the
other hand, a switch to GC is really quite a major design change.
2009-01-17 Wolfgang Lux <wolfgang.lux@gmail.com>
* Source/unix/GSRunLoopCtxt.m (+awakenedBefore): Fix typo.

View file

@ -421,11 +421,11 @@ GSIMapMoreNodes(GSIMapTable map, unsigned required)
/*
* Our nodes may be allocated from the atomic zone - but we don't want
* them freed - so we must keep the array of pointers to memory chunks in
* the default zone
* scanned memory.
*/
if (map->zone == GSAtomicMallocZone())
{
newArray = (GSIMapNode*)NSZoneMalloc(NSDefaultMallocZone(), arraySize);
newArray = (GSIMapNode*)NSAllocateCollectable(arraySize, NSScannedOption);
}
else
#endif
@ -438,7 +438,8 @@ GSIMapMoreNodes(GSIMapTable map, unsigned required)
if (map->nodeChunks != 0)
{
memcpy(newArray, map->nodeChunks, (map->chunkCount)*sizeof(GSIMapNode));
memcpy(newArray, map->nodeChunks,
(map->chunkCount)*sizeof(GSIMapNode));
NSZoneFree(map->zone, map->nodeChunks);
}
map->nodeChunks = newArray;

View file

@ -136,40 +136,31 @@ struct _NSZone
* If we can't do anything, just return a null pointer.
* Try to do some logging if possible.
*/
void *GSOutOfMemory(size_t size, BOOL retry);
void*
GSOutOfMemory(size_t size, BOOL retry);
#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
NSZone*
NSCreateZone (size_t start, size_t gran, BOOL canFree);
/* Default zone. Name is hopelessly long so that no one will ever
want to use it. ;) Private variable. */
GS_EXPORT NSZone* __nszone_private_hidden_default_zone;
NSZone*
NSDefaultMallocZone (void);
#ifndef GS_WITH_GC
#define GS_WITH_GC 0
#endif
#if GS_WITH_GC
/**
* Returns the default zone used for memory allocation, created at startup.
* This zone cannot be recycled.
*/
NSZone*
GSAtomicMallocZone (void);
#include <gc.h>
/**
* Returns the default zone used for scanned memory allocation ... a
* garbage collectable chunk of memory which is scanned for pointers.
*/
NSZone*
GSScannedMallocZone (void);
GS_EXPORT NSZone* __nszone_private_hidden_atomic_zone;
GS_ZONE_SCOPE NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree)
{ return __nszone_private_hidden_default_zone; }
GS_ZONE_SCOPE NSZone* NSDefaultMallocZone (void)
{ return __nszone_private_hidden_default_zone; }
GS_ZONE_SCOPE NSZone* GSAtomicMallocZone (void)
{ return __nszone_private_hidden_atomic_zone; }
GS_ZONE_SCOPE NSZone* NSZoneFromPointer (void *ptr)
{ return __nszone_private_hidden_default_zone; }
NSZone*
NSZoneFromPointer (void *ptr);
/**
* Allocates and returns memory for elems items of size bytes, in the
@ -178,19 +169,8 @@ GS_ZONE_SCOPE NSZone* NSZoneFromPointer (void *ptr)
* allocate and no more can be obtained from system, unless using the
* default zone, in which case NULL is returned.
*/
GS_ZONE_SCOPE void* NSZoneMalloc (NSZone *zone, size_t size)
{
void *ptr;
if (zone == GSAtomicMallocZone())
ptr = (void*)GC_MALLOC_ATOMIC(size);
else
ptr = (void*)GC_MALLOC(size);
if (ptr == 0)
ptr = GSOutOfMemory(size, YES);
return ptr;
}
void*
NSZoneMalloc (NSZone *zone, size_t size);
/**
* Allocates and returns cleared memory for elems items of size bytes, in the
@ -199,134 +179,8 @@ GS_ZONE_SCOPE void* NSZoneMalloc (NSZone *zone, size_t size)
* allocate and no more can be obtained from system, unless using the
* default zone, in which case NULL is returned.
*/
GS_ZONE_SCOPE void* NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
{
size_t size = elems * bytes;
void *ptr;
if (zone == __nszone_private_hidden_atomic_zone)
ptr = (void*)GC_MALLOC_ATOMIC(size);
else
ptr = (void*)GC_MALLOC(size);
if (ptr == 0)
ptr = GSOutOfMemory(size, NO);
memset(ptr, '\0', size);
return ptr;
}
GS_ZONE_SCOPE void* NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
{
ptr = GC_REALLOC(ptr, size);
if (ptr == 0)
GSOutOfMemory(size, NO);
return ptr;
}
GS_ZONE_SCOPE void NSRecycleZone (NSZone *zone)
{
}
GS_ZONE_SCOPE void NSZoneFree (NSZone *zone, void *ptr)
{
GC_FREE(ptr);
}
/**
* Sets name of the given zone (useful for debugging and logging).
*/
GS_ZONE_SCOPE void NSSetZoneName (NSZone *zone, NSString *name)
{
}
/**
* Sets name of the given zone (useful for debugging and logging).
*/
GS_ZONE_SCOPE NSString* NSZoneName (NSZone *zone)
{
return nil;
}
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
/**
* Allocates mmemory of size bytes from zone, with the assumption that the
* memory will never contain pointers. This is only relevant in situations
* where a form of garbage collection is enabled, and NSZoneMalloc() should
* always be used otherwise. Not defined by OpenStep or OS X.
*/
GS_ZONE_SCOPE void* NSZoneMallocAtomic (NSZone *zone, size_t size)
{
return NSZoneMalloc(GSAtomicMallocZone(), size);
}
GS_ZONE_SCOPE BOOL NSZoneCheck (NSZone *zone)
{
return YES;
}
GS_ZONE_SCOPE struct NSZoneStats NSZoneStats (NSZone *zone)
{
struct NSZoneStats stats = { 0 };
return stats;
}
#endif
#else /* GS_WITH_GC */
GS_EXPORT NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree);
GS_ZONE_SCOPE NSZone* NSDefaultMallocZone (void) GS_ZONE_ATTR;
/**
* Returns the default zone used for memory allocation, created at startup.
* This zone cannot be recycled.
*/
GS_ZONE_SCOPE NSZone* NSDefaultMallocZone (void)
{
return __nszone_private_hidden_default_zone;
}
GS_ZONE_SCOPE NSZone* GSAtomicMallocZone (void) GS_ZONE_ATTR;
/**
* Returns the default zone used for atomic memory allocation (see
* NSMallocAtomic()), if no zone is specified.
*/
GS_ZONE_SCOPE NSZone* GSAtomicMallocZone (void)
{
return NSDefaultMallocZone();
}
GS_EXPORT NSZone* NSZoneFromPointer (void *ptr);
GS_ZONE_SCOPE void* NSZoneMalloc (NSZone *zone, size_t size) GS_ZONE_ATTR;
/**
* Allocates and returns cleared memory for elems items of size bytes, in the
* given zone. Returns NULL if allocation of size 0 requested. Raises
* <code>NSMallocException</code> if not enough free memory in zone to
* allocate and no more can be obtained from system, unless using the
* default zone, in which case NULL is returned.
*/
GS_ZONE_SCOPE void* NSZoneMalloc (NSZone *zone, size_t size)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->malloc)(zone, size);
}
/**
* Allocates and returns cleared memory for elems items of size bytes, in the
* given zone. Returns NULL if allocation of size 0 requested. Raises
* <code>NSMallocException</code> if not enough free memory in zone to
* allocate and no more can be obtained from system, unless using the
* default zone, in which case NULL is returned.
*/
GS_EXPORT void* NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes);
GS_ZONE_SCOPE void*
NSZoneRealloc (NSZone *zone, void *ptr, size_t size) GS_ZONE_ATTR;
void*
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes);
/**
* Reallocates the chunk of memory in zone pointed to by ptr to a new one of
@ -335,14 +189,8 @@ NSZoneRealloc (NSZone *zone, void *ptr, size_t size) GS_ZONE_ATTR;
* zone and no more memory can be obtained from the system, unless using the
* default zone, in which case NULL is returned.
*/
GS_ZONE_SCOPE void* NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->realloc)(zone, ptr, size);
}
GS_ZONE_SCOPE void NSRecycleZone (NSZone *zone) GS_ZONE_ATTR;
void*
NSZoneRealloc (NSZone *zone, void *ptr, size_t size);
/**
* Return memory for an entire zone to system. In fact, this will not be done
@ -351,14 +199,8 @@ GS_ZONE_SCOPE void NSRecycleZone (NSZone *zone) GS_ZONE_ATTR;
* must simply equal the number of allocation calls. The default zone, on the
* other hand, cannot be recycled.
*/
GS_ZONE_SCOPE void NSRecycleZone (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
(zone->recycle)(zone);
}
GS_ZONE_SCOPE void NSZoneFree (NSZone *zone, void *ptr) GS_ZONE_ATTR;
void
NSRecycleZone (NSZone *zone);
/**
* Frees memory pointed to by ptr (which should have been allocated by a
@ -366,91 +208,89 @@ GS_ZONE_SCOPE void NSZoneFree (NSZone *zone, void *ptr) GS_ZONE_ATTR;
* returns it to zone. Note, if this is a nonfreeable zone, the memory is
* not actually freed, but the count of number of free()s is updated.
*/
GS_ZONE_SCOPE void NSZoneFree (NSZone *zone, void *ptr)
{
if (!zone)
zone = NSDefaultMallocZone();
(zone->free)(zone, ptr);
}
GS_EXPORT void NSSetZoneName (NSZone *zone, NSString *name);
GS_ZONE_SCOPE NSString* NSZoneName (NSZone *zone) GS_ZONE_ATTR;
void
NSZoneFree (NSZone *zone, void *ptr);
/**
* Returns the name assigned to the zone, if one has been given (see
* NSSetZoneName()), otherwise nil. Useful for debugging/logging.
* Sets name of the given zone (useful for debugging and logging).
*/
GS_ZONE_SCOPE NSString* NSZoneName (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return zone->name;
}
void
NSSetZoneName (NSZone *zone, NSString *name);
/**
* Sets name of the given zone (useful for debugging and logging).
*/
NSString*
NSZoneName (NSZone *zone);
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
GS_ZONE_SCOPE void*
NSZoneMallocAtomic (NSZone *zone, size_t size) GS_ZONE_ATTR;
/**
* Allocates memory of size bytes from zone, with the assumption that the
* memory will never contain pointers. This is only relevant in situations
* where a form of garbage collection is enabled, and NSZoneMalloc() should
* always be used otherwise. Not defined by OpenStep or OS X.
*/
GS_ZONE_SCOPE void* NSZoneMallocAtomic (NSZone *zone, size_t size)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->malloc)(zone, size);
}
GS_ZONE_SCOPE BOOL NSZoneCheck (NSZone *zone) GS_ZONE_ATTR;
/**
* Checks integrity of a zone. Not defined by OpenStep or OS X.
*/
GS_ZONE_SCOPE BOOL NSZoneCheck (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->check)(zone);
}
GS_ZONE_SCOPE struct NSZoneStats NSZoneStats (NSZone *zone) GS_ZONE_ATTR;
BOOL
NSZoneCheck (NSZone *zone);
/**
* Obtain statistics about the zone. Implementation emphasis is on
* correctness, not speed. Not defined by OpenStep or OS X.
*/
GS_ZONE_SCOPE struct NSZoneStats NSZoneStats (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->stats)(zone);
}
#endif /* GS_API_NONE */
struct NSZoneStats
NSZoneStats (NSZone *zone);
#endif /* GS_WITH_GC */
#endif
GS_EXPORT NSUInteger
NSPageSize (void) __attribute__ ((const));
GS_EXPORT NSUInteger NSPageSize (void) __attribute__ ((const));
GS_EXPORT NSUInteger
NSLogPageSize (void) __attribute__ ((const));
GS_EXPORT NSUInteger NSLogPageSize (void) __attribute__ ((const));
GS_EXPORT NSUInteger
NSRoundDownToMultipleOfPageSize (NSUInteger bytes) __attribute__ ((const));
GS_EXPORT NSUInteger NSRoundDownToMultipleOfPageSize (NSUInteger bytes)
__attribute__ ((const));
GS_EXPORT NSUInteger
NSRoundUpToMultipleOfPageSize (NSUInteger bytes) __attribute__ ((const));
GS_EXPORT NSUInteger NSRoundUpToMultipleOfPageSize (NSUInteger bytes)
__attribute__ ((const));
GS_EXPORT NSUInteger
NSRealMemoryAvailable (void);
GS_EXPORT NSUInteger NSRealMemoryAvailable (void);
GS_EXPORT void*
NSAllocateMemoryPages (NSUInteger bytes);
GS_EXPORT void* NSAllocateMemoryPages (NSUInteger bytes);
GS_EXPORT void
NSDeallocateMemoryPages (void *ptr, NSUInteger bytes);
GS_EXPORT void NSDeallocateMemoryPages (void *ptr, NSUInteger bytes);
GS_EXPORT void
NSCopyMemoryPages (const void *src, void *dest, NSUInteger bytes);
GS_EXPORT void NSCopyMemoryPages (const void *src, void *dest, NSUInteger bytes);
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, OS_API_LATEST)
enum {
NSScannedOption = (1<<0),
NSCollectorDisabledOption = (1<<1),
};
/** Allocate memory. If garbage collection is not enabled this uses the
* default malloc zone and the options are ignored.<br />
* If garbage collection is enabled, the allocate memory is normally not
* scanned for pointers but is isttself garbage collectable. The options
* argument is a bitmask in which NSScannedOption sets the memory to be
* scanned for pointers by the garbage collector, and
* NSCollectorDisabledOption causes the memory to be excempt from being
* garbage collected itsself.
*/
GS_EXPORT void *
NSAllocateCollectable(NSUInteger size, NSUInteger options);
/** Reallocate memory to be of a different size and/or to have different
* options settings. The behavior of options is as for
* the NSAllocateCollectable() function.
*/
GS_EXPORT void *
NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options);
#endif
#if defined(__cplusplus)
}

View file

@ -2342,7 +2342,7 @@ void *
GSAutoreleasedBuffer(unsigned size)
{
#if GS_WITH_GC
return GC_malloc(size);
return NSAllocateCollectable(size, NSScannedOption);
#else
#ifdef ALIGN
#undef ALIGN

View file

@ -147,7 +147,12 @@ static Class GSInlineArrayClass;
{
unsigned i;
#if GS_WITH_GC
_contents_array = NSAllocateCollectable(sizeof(id)*count,
NSScannedOption);
#else
_contents_array = NSZoneMalloc([self zone], sizeof(id)*count);
#endif
if (_contents_array == 0)
{
RELEASE(self);
@ -204,7 +209,12 @@ static Class GSInlineArrayClass;
at: &_count];
if (_count > 0)
{
#if GS_WITH_GC
_contents_array = NSAllocateCollectable(sizeof(id) * _count,
NSScannedOption);
#else
_contents_array = NSZoneCalloc([self zone], _count, sizeof(id));
#endif
if (_contents_array == 0)
{
[NSException raise: NSMallocException
@ -497,7 +507,11 @@ static Class GSInlineArrayClass;
{
cap = 1;
}
#if GS_WITH_GC
_contents_array = NSAllocateCollectable(sizeof(id)*cap, NSScannedOption);
#else
_contents_array = NSZoneMalloc([self zone], sizeof(id)*cap);
#endif
_capacity = cap;
_grow_factor = cap > 1 ? cap/2 : 1;
return self;
@ -1074,7 +1088,7 @@ static Class GSInlineArrayClass;
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &c];
a = (id)NSAllocateObject(GSArrayClass, 0, GSObjCZone(self));
a->_contents_array = NSZoneMalloc(GSObjCZone(self), sizeof(id)*c);
a->_contents_array = NSAllocateCollectable(sizeof(id)*c, NSScannedOption);
#else
GSInlineArray *a;

View file

@ -275,7 +275,7 @@ static void _setup(void)
NSMutableArray *a;
NSDictionary *d;
GSIMapInitWithZoneAndCapacity(&attrMap, NSDefaultMallocZone(), 32);
GSIMapInitWithZoneAndCapacity(&attrMap, GSScannedMallocZone(), 32);
infSel = @selector(newWithZone:value:at:);
addSel = @selector(addObject:);

View file

@ -183,7 +183,11 @@
/* Designated initialiser */
- (id) initWithCapacity: (unsigned)cap
{
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), cap);
#else
GSIMapInitWithZoneAndCapacity(&map, [self zone], cap);
#endif
return self;
}
@ -199,7 +203,11 @@
(*imp)(aCoder, sel, utype, &count);
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), count);
#else
GSIMapInitWithZoneAndCapacity(&map, [self zone], count);
#endif
while (count-- > 0)
{
(*imp)(aCoder, sel, otype, &value);

View file

@ -156,7 +156,11 @@ static SEL objSel;
[aCoder decodeValueOfObjCType: @encode(unsigned)
at: &count];
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), count);
#else
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
#endif
while (count-- > 0)
{
(*imp)(aCoder, sel, type, &key);
@ -172,7 +176,11 @@ static SEL objSel;
{
unsigned int i;
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), c);
#else
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), c);
#endif
for (i = 0; i < c; i++)
{
GSIMapNode node;
@ -214,7 +222,11 @@ static SEL objSel;
NSZone *z = GSObjCZone(self);
unsigned c = [other count];
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), c);
#else
GSIMapInitWithZoneAndCapacity(&map, z, c);
#endif
if (c > 0)
{
@ -366,7 +378,11 @@ static SEL objSel;
/* Designated initialiser */
- (id) initWithCapacity: (unsigned)cap
{
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), cap);
#else
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), cap);
#endif
return self;
}

View file

@ -227,7 +227,11 @@ static Class mutableSetClass;
(*imp)(aCoder, sel, @encode(unsigned), &count);
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), count);
#else
GSIMapInitWithZoneAndCapacity(&map, [self zone], count);
#endif
while (count-- > 0)
{
(*imp)(aCoder, sel, type, &value);
@ -242,7 +246,11 @@ static Class mutableSetClass;
{
unsigned i;
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), c);
#else
GSIMapInitWithZoneAndCapacity(&map, [self zone], c);
#endif
for (i = 0; i < c; i++)
{
GSIMapNode node;
@ -576,7 +584,11 @@ static Class mutableSetClass;
/* Designated initialiser */
- (id) initWithCapacity: (unsigned)cap
{
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), cap);
#else
GSIMapInitWithZoneAndCapacity(&map, [self zone], cap);
#endif
return self;
}

View file

@ -137,6 +137,9 @@ static Class NSMutableDataMallocClass;
/*
* Set up map tables.
*/
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
_clsMap = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t)*6);
_cIdMap = &_clsMap[1];
_uIdMap = &_clsMap[2];

View file

@ -949,6 +949,9 @@ static NSLock *cached_proxies_gate = nil;
*/
_requestQueue = [NSMutableArray new];
#if GS_WITH_GC
z = GSScannedMallocZone();
#endif
/*
* This maps request sequence numbers to the NSPortCoder objects representing
* replies arriving from the remote connection.

View file

@ -155,6 +155,9 @@ NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
return 0;
}
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
t = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t, zone, ((GSIMapTable)table)->nodeCount);
t->extra = ((GSIMapTable)table)->extra;
@ -213,6 +216,9 @@ NSCreateHashTableWithZone(
{
GSIMapTable table;
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
table = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(table, zone, capacity);
table->extra = callBacks;

View file

@ -809,6 +809,9 @@ static NSDictionary *makeReference(unsigned ref)
/*
* Set up map tables.
*/
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
_cIdMap = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t)*5);
_uIdMap = &_cIdMap[1];
_repMap = &_cIdMap[2];

View file

@ -207,6 +207,9 @@ NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
return 0;
}
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
t = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t, zone, ((GSIMapTable)table)->nodeCount);
t->extra.k = ((GSIMapTable)table)->extra.k;
@ -270,6 +273,9 @@ NSCreateMapTableWithZone(
{
GSIMapTable table;
#if GS_WITH_GC
zone = GSScannedMallocZone();
#endif
table = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(table, zone, capacity);
table->extra.k = keyCallBacks;

View file

@ -47,6 +47,8 @@
#define purgeCollected(X) (X)
#endif
static NSZone *_zone = 0;
/**
* Concrete class implementing NSNotification.
*/
@ -286,7 +288,7 @@ static Observation *obsNew(NCTable* t)
size = CHUNKSIZE * sizeof(Observation);
#if GS_WITH_GC
t->chunks[t->numChunks - 1]
= (Observation*)NSZoneMallocAtomic(NSDefaultMallocZone(), size);
= (Observation*)NSZoneMalloc(GSAtomicMallocZone(), size);
#else
t->chunks[t->numChunks - 1]
= (Observation*)NSZoneMalloc(NSDefaultMallocZone(), size);
@ -312,8 +314,8 @@ static GSIMapTable mapNew(NCTable *t)
{
GSIMapTable m;
m = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(m, NSDefaultMallocZone(), 2);
m = NSZoneMalloc(_zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(m, _zone, 2);
return m;
}
}
@ -399,16 +401,16 @@ static NCTable *newNCTable(void)
{
NCTable *t;
t = (NCTable*)NSZoneMalloc(NSDefaultMallocZone(), sizeof(NCTable));
t = (NCTable*)NSZoneMalloc(_zone, sizeof(NCTable));
memset((void*)t, '\0', sizeof(NCTable));
t->chunkIndex = CHUNKSIZE;
t->wildcard = ENDOBS;
t->nameless = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t->nameless, NSDefaultMallocZone(), 16);
t->nameless = NSZoneMalloc(_zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t->nameless, _zone, 16);
t->named = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t->named, NSDefaultMallocZone(), 128);
t->named = NSZoneMalloc(_zone, sizeof(GSIMapTable_t));
GSIMapInitWithZoneAndCapacity(t->named, _zone, 128);
// t->_lock = [GSLazyRecursiveLock new];
t->_lock = [NSRecursiveLock new];
@ -582,6 +584,11 @@ static NSNotificationCenter *default_center = nil;
{
if (self == [NSNotificationCenter class])
{
#if GS_WITH_GC
_zone = GSScannedMallocZone();
#else
_zone = NSDefaultMallocZone();
#endif
if (concrete == 0)
{
concrete = [GSNotification class];
@ -1001,7 +1008,7 @@ static NSNotificationCenter *default_center = nil;
/*
* Initialise static array to store copies of observers.
*/
GSIArrayInitWithZoneAndStaticCapacity(a, NSDefaultMallocZone(), 64, i);
GSIArrayInitWithZoneAndStaticCapacity(a, _zone, 64, i);
/*
* Lock the table of observations while we traverse it.

View file

@ -668,7 +668,14 @@ NSIncrementExtraRefCount(id anObject)
inline NSZone *
GSObjCZone(NSObject *object)
{
return 0;
/* If we have GC enabled, all objects are garbage collected and memory
* they allocate should generally be garbage collectable but not scanned
* for pointers.
* If an object wants to have memory which IS scanned for pointers by the
* garbage collector, it should use NSAllocateCollectable() to get it,
* rather than using the old zone based memory allocation.
*/
return GSAtomicMallocZone();
}
static void
@ -686,8 +693,10 @@ NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone)
{
id new;
int size;
GC_descr gc_type;
NSCAssert((CLS_ISCLASS(aClass)), @"Bad class for new object");
gc_type = (GC_descr)aClass->gc_object_type;
size = aClass->instance_size + extraBytes;
if (size % sizeof(void*) != 0)
{
@ -696,29 +705,20 @@ NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone)
*/
size += sizeof(void*) - size % sizeof(void*);
}
if (zone == GSAtomicMallocZone())
if (gc_type == 0)
{
new = NSZoneCalloc(zone, 1, size);
NSLog(@"No garbage collection information for '%s'",
GSNameFromClass(aClass));
}
else
{
GC_descr gc_type = (GC_descr)aClass->gc_object_type;
if (gc_type == 0)
{
new = NSZoneCalloc(zone, 1, size);
NSLog(@"No garbage collection information for '%s'",
GSNameFromClass(aClass));
}
else
{
new = GC_calloc_explicitly_typed(1, size, gc_type);
}
new = GC_calloc_explicitly_typed(1, size, gc_type);
}
if (new != nil)
{
memset(new, 0, size);
new->class_pointer = aClass;
if (get_imp(aClass, finalize_sel) != finalize_imp
&& __objc_responds_to(new, finalize_sel))

View file

@ -1709,6 +1709,9 @@ static IMP _xRefImp; /* Serialize a crossref. */
_eObjImp = [self methodForSelector: eObjSel];
_eValImp = [self methodForSelector: eValSel];
#if GS_WITH_GC
_zone = GSScannedMallocZone();
#endif
/*
* Set up map tables.
*/

View file

@ -723,7 +723,7 @@ static inline id parseQuotedString(pldata* pld)
return nil;
}
length = temp_length - shrink;
chars = NSZoneMalloc(NSDefaultMallocZone(), sizeof(unichar) * length);
chars = NSAllocateCollectable(sizeof(unichar) * length, 0);
escaped = 0;
hex = NO;
for (j = 0, k = 0; j < temp_length; j++)
@ -845,7 +845,7 @@ static inline id parseUnquotedString(pldata *pld)
}
length = pld->pos - start;
chars = NSZoneMalloc(NSDefaultMallocZone(), sizeof(unichar) * length);
chars = NSAllocateCollectable(sizeof(unichar) * length, 0);
for (i = 0; i < length; i++)
{
chars[i] = pld->ptr[start + i];
@ -1606,7 +1606,7 @@ PString(NSString *obj, NSMutableData *output)
}
else
{
ustring = NSZoneMalloc(NSDefaultMallocZone(), length*sizeof(unichar));
ustring = NSAllocateCollectable(sizeof(unichar) * length, 0);
}
end = &ustring[length];
[obj getCharacters: ustring];
@ -1747,7 +1747,7 @@ XString(NSString* obj, NSMutableData *output)
unsigned rpos;
unsigned wpos;
base = NSZoneMalloc(NSDefaultMallocZone(), end * sizeof(unichar));
base = NSAllocateCollectable(sizeof(unichar) * end, 0);
[obj getCharacters: base];
for (len = rpos = 0; rpos < end; rpos++)
{
@ -1779,7 +1779,7 @@ XString(NSString* obj, NSMutableData *output)
break;
}
}
map = NSZoneMalloc(NSDefaultMallocZone(), len * sizeof(unichar));
map = NSAllocateCollectable(sizeof(unichar) * len, 0);
for (wpos = rpos = 0; rpos < end; rpos++)
{
c = base[rpos];
@ -3151,7 +3151,7 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
char *buffer;
len = [self readCountAt: &counter];
buffer = NSZoneMalloc(NSDefaultMallocZone(), len+1);
buffer = NSAllocateCollectable(len + 1, 0);
[data getBytes: buffer range: NSMakeRange(counter, len)];
buffer[len] = '\0';
if (mutability == NSPropertyListMutableContainersAndLeaves)
@ -3196,7 +3196,7 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
unichar *buffer;
len = [self readCountAt: &counter];
buffer = NSZoneMalloc(NSDefaultMallocZone(), sizeof(unichar)*len);
buffer = NSAllocateCollectable(sizeof(unichar) * len, 0);
[data getBytes: buffer range: NSMakeRange(counter, sizeof(unichar)*len)];
for (i = 0; i < len; i++)
@ -3265,7 +3265,7 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
id *objects;
len = [self readCountAt: &counter];
objects = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id) * len);
objects = NSAllocateCollectable(sizeof(id) * len, NSScannedOption);
for (i = 0; i < len; i++)
{
@ -3330,8 +3330,8 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
id *values;
len = [self readCountAt: &counter];
keys = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id)*len);
values = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id)*len);
keys = NSAllocateCollectable(sizeof(id) * len * 2, NSScannedOption);
values = keys + len;
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
@ -3359,7 +3359,6 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
forKeys: keys
count: len];
}
NSZoneFree(NSDefaultMallocZone(), values);
NSZoneFree(NSDefaultMallocZone(), keys);
}
else

View file

@ -157,7 +157,11 @@ initSerializerInfo(_NSSerializerInfo* info, NSMutableData *d, BOOL u)
(*info->appImp)(d, appSel, &info->shouldUnique, 1);
if (u)
{
#if GS_WITH_GC
GSIMapInitWithZoneAndCapacity(&info->map, GSScannedMallocZone(), 16);
#else
GSIMapInitWithZoneAndCapacity(&info->map, NSDefaultMallocZone(), 16);
#endif
info->count = 0;
}
}

View file

@ -405,10 +405,6 @@ static NSZone default_zone =
default_check, default_lookup, default_stats, DEFBLOCK, @"default", 0
};
/* Default zone. Name is hopelessly long so that no one will ever
want to use it. ;) */
NSZone* __nszone_private_hidden_default_zone = &default_zone;
/*
* Lists of zones to be used to determine if a pointer is in a zone.
*/
@ -1739,6 +1735,17 @@ NSSetZoneName (NSZone *zone, NSString *name)
[gnustep_global_lock unlock];
}
void *
NSAllocateCollectable(NSUInteger size, NSUInteger options)
{
return NSZoneCalloc(NSDefaultMallocZone(), 1, size);
}
void *
NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options)
{
return NSZoneRealloc(NSDefaultMallocZone(), ptr, size);
}
#else
#include <gc.h>
@ -1752,14 +1759,290 @@ static NSZone default_zone =
{
0, 0, 0, 0, 0, 0, 0, 0, @"default", 0
};
NSZone* __nszone_private_hidden_default_zone = &default_zone;
static NSZone atomic_zone =
{
0, 0, 0, 0, 0, 0, 0, 0, @"default", 0
};
NSZone* __nszone_private_hidden_atomic_zone = &atomic_zone;
static NSZone scanned_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);
}
else
{
ptr = (void*)GC_MALLOC(size);
}
}
else
{
if (options & NSCollectorDisabledOption)
{
ptr = (void*)calloc(1, size);
}
else
{
ptr = (void*)GC_MALLOC_ATOMIC(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
#ifndef GS_WITH_GC
#define GS_WITH_GC 0
#endif
#if GS_WITH_GC
#include <gc.h>
NSZone*
NSCreateZone (size_t start, size_t gran, BOOL canFree)
{
return &default_zone;
}
NSZone*
NSDefaultMallocZone (void)
{
return &default_zone;
}
NSZone*
GSAtomicMallocZone (void)
{
return &atomic_zone;
}
NSZone*
GSScannedMallocZone (void)
{
return &scanned_zone;
}
NSZone*
NSZoneFromPointer (void *ptr)
{
return &default_zone;
}
void*
NSZoneMalloc (NSZone *zone, size_t size)
{
void *ptr;
if (zone == GSAtomicMallocZone())
ptr = (void*)GC_MALLOC_ATOMIC(size);
else if (zone == GSScannedMallocZone())
ptr = (void*)GC_MALLOC(size);
else
ptr = (void*)malloc(size);
if (ptr == 0)
ptr = GSOutOfMemory(size, YES);
return ptr;
}
void*
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
{
size_t size = elems * bytes;
void *ptr;
if (zone == &atomic_zone)
ptr = (void*)GC_MALLOC_ATOMIC(size);
else if (zone == &scanned_zone)
ptr = (void*)GC_MALLOC(size);
else
ptr = (void*)malloc(size);
if (ptr == 0)
ptr = GSOutOfMemory(size, NO);
memset(ptr, '\0', size);
return ptr;
}
void*
NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
{
if (GC_base(ptr) != 0)
{
ptr = GC_REALLOC(ptr, size);
}
else
{
ptr = realloc(ptr, size);
}
if (ptr == 0)
GSOutOfMemory(size, NO);
return ptr;
}
void
NSRecycleZone (NSZone *zone)
{
}
void
NSZoneFree (NSZone *zone, void *ptr)
{
if (GC_base(ptr) != 0)
{
GC_FREE(ptr);
}
else
{
free(ptr);
}
}
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;
}
#else /* GS_WITH_GC */
NSZone*
NSDefaultMallocZone (void)
{
return &default_zone;
}
NSZone*
GSAtomicMallocZone (void)
{
return &default_zone;
}
NSZone*
GSScannedMallocZone (void)
{
return &default_zone;
}
void*
NSZoneMalloc (NSZone *zone, size_t size)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->malloc)(zone, size);
}
void*
NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->realloc)(zone, ptr, size);
}
void
NSRecycleZone (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
(zone->recycle)(zone);
}
void
NSZoneFree (NSZone *zone, void *ptr)
{
if (!zone)
zone = NSDefaultMallocZone();
(zone->free)(zone, ptr);
}
NSString*
NSZoneName (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return zone->name;
}
BOOL
NSZoneCheck (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->check)(zone);
}
struct NSZoneStats
NSZoneStats (NSZone *zone)
{
if (!zone)
zone = NSDefaultMallocZone();
return (zone->stats)(zone);
}
#endif /* GS_WITH_GC */