mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +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
f14aaf6268
commit
cd1e3d393f
4 changed files with 224 additions and 23 deletions
|
@ -192,6 +192,15 @@ extern NSRecursiveLock *gnustep_global_lock;
|
|||
- read: (TypedStream*)aStream;
|
||||
- write: (TypedStream*)aStream;
|
||||
@end
|
||||
|
||||
/*
|
||||
* Protocol for garbage collection finalization - same as libFoundation
|
||||
* for compatibility.
|
||||
*/
|
||||
@protocol GCFinalization
|
||||
- (void) gcFinalize;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
#include <Foundation/NSDate.h>
|
||||
|
@ -210,8 +219,22 @@ extern NSRecursiveLock *gnustep_global_lock;
|
|||
|
||||
/*
|
||||
* 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 RELEASE(object) [object release]
|
||||
#define AUTORELEASE(object) [object autorelease]
|
||||
|
@ -241,5 +264,6 @@ if (value != object) \
|
|||
* object later.
|
||||
*/
|
||||
#define DESTROY(object) ([object release], object = nil)
|
||||
#endif
|
||||
|
||||
#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
|
@ -23,16 +23,12 @@
|
|||
#ifndef __NSZone_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NSZone_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
|
||||
@class NSString;
|
||||
|
||||
|
||||
typedef struct _NSZone NSZone;
|
||||
|
||||
|
||||
/* The members are the same as the structure mstats which is in the
|
||||
GNU C library. */
|
||||
struct NSZoneStats
|
||||
|
@ -60,19 +56,93 @@ struct _NSZone
|
|||
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
|
||||
want to use it. ;) Private variable. */
|
||||
extern NSZone* __nszone_private_hidden_default_zone;
|
||||
|
||||
|
||||
extern NSZone* NSCreateZone (size_t start, size_t gran, BOOL canFree);
|
||||
|
||||
extern inline NSZone* NSDefaultMallocZone (void)
|
||||
{ return __nszone_private_hidden_default_zone; }
|
||||
|
||||
extern void NSSetDefaultMallocZone (NSZone *zone); // Not in OpenStep
|
||||
|
||||
extern NSZone* NSZoneFromPointer (void *ptr);
|
||||
|
||||
extern inline void* NSZoneMalloc (NSZone *zone, size_t size)
|
||||
|
@ -108,4 +178,6 @@ extern inline struct NSZoneStats NSZoneStats (NSZone *zone)
|
|||
{ if (!zone) zone = NSDefaultMallocZone();
|
||||
return (zone->stats)(zone); }
|
||||
|
||||
#endif /* GS_WITH_GC */
|
||||
|
||||
#endif /* not __NSZone_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
|
@ -100,8 +100,10 @@ void _fastBuildCache()
|
|||
* correct zone to free memory very fast.
|
||||
*/
|
||||
|
||||
#if GS_WITH_GC == 0
|
||||
#define REFCNT_LOCAL 1
|
||||
#define CACHE_ZONE 1
|
||||
#endif
|
||||
|
||||
#if defined(REFCNT_LOCAL) || defined(CACHE_ZONE)
|
||||
|
||||
|
@ -140,6 +142,22 @@ typedef struct obj_layout *obj;
|
|||
#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
|
||||
* depending on whether we are using local or global counting.
|
||||
|
@ -226,12 +244,72 @@ extraRefCount (id anObject)
|
|||
|
||||
#endif /* defined(REFCNT_LOCAL) */
|
||||
|
||||
#endif /* GS_WITH_GC */
|
||||
|
||||
|
||||
/*
|
||||
* Now do conditional compilation of memory allocation functions
|
||||
* depending on what information (if any) we are storing before
|
||||
* 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(CACHE_ZONE)
|
||||
|
@ -239,9 +317,9 @@ extraRefCount (id anObject)
|
|||
inline NSZone *
|
||||
fastZone(NSObject *object)
|
||||
{
|
||||
if (fastClass(object) == _fastCls._NXConstantString)
|
||||
return NSDefaultMallocZone();
|
||||
return ((obj)object)[-1].zone;
|
||||
if (fastClass(object) == _fastCls._NXConstantString)
|
||||
return NSDefaultMallocZone();
|
||||
return ((obj)object)[-1].zone;
|
||||
}
|
||||
|
||||
#else /* defined(CACHE_ZONE) */
|
||||
|
@ -249,9 +327,9 @@ fastZone(NSObject *object)
|
|||
inline NSZone *
|
||||
fastZone(NSObject *object)
|
||||
{
|
||||
if (fastClass(object) == _fastCls._NXConstantString)
|
||||
return NSDefaultMallocZone();
|
||||
return NSZoneFromPointer(&((obj)object)[-1]);
|
||||
if (fastClass(object) == _fastCls._NXConstantString)
|
||||
return NSDefaultMallocZone();
|
||||
return NSZoneFromPointer(&((obj)object)[-1]);
|
||||
}
|
||||
|
||||
#endif /* defined(CACHE_ZONE) */
|
||||
|
@ -345,11 +423,17 @@ NSDeallocateObject(NSObject *anObject)
|
|||
|
||||
#endif /* defined(REFCNT_LOCAL) || defined(CACHE_ZONE) */
|
||||
|
||||
#endif /* GS_WITH_GC */
|
||||
|
||||
BOOL
|
||||
NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
|
||||
{
|
||||
return (!requestedZone || requestedZone == NSDefaultMallocZone()
|
||||
#if GS_WITH_GC
|
||||
return YES;
|
||||
#else
|
||||
return (!requestedZone || requestedZone == NSDefaultMallocZone()
|
||||
|| fastZone(anObject) == requestedZone);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -630,6 +714,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
- autorelease
|
||||
{
|
||||
#if GS_WITH_GC == 0
|
||||
if (double_release_check_enabled)
|
||||
{
|
||||
unsigned release_count;
|
||||
|
@ -643,6 +728,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
}
|
||||
|
||||
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -781,6 +867,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
- (oneway void) release
|
||||
{
|
||||
#if GS_WITH_GC == 0
|
||||
if (double_release_check_enabled)
|
||||
{
|
||||
unsigned release_count;
|
||||
|
@ -793,7 +880,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
if (NSDecrementExtraRefCountWasZero(self))
|
||||
[self dealloc];
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (oneway void) release
|
||||
|
@ -815,7 +902,9 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
- retain
|
||||
{
|
||||
#if GS_WITH_GC == 0
|
||||
NSIncrementExtraRefCount(self);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -826,7 +915,11 @@ static BOOL double_release_check_enabled = NO;
|
|||
|
||||
- (unsigned) retainCount
|
||||
{
|
||||
#if GS_WITH_GC
|
||||
return UINT_MAX;
|
||||
#else
|
||||
return extraRefCount(self) + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (unsigned) retainCount
|
||||
|
|
|
@ -92,6 +92,22 @@
|
|||
#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 */
|
||||
#define ALIGN ((__alignof__(double) < 8) ? 8 : __alignof__(double))
|
||||
#define MINGRAN 256 /* Minimum granularity. */
|
||||
|
@ -1659,13 +1675,6 @@ NSDefaultMallocZone (void)
|
|||
return __nszone_private_hidden_default_zone;
|
||||
}
|
||||
|
||||
/* Not in OpenStep. */
|
||||
void
|
||||
NSSetDefaultMallocZone (NSZone *zone)
|
||||
{
|
||||
__nszone_private_hidden_default_zone = zone;
|
||||
}
|
||||
|
||||
inline void*
|
||||
NSZoneMalloc (NSZone *zone, size_t size)
|
||||
{
|
||||
|
@ -1743,3 +1752,6 @@ NSZoneStats (NSZone *zone)
|
|||
zone = NSDefaultMallocZone();
|
||||
return (zone->stats)(zone);
|
||||
}
|
||||
|
||||
#endif /* GS_WITH_GC */
|
||||
|
||||
|
|
Loading…
Reference in a new issue