mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 00:30:53 +00:00
Preliminary changes for GC
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3612 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cf2322e4cf
commit
8636aa3eb4
4 changed files with 224 additions and 23 deletions
|
@ -192,6 +192,15 @@ extern NSRecursiveLock *gnustep_global_lock;
|
||||||
- read: (TypedStream*)aStream;
|
- read: (TypedStream*)aStream;
|
||||||
- write: (TypedStream*)aStream;
|
- write: (TypedStream*)aStream;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol for garbage collection finalization - same as libFoundation
|
||||||
|
* for compatibility.
|
||||||
|
*/
|
||||||
|
@protocol GCFinalization
|
||||||
|
- (void) gcFinalize;
|
||||||
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Foundation/NSDate.h>
|
#include <Foundation/NSDate.h>
|
||||||
|
@ -210,8 +219,22 @@ extern NSRecursiveLock *gnustep_global_lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RETAIN(), RELEASE(), and AUTORELEASE() are placeholders for the
|
* RETAIN(), RELEASE(), and AUTORELEASE() are placeholders for the
|
||||||
* (possible) future day when we have garbage collecting.
|
* future day when we have garbage collecting.
|
||||||
*/
|
*/
|
||||||
|
#ifndef GS_WITH_GC
|
||||||
|
#define GS_WITH_GC 0
|
||||||
|
#endif
|
||||||
|
#if GS_WITH_GC
|
||||||
|
|
||||||
|
#define RETAIN(object) ((id)object)
|
||||||
|
#define RELEASE(object)
|
||||||
|
#define AUTORELEASE(object) ((id)object)
|
||||||
|
|
||||||
|
#define ASSIGN(object,value) (object = value)
|
||||||
|
#define DESTROY(object) (object = nil)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#define RETAIN(object) [object retain]
|
#define RETAIN(object) [object retain]
|
||||||
#define RELEASE(object) [object release]
|
#define RELEASE(object) [object release]
|
||||||
#define AUTORELEASE(object) [object autorelease]
|
#define AUTORELEASE(object) [object autorelease]
|
||||||
|
@ -241,5 +264,6 @@ if (value != object) \
|
||||||
* object later.
|
* object later.
|
||||||
*/
|
*/
|
||||||
#define DESTROY(object) ([object release], object = nil)
|
#define DESTROY(object) ([object release], object = nil)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */
|
#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */
|
||||||
|
|
|
@ -23,16 +23,12 @@
|
||||||
#ifndef __NSZone_h_GNUSTEP_BASE_INCLUDE
|
#ifndef __NSZone_h_GNUSTEP_BASE_INCLUDE
|
||||||
#define __NSZone_h_GNUSTEP_BASE_INCLUDE
|
#define __NSZone_h_GNUSTEP_BASE_INCLUDE
|
||||||
|
|
||||||
|
|
||||||
#include <objc/objc.h>
|
#include <objc/objc.h>
|
||||||
|
|
||||||
|
|
||||||
@class NSString;
|
@class NSString;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _NSZone NSZone;
|
typedef struct _NSZone NSZone;
|
||||||
|
|
||||||
|
|
||||||
/* The members are the same as the structure mstats which is in the
|
/* The members are the same as the structure mstats which is in the
|
||||||
GNU C library. */
|
GNU C library. */
|
||||||
struct NSZoneStats
|
struct NSZoneStats
|
||||||
|
@ -60,19 +56,93 @@ struct _NSZone
|
||||||
NSZone *next;
|
NSZone *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *GSOutOfMemory(size_t size, BOOL retry);
|
||||||
|
|
||||||
|
#ifndef GS_WITH_GC
|
||||||
|
#define GS_WITH_GC 0
|
||||||
|
#endif
|
||||||
|
#if GS_WITH_GC
|
||||||
|
|
||||||
|
#include <gc.h>
|
||||||
|
|
||||||
|
extern inline NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree)
|
||||||
|
{ return 0; }
|
||||||
|
|
||||||
|
extern inline NSZone* NSDefaultMallocZone (void)
|
||||||
|
{ return 0; }
|
||||||
|
|
||||||
|
extern inline NSZone* NSZoneFromPointer (void *ptr)
|
||||||
|
{ return 0; }
|
||||||
|
|
||||||
|
extern inline void* NSZoneMalloc (NSZone *zone, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = (void*)GC_MALLOC(size);
|
||||||
|
|
||||||
|
if (ptr == 0)
|
||||||
|
ptr = GSOutOfMemory(size, YES);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void* NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
|
||||||
|
{
|
||||||
|
size_t size = elems * bytes;
|
||||||
|
void *ptr = (void*)GC_MALLOC(size);
|
||||||
|
|
||||||
|
void *ptr = (void*)GC_MALLOC(size, YES);
|
||||||
|
if (ptr == 0)
|
||||||
|
ptr = GSOutOfMemory(size);
|
||||||
|
memset(ptr, '\0', size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void* NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
ptr = GC_REALLOC(ptr, size);
|
||||||
|
if (ptr == 0)
|
||||||
|
GSOutOfMemory(size, NO);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void NSRecycleZone (NSZone *zone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void NSZoneFree (NSZone *zone, void *ptr)
|
||||||
|
{
|
||||||
|
GC_FREE(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void NSSetZoneName (NSZone *zone, NSString *name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline NSString* NSZoneName (NSZone *zone)
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline BOOL NSZoneCheck (NSZone *zone)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline struct NSZoneStats NSZoneStats (NSZone *zone)
|
||||||
|
{
|
||||||
|
struct NSZoneStats stats = { 0 };
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* GS_WITH_GC */
|
||||||
|
|
||||||
/* Default zone. Name is hopelessly long so that no one will ever
|
/* Default zone. Name is hopelessly long so that no one will ever
|
||||||
want to use it. ;) Private variable. */
|
want to use it. ;) Private variable. */
|
||||||
extern NSZone* __nszone_private_hidden_default_zone;
|
extern NSZone* __nszone_private_hidden_default_zone;
|
||||||
|
|
||||||
|
|
||||||
extern NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree);
|
extern NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree);
|
||||||
|
|
||||||
extern inline NSZone* NSDefaultMallocZone (void)
|
extern inline NSZone* NSDefaultMallocZone (void)
|
||||||
{ return __nszone_private_hidden_default_zone; }
|
{ return __nszone_private_hidden_default_zone; }
|
||||||
|
|
||||||
extern void NSSetDefaultMallocZone (NSZone *zone); // Not in OpenStep
|
|
||||||
|
|
||||||
extern NSZone* NSZoneFromPointer (void *ptr);
|
extern NSZone* NSZoneFromPointer (void *ptr);
|
||||||
|
|
||||||
extern inline void* NSZoneMalloc (NSZone *zone, size_t size)
|
extern inline void* NSZoneMalloc (NSZone *zone, size_t size)
|
||||||
|
@ -108,4 +178,6 @@ extern inline struct NSZoneStats NSZoneStats (NSZone *zone)
|
||||||
{ if (!zone) zone = NSDefaultMallocZone();
|
{ if (!zone) zone = NSDefaultMallocZone();
|
||||||
return (zone->stats)(zone); }
|
return (zone->stats)(zone); }
|
||||||
|
|
||||||
|
#endif /* GS_WITH_GC */
|
||||||
|
|
||||||
#endif /* not __NSZone_h_GNUSTEP_BASE_INCLUDE */
|
#endif /* not __NSZone_h_GNUSTEP_BASE_INCLUDE */
|
||||||
|
|
|
@ -100,8 +100,10 @@ void _fastBuildCache()
|
||||||
* correct zone to free memory very fast.
|
* correct zone to free memory very fast.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if GS_WITH_GC == 0
|
||||||
#define REFCNT_LOCAL 1
|
#define REFCNT_LOCAL 1
|
||||||
#define CACHE_ZONE 1
|
#define CACHE_ZONE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
||||||
|
|
||||||
|
@ -140,6 +142,22 @@ typedef struct obj_layout *obj;
|
||||||
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
||||||
|
|
||||||
|
|
||||||
|
#if GS_WITH_GC
|
||||||
|
|
||||||
|
void
|
||||||
|
NSIncrementExtraRefCount(id anObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#define NSIncrementExtraRefCount(X)
|
||||||
|
BOOL
|
||||||
|
NSDecrementExtraRefCountWasZero(id anObject)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
#define NSDecrementExtraRefCountWasZero(X) NO
|
||||||
|
|
||||||
|
#else /* GS_WITH_GC */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now do conditional compilation of reference count functions
|
* Now do conditional compilation of reference count functions
|
||||||
* depending on whether we are using local or global counting.
|
* depending on whether we are using local or global counting.
|
||||||
|
@ -226,12 +244,72 @@ extraRefCount (id anObject)
|
||||||
|
|
||||||
#endif /* defined(REFCNT_LOCAL) */
|
#endif /* defined(REFCNT_LOCAL) */
|
||||||
|
|
||||||
|
#endif /* GS_WITH_GC */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now do conditional compilation of memory allocation functions
|
* Now do conditional compilation of memory allocation functions
|
||||||
* depending on what information (if any) we are storing before
|
* depending on what information (if any) we are storing before
|
||||||
* the start of each object.
|
* the start of each object.
|
||||||
*/
|
*/
|
||||||
|
#if GS_WITH_GC
|
||||||
|
|
||||||
|
inline NSZone *
|
||||||
|
fastZone(NSObject *object)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
GSFinalize(void* object, void* data)
|
||||||
|
{
|
||||||
|
[(id)object gcFinalize];
|
||||||
|
|
||||||
|
/* Set the class of anObject to FREED_OBJECT. The further messages to this
|
||||||
|
object will cause an error to occur. */
|
||||||
|
((id)object)->class_pointer = __freedObjectClass;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
GSDebugAllocationRemove(((id)object)->class_pointer);
|
||||||
|
#endif
|
||||||
|
((id)object)->class_pointer = (void*) 0xdeadface;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NSObject *
|
||||||
|
NSAllocateObject (Class aClass, unsigned extraBytes, NSZone *zone)
|
||||||
|
{
|
||||||
|
id new = nil;
|
||||||
|
int size = aClass->instance_size + extraBytes;
|
||||||
|
if (CLS_ISCLASS (aClass))
|
||||||
|
new = NSZoneMalloc (zone, size);
|
||||||
|
if (new != nil)
|
||||||
|
{
|
||||||
|
memset (new, 0, size);
|
||||||
|
new->class_pointer = aClass;
|
||||||
|
}
|
||||||
|
if ([new respondsToSelector: @selector(gcFinalize)])
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
/*
|
||||||
|
* We only do allocation counting for objects that can be
|
||||||
|
* finalised - for other objects we have no way of decrementing
|
||||||
|
* the count when the object is collected.
|
||||||
|
*/
|
||||||
|
GSDebugAllocationAdd(aClass);
|
||||||
|
#endif
|
||||||
|
GC_REGISTER_FINALIZER (new, GSFinalize, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
NSDeallocateObject(NSObject *anObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* GS_WITH_GC */
|
||||||
|
|
||||||
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
||||||
|
|
||||||
#if defined(CACHE_ZONE)
|
#if defined(CACHE_ZONE)
|
||||||
|
@ -239,9 +317,9 @@ extraRefCount (id anObject)
|
||||||
inline NSZone *
|
inline NSZone *
|
||||||
fastZone(NSObject *object)
|
fastZone(NSObject *object)
|
||||||
{
|
{
|
||||||
if (fastClass(object) == _fastCls._NXConstantString)
|
if (fastClass(object) == _fastCls._NXConstantString)
|
||||||
return NSDefaultMallocZone();
|
return NSDefaultMallocZone();
|
||||||
return ((obj)object)[-1].zone;
|
return ((obj)object)[-1].zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* defined(CACHE_ZONE) */
|
#else /* defined(CACHE_ZONE) */
|
||||||
|
@ -249,9 +327,9 @@ fastZone(NSObject *object)
|
||||||
inline NSZone *
|
inline NSZone *
|
||||||
fastZone(NSObject *object)
|
fastZone(NSObject *object)
|
||||||
{
|
{
|
||||||
if (fastClass(object) == _fastCls._NXConstantString)
|
if (fastClass(object) == _fastCls._NXConstantString)
|
||||||
return NSDefaultMallocZone();
|
return NSDefaultMallocZone();
|
||||||
return NSZoneFromPointer(&((obj)object)[-1]);
|
return NSZoneFromPointer(&((obj)object)[-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(CACHE_ZONE) */
|
#endif /* defined(CACHE_ZONE) */
|
||||||
|
@ -345,11 +423,17 @@ NSDeallocateObject(NSObject *anObject)
|
||||||
|
|
||||||
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
||||||
|
|
||||||
|
#endif /* GS_WITH_GC */
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
|
NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
|
||||||
{
|
{
|
||||||
return (!requestedZone || requestedZone == NSDefaultMallocZone()
|
#if GS_WITH_GC
|
||||||
|
return YES;
|
||||||
|
#else
|
||||||
|
return (!requestedZone || requestedZone == NSDefaultMallocZone()
|
||||||
|| fastZone(anObject) == requestedZone);
|
|| fastZone(anObject) == requestedZone);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -630,6 +714,7 @@ static BOOL double_release_check_enabled = NO;
|
||||||
|
|
||||||
- autorelease
|
- autorelease
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC == 0
|
||||||
if (double_release_check_enabled)
|
if (double_release_check_enabled)
|
||||||
{
|
{
|
||||||
unsigned release_count;
|
unsigned release_count;
|
||||||
|
@ -643,6 +728,7 @@ static BOOL double_release_check_enabled = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
|
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
|
||||||
|
#endif
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,6 +867,7 @@ static BOOL double_release_check_enabled = NO;
|
||||||
|
|
||||||
- (oneway void) release
|
- (oneway void) release
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC == 0
|
||||||
if (double_release_check_enabled)
|
if (double_release_check_enabled)
|
||||||
{
|
{
|
||||||
unsigned release_count;
|
unsigned release_count;
|
||||||
|
@ -793,7 +880,7 @@ static BOOL double_release_check_enabled = NO;
|
||||||
|
|
||||||
if (NSDecrementExtraRefCountWasZero(self))
|
if (NSDecrementExtraRefCountWasZero(self))
|
||||||
[self dealloc];
|
[self dealloc];
|
||||||
return;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (oneway void) release
|
+ (oneway void) release
|
||||||
|
@ -815,7 +902,9 @@ static BOOL double_release_check_enabled = NO;
|
||||||
|
|
||||||
- retain
|
- retain
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC == 0
|
||||||
NSIncrementExtraRefCount(self);
|
NSIncrementExtraRefCount(self);
|
||||||
|
#endif
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,7 +915,11 @@ static BOOL double_release_check_enabled = NO;
|
||||||
|
|
||||||
- (unsigned) retainCount
|
- (unsigned) retainCount
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
return UINT_MAX;
|
||||||
|
#else
|
||||||
return extraRefCount(self) + 1;
|
return extraRefCount(self) + 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (unsigned) retainCount
|
+ (unsigned) retainCount
|
||||||
|
|
|
@ -92,6 +92,22 @@
|
||||||
#include <Foundation/NSLock.h>
|
#include <Foundation/NSLock.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to get more memory - the normal process has failed.
|
||||||
|
* If we can't do anything, bomb out.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
GSOutOfMemory(size_t size, BOOL retry)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* It would be nice to raise an exception - but how can we if there is
|
||||||
|
* no memory available?
|
||||||
|
*/
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GS_WITH_GC == 0
|
||||||
|
|
||||||
/* Alignment */
|
/* Alignment */
|
||||||
#define ALIGN ((__alignof__(double) < 8) ? 8 : __alignof__(double))
|
#define ALIGN ((__alignof__(double) < 8) ? 8 : __alignof__(double))
|
||||||
#define MINGRAN 256 /* Minimum granularity. */
|
#define MINGRAN 256 /* Minimum granularity. */
|
||||||
|
@ -1659,13 +1675,6 @@ NSDefaultMallocZone (void)
|
||||||
return __nszone_private_hidden_default_zone;
|
return __nszone_private_hidden_default_zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in OpenStep. */
|
|
||||||
void
|
|
||||||
NSSetDefaultMallocZone (NSZone *zone)
|
|
||||||
{
|
|
||||||
__nszone_private_hidden_default_zone = zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void*
|
inline void*
|
||||||
NSZoneMalloc (NSZone *zone, size_t size)
|
NSZoneMalloc (NSZone *zone, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -1743,3 +1752,6 @@ NSZoneStats (NSZone *zone)
|
||||||
zone = NSDefaultMallocZone();
|
zone = NSDefaultMallocZone();
|
||||||
return (zone->stats)(zone);
|
return (zone->stats)(zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* GS_WITH_GC */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue